Controller
<?php
declare(strict_types=1);
namespace Oms\Http\Controllers\Front;
use Illuminate\Auth\AuthManager;
use Illuminate\Contracts\View\View;
use Illuminate\Database\DatabaseManager;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\URL;
use Oms\Cart\CartFactory;
use Oms\Domain\Front\CustomerAuthentication\CustomerAuthentication;
use Oms\Domain\Front\CustomerMyPage\EditProfile\EditProfile;
use Oms\Domain\Front\CustomerMyPage\EditProfile\ProfileUpdater;
use Oms\Exceptions\OmsException;
use Oms\Http\Controllers\Controller;
use Oms\Http\Requests\Front\MyPage\UpdateProfileRequest;
use Oms\Models\ArticleTag;
use Oms\Models\Customer;
use Oms\Models\Order;
use Oms\Models\Prefecture;
use Oms\Models\Product;
use Oms\UseCase\Order\Exceptions\InvalidOrderException;
use Oms\UseCase\Order\GeneratePdfReceiptAction;
use PDF;
class MyPageController extends Controller
{
/** @var DatabaseManager */
protected $dbm;
/** @var CustomerAuthentication */
protected $auth;
/**
* MyPageController constructor.
*
* @param DatabaseManager $databaseManager
* @param CustomerAuthentication $auth
*/
public function __construct(
DatabaseManager $databaseManager,
CustomerAuthentication $auth
) {
$this->dbm = $databaseManager;
$this->auth = $auth;
}
/**
* @param EditProfile $domain
* @param AuthManager $authManager
*
* @return View
*/
public function editProfile(EditProfile $domain, AuthManager $authManager): View
{
/** @var Customer $customer */
$customer = $domain->findCustomer($authManager->guard()->id());
$posts = Customer::POSTS;
$jobs = Customer::JOBS;
$prefectures = Prefecture::all()->pluck('name', 'id')->toArray();
$sexes = Customer::SEXES;
$mailmagaFlgs = Customer::MAILMAGA_FLAGS;
$articleTags = ArticleTag::all()->pluck('name', 'id')->toArray();
// 定期購読の購入フローに入ったことがある場合は会員情報の必須埋めを促す
$isNeedProfiling = session()->exists('subscribe.shopping');
$orders = $customer
->orders()
->with([
'paymentType',
'orderDetails',
])
->where('status', '<>', Order::DELETED)
->orderBy('id', 'desc')
->get();
// お届け先を変更できる注文が最低1件存在する場合、「お届け先変更」ボタンを表示する
$filteredOrder = $orders->first(function ($order) {
return $order->canEditDelivery();
});
$canEditDelivery = false;
if (!is_null($filteredOrder)) {
$canEditDelivery = true;
}
return view(
'front.mypages.profiles.edit',
compact(
'customer',
'posts',
'jobs',
'prefectures',
'sexes',
'mailmagaFlgs',
'articleTags',
'isNeedProfiling',
'canEditDelivery'
)
);
}
/**
* @param UpdateProfileRequest $request
* @param ProfileUpdater $service
* @param AuthManager $authManager
* @param CartFactory $cartFactory
*
* @return RedirectResponse
* @throws \Exception
*/
public function updateProfile(
UpdateProfileRequest $request,
ProfileUpdater $service,
AuthManager $authManager,
CartFactory $cartFactory
): RedirectResponse {
$this->dbm->beginTransaction();
try {
$service->update($authManager->guard()->id(), $request->all());
$this->dbm->commit();
} catch (OmsException $e) {
$this->dbm->rollBack();
}
// [購入フローから会員情報変更へ飛ばされたフラグ]がない場合は更新完了画面
if (!session()->exists('subscribe.shopping')) {
return redirect()->route('web.mypage.profile.complete');
}
session()->forget('subscribe.shopping');
// カートの商品を取得
$cart = $cartFactory->create();
$cartAll = $cart->all();
if (count($cartAll) === 0) {
// カートが空の場合は更新完了画面
return redirect()->route('web.mypage.profile.complete');
}
// 商品ごとの支払方法を取得
$productIds = $cartAll->pluck('product_id')->toArray();
$products = Product::find($productIds);
$product = $products->first();
if (is_null($product)) {
// カート内の商品情報が取得できなかった場合は更新完了画面
return redirect()->route('web.mypage.profile.complete');
}
if ($product->productType->isSubscription() || $product->productType->isYearly()) {
// 定期購読商品・年払い商品の場合は支払い方法選択画面
return redirect()->route('web.shopping.payment');
}
// それ以外はカート画面
return redirect()->route('web.cart');
}
/**
* @return View
*/
public function completeProfile(): View
{
return view('front.mypages.profiles.complete');
}
/**
* Download receipt pdf files.
*/
public function receipt(Request $request, GeneratePdfReceiptAction $generatePdfReceiptAction): Response
{
$id = (int)$request->route('orderId');
/** @var \Oms\Models\Order $order */
$order = Order::query()->findOrFail($id);
// フロントからのリクエストの場合、
// 他の顧客の受注の領収書をダウンロードさせない
$customer = $this->auth->customer();
if ($customer === null || !$order->isBelongsToCustomer($customer)) {
abort(404);
}
try {
return $generatePdfReceiptAction->handle($order)
->stream('ryoshusyo.pdf');
} catch (InvalidOrderException $e) {
Log::error($e->getMessage());
abort(400);
}
}
}
Updator
<?php
declare(strict_types=1);
namespace Oms\Domain\Front\CustomerMyPage\EditProfile;
use Oms\Domain\Front\CustomerMyPage\EditProfile\Entity\Birthday;
use Oms\Domain\Front\CustomerMyPage\EditProfile\Entity\FullName;
use Oms\Models\Interfaces\CustomerInterface;
use Oms\Models\Customer;
use Oms\Models\Prefecture;
use Stripe\Exception\ApiErrorException as StripeApiErrorException;
class ProfileUpdater
{
/** @var EditProfile */
protected $domain;
/**
* ProfileUpdater constructor.
*
* @param EditProfile $editProfile
*/
public function __construct(EditProfile $editProfile)
{
$this->domain = $editProfile;
}
/**
* @param int $id
* @param array $data
*
* @return CustomerInterface
* @throws StripeApiErrorException
*/
public function update(int $id, array $data): CustomerInterface
{
/**
* Customer Attributes
*/
$customerAttributes = [
'email' => strtolower($data['email']),
'name01' => $data['name01'],
'name02' => $data['name02'],
'kana01' => $data['kana01'],
'kana02' => $data['kana02'],
'company' => $data['company'],
'unit' => $data['unit'],
'post' => (int)$data['post'],
// 性別は個人情報として収集しない方針になったため常に「未回答」として保存する
'sex' => Customer::SEX_UNSELECTED,
'mailmaga_flg' => (bool)$data['mailmaga_flg'],
'job' => (int)$data['job'],
'birth' => null,
];
$customerAttributes['name'] = (new FullName($data['name01'], $data['name02']))->getFullName();
if ($data['raw_password']) {
$customerAttributes['password'] = $data['raw_password'];
}
$birthday = (new Birthday($data['year'], $data['month'], $data['day']))->getBirthday();
if ($birthday) {
$customerAttributes['birth'] = $birthday;
}
/**
* Address Attributes
*/
$addressAttributes = [
'customer_id' => $id,
'prefecture_id' => $data['prefecture_id'],
'country' => $data['country'] ?? '日本', // dont update on this feature.
'postcode' => $data['postcode'],
'city' => $data['city'],
'line1' => $data['line1'],
'tel' => $data['tel'],
'fax' => $data['fax'],
'sort' => 1, // 会員情報の住所は1
'name01' => $data['name01'],
'name02' => $data['name02'],
'kana01' => $data['kana01'],
'kana02' => $data['kana02'],
'company' => $data['company'],
'unit' => $data['unit'],
];
/**
* Stripe Customer Attributes
*/
$stripeCustomerAttributes = [
'email' => strtolower($data['email']),
];
$customer = $this->domain->findCustomer($id);
/**
* Tags
*/
$articleTags = $data['article_tags'] ?? [];
/**
* Status
*/
if ($customer->statusNotYetCustomerPlus()) {
$customerAttributes['status'] = $customer::STATUS_CUSTOMER_PLUS;
}
return $this->domain->update(
$id,
$customerAttributes,
$addressAttributes,
$stripeCustomerAttributes,
$articleTags
);
}
}
EditProfile
<?php
declare(strict_types=1);
namespace Oms\Domain\Front\CustomerMyPage\EditProfile;
use Oms\Domain\Integrations\BlastMail\BlastMailCustomerIntegrationInterface;
use Oms\Domain\Payments\Stripe\Customer\CustomerUpdation as StripeCustomerUpdation;
use Oms\Models\Interfaces\CustomerInterface;
use Oms\Repositories\Interfaces\AddressRepositoryInterface;
use Oms\Repositories\Interfaces\CustomerRepositoryInterface;
use Stripe\Exception\ApiErrorException as StripeApiErrorException;
class EditProfile
{
/** @var CustomerRepositoryInterface */
protected $customerRepository;
/** @var AddressRepositoryInterface */
protected $addressRepository;
/** @var StripeCustomerUpdation */
protected $stripeCustomerUpdation;
/** @var BlastMailCustomerIntegrationInterface */
protected $blastMailCustomerUpsertion;
public function __construct(
CustomerRepositoryInterface $customerRepository,
AddressRepositoryInterface $addressRepository,
StripeCustomerUpdation $stripeCustomerUpdation,
BlastMailCustomerIntegrationInterface $blastMailCustomerUpsertion
) {
$this->customerRepository = $customerRepository;
$this->addressRepository = $addressRepository;
$this->stripeCustomerUpdation = $stripeCustomerUpdation;
$this->blastMailCustomerUpsertion = $blastMailCustomerUpsertion;
}
/**
* @param int $customerId
*
* @return CustomerInterface
*/
public function findCustomer(int $customerId): CustomerInterface
{
return $this->customerRepository->find($customerId)->load(['address', 'articleTags']);
}
/**
* @param int $id
* @param array $customerAttributes
* @param array $addressAttributes
* @param array $stripeCustomerAttributes
* @param array $satoriCustomerAttributes
* @param array $articleTags
* @return CustomerInterface
* @throws StripeApiErrorException
*/
public function update(
int $id,
array $customerAttributes,
array $addressAttributes,
array $stripeCustomerAttributes,
array $articleTags = []
): CustomerInterface {
$customer = $this->findCustomer($id);
$this->customerRepository->update($customer, $customerAttributes);
// If address is null store address else update.
if ($customer->address) {
$this->addressRepository->update($customer->address, $addressAttributes);
} else {
$this->addressRepository->store($addressAttributes);
}
$customer->articleTags()->sync($articleTags);
$this->stripeCustomerUpdation->update($customer, $stripeCustomerAttributes);
// ブラストメール連携
$customer = $this->findCustomer($customer->id);
if (config('blastmail.integration_enable')) {
$this->blastMailCustomerUpsertion->integration($customer);
}
return $customer;
}
}
AppServiceProvider
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->registerInterfaces();
$this->registerServiceProviders();
$this->registerFacadeAliases();
}
/**
* Resister Repositories
*
* @return void
*/
public function registerInterfaces()
{
$this->app->bind(CustomerInterface::class, function (Application $app) {
return new Customer();
});
$this->app->bind(CustomerRepositoryInterface::class, function (Application $app) {
return new CustomerRepository(
$app->make(CustomerFactory::class),
$app->make(CustomerInterface::class)
);
});
$this->app->bind(AddressRepositoryInterface::class, function (Application $app) {
return new AddressRepository($app->make(AddressInterface::class));
});
}
Repository
<?php
declare(strict_types=1);
namespace Oms\Repositories;
use Oms\Models\Customer;
use Oms\Models\Factory\CustomerFactory;
use Oms\Models\Interfaces\CustomerInterface;
use Oms\Repositories\Exceptions\NotExistsCustomerException;
use Oms\Repositories\Interfaces\CustomerRepositoryInterface;
use Traversable;
class CustomerRepository implements CustomerRepositoryInterface
{
/** @var CustomerFactory */
protected $factory;
/** @var Customer */
protected $orm;
/**
* @inheritdoc
*/
public function __construct(CustomerFactory $factory, Customer $customer)
{
$this->factory = $factory;
$this->orm = $customer;
}
/**
* @param int $customerId
*
* @return CustomerInterface
* @throws NotExistsCustomerException
*/
public function find(int $customerId): CustomerInterface
{
$customer = $this->orm->find($customerId);
if (!$customer) {
throw new NotExistsCustomerException();
}
return $customer;
}
/**
* @inheritdoc
*/
public function findAll(): Traversable
{
return $this->orm->get();
}
/**
* @inheritdoc
*/
public function store(array $attributes): CustomerInterface
{
$customer = app(Customer::class);
return $this->factory->persist($customer, $attributes);
}
/**
* @param CustomerInterface $customer
* @param array $attributes
*
* @return CustomerInterface
* @throws NotExistsCustomerException
*/
public function update(CustomerInterface $customer, array $attributes): CustomerInterface
{
if (!$customer->exists) {
throw new NotExistsCustomerException();
}
$updatedCustomer = $this->factory->persist($customer, $attributes);
return $this->find($updatedCustomer->id);
}
/**
* @param CustomerInterface $customer
*
* @return void
* @throws NotExistsCustomerException
*/
public function remove(CustomerInterface $customer)
{
if (!$customer->exists) {
throw new NotExistsCustomerException();
}
$customer->delete();
}
/**
* @param $email
*
* @return \Illuminate\Database\Eloquent\Model|null|static
*/
public function findByEmail($email)
{
$customer = $this->orm->where('email', $email)->first();
if (!$customer) {
throw new NotExistsCustomerException();
}
return $customer;
}
}
factory
<?php
declare(strict_types=1);
namespace Oms\Models\Factory;
use Oms\Models\Customer;
use Oms\Models\Factory\FactoryInterface;
final class CustomerFactory implements FactoryInterface
{
/** @var Customer */
private $orm;
/**
* CustomerFactory constructor.
*
* @param Customer $customer
*/
public function __construct(Customer $customer)
{
$this->orm = $customer;
}
/**
* @param Customer $customer
* @param array $attributes
*
* @return Customer
*/
public function persist($customer, array $attributes): Customer
{
if (!$customer->exists) {
return $this->create($attributes);
}
return $this->update($customer, $attributes);
}
/**
* @param array $attributes
*
* @return Customer
*/
protected function create(array $attributes): Customer
{
$customer = $this->orm->fill($attributes);
$customer->save();
return $customer->refresh();
}
/**
* @param Customer $customer
* @param array $attributes
*
* @return Customer
*/
protected function update(Customer $customer, array $attributes): Customer
{
$customer->fill($attributes)->update();
return $customer->refresh();
}
}
パスワードリセット
Controller
<?php
declare(strict_types=1);
namespace Oms\Http\Controllers\Front;
use Illuminate\View\View;
use Illuminate\Database\DatabaseManager;
use Oms\Domain\Front\CustomerPassword\PasswordReset\PasswordUpdater;
use Oms\Exceptions\OmsException;
use Oms\Http\Controllers\Controller;
use Oms\Http\Requests\Front\Forgot\PasswordResetRequest;
class ResetPasswordController extends Controller
{
/** @var DatabaseManager */
protected $dbm;
// cookie name for memoried email
const MEMORIED_EMAIL_COOKIE_NAME = 'login_email';
/**
* Create a new controller instance.
*/
public function __construct(DatabaseManager $databaseManager)
{
$this->dbm = $databaseManager;
}
/**
* Display the password reset view for the given token.
*
* @return \Illuminate\View\View
*/
public function showResetForm(): View
{
$memoriedEmail = request()->cookie(static::MEMORIED_EMAIL_COOKIE_NAME);
return view('front.customers.reset-passwords.form', compact('memoriedEmail'), ['isOneColumn' => true]);
}
/**
* Reset the given customer's password.
*
* @param PasswordResetRequest $request
* @param PasswordUpdater $service
* @return \Illuminate\View\View
*/
public function reset(
PasswordResetRequest $request,
PasswordUpdater $service
): View {
$this->dbm->beginTransaction();
try {
$service->update($request['email']);
$this->dbm->commit();
} catch (OmsException $e) {
$this->dbm->rollBack();
}
return view('front.customers.reset-passwords.complete', ['isOneColumn' => true]);
}
}
Updator
<?php
declare(strict_types=1);
namespace Oms\Domain\Front\CustomerPassword\PasswordReset;
use Oms\Models\Interfaces\CustomerInterface;
class PasswordUpdater
{
/** @var PasswordUpdate */
protected $domain;
/**
* PasswordUpdater constructor.
*
* @param PasswordUpdate $passwordUpdate
*/
public function __construct(PasswordUpdate $passwordUpdate)
{
$this->domain = $passwordUpdate;
}
/**
* @param string $email
*
* @return CustomerInterface
*/
public function update(string $email): CustomerInterface
{
return $this->domain->update($email);
}
}
Updation Update
<?php
declare(strict_types=1);
namespace Oms\Domain\Front\CustomerPassword\PasswordReset;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Support\Str;
use Oms\Models\Interfaces\CustomerInterface;
use Oms\Repositories\Interfaces\CustomerRepositoryInterface;
class PasswordUpdate
{
/** @var CustomerRepositoryInterface */
protected $customerRepository;
/** @var Mailer */
protected $mailer;
/**
* PasswordUpdate constructor.
*
* @param Mailer $mailer
* @param CustomerRepositoryInterface $customerRepository
*/
public function __construct(
Mailer $mailer,
CustomerRepositoryInterface $customerRepository
) {
$this->mailer = $mailer;
$this->customerRepository = $customerRepository;
}
/**
* Update customer password with ramdom string.
*
* @param string $email
*
* @return CustomerInterface
*/
public function update(string $email): CustomerInterface
{
$customer = $this->customerRepository->findByEmail($email);
/**
* create a reseted password with random string.
*/
$newPassword = Str::random(13);
$attributes['password'] = $newPassword;
$this->customerRepository->update($customer, $attributes);
/**
* Send a reseted password mail to customer.
*/
$this->sendMail($customer, $newPassword);
return $this->customerRepository->findByEmail($customer->email);
}
/**
* @param CustomerInterface $customer
* @param string $newPassword
*/
protected function sendMail(CustomerInterface $customer, string $newPassword)
{
$mailable = new CustomerPasswordResetMail($customer, $newPassword);
$this->mailer->to($customer->email)->send($mailable);
}
}
repository
<?php
declare(strict_types=1);
namespace Oms\Repositories;
use Oms\Models\Customer;
use Oms\Models\Factory\CustomerFactory;
use Oms\Models\Interfaces\CustomerInterface;
use Oms\Repositories\Exceptions\NotExistsCustomerException;
use Oms\Repositories\Interfaces\CustomerRepositoryInterface;
use Traversable;
class CustomerRepository implements CustomerRepositoryInterface
{
/** @var CustomerFactory */
protected $factory;
/** @var Customer */
protected $orm;
/**
* @inheritdoc
*/
public function __construct(CustomerFactory $factory, Customer $customer)
{
$this->factory = $factory;
$this->orm = $customer;
}
/**
* @param int $customerId
*
* @return CustomerInterface
* @throws NotExistsCustomerException
*/
public function find(int $customerId): CustomerInterface
{
$customer = $this->orm->find($customerId);
if (!$customer) {
throw new NotExistsCustomerException();
}
return $customer;
}
/**
* @inheritdoc
*/
public function findAll(): Traversable
{
return $this->orm->get();
}
/**
* @inheritdoc
*/
public function store(array $attributes): CustomerInterface
{
$customer = app(Customer::class);
return $this->factory->persist($customer, $attributes);
}
/**
* @param CustomerInterface $customer
* @param array $attributes
*
* @return CustomerInterface
* @throws NotExistsCustomerException
*/
public function update(CustomerInterface $customer, array $attributes): CustomerInterface
{
if (!$customer->exists) {
throw new NotExistsCustomerException();
}
$updatedCustomer = $this->factory->persist($customer, $attributes);
return $this->find($updatedCustomer->id);
}
/**
* @param CustomerInterface $customer
*
* @return void
* @throws NotExistsCustomerException
*/
public function remove(CustomerInterface $customer)
{
if (!$customer->exists) {
throw new NotExistsCustomerException();
}
$customer->delete();
}
/**
* @param $email
*
* @return \Illuminate\Database\Eloquent\Model|null|static
*/
public function findByEmail($email)
{
$customer = $this->orm->where('email', $email)->first();
if (!$customer) {
throw new NotExistsCustomerException();
}
return $customer;
}
}
factory
<?php
declare(strict_types=1);
namespace Oms\Models\Factory;
use Oms\Models\Customer;
use Oms\Models\Factory\FactoryInterface;
final class CustomerFactory implements FactoryInterface
{
/** @var Customer */
private $orm;
/**
* CustomerFactory constructor.
*
* @param Customer $customer
*/
public function __construct(Customer $customer)
{
$this->orm = $customer;
}
/**
* @param Customer $customer
* @param array $attributes
*
* @return Customer
*/
public function persist($customer, array $attributes): Customer
{
if (!$customer->exists) {
return $this->create($attributes);
}
return $this->update($customer, $attributes);
}
/**
* @param array $attributes
*
* @return Customer
*/
protected function create(array $attributes): Customer
{
$customer = $this->orm->fill($attributes);
$customer->save();
return $customer->refresh();
}
/**
* @param Customer $customer
* @param array $attributes
*
* @return Customer
*/
protected function update(Customer $customer, array $attributes): Customer
{
$customer->fill($attributes)->update();
return $customer->refresh();
}
}
メール生成
<?php
declare(strict_types=1);
namespace Oms\Domain\Front\CustomerPassword\PasswordReset;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Oms\Models\Interfaces\CustomerInterface;
class CustomerPasswordResetMail extends Mailable implements ShouldQueue
{
use Queueable;
use SerializesModels;
/** @var CustomerInterface */
protected $customer;
/** @var string */
protected $newPassword;
/**
* CustomerPasswordResetMail constructor.
*
* @param CustomerInterface $customer
* @param string $newPassword
*/
public function __construct(CustomerInterface $customer, string $newPassword)
{
$this->customer = $customer;
$this->newPassword = $newPassword;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$fromAddress = config('oms.site.email.noreply');
$fromName = '事業構想オンライン';
$subject = '◆パスワード再発行のお知らせ◆ 事業構想オンライン';
return $this->view('front.customers.reset-passwords.email')
->from($fromAddress, $fromName)
->subject($subject)
->with([
'email' => $this->customer->email,
'newPassword' => $this->newPassword,
]);
}
}
コメント