From f977999557a3662d2aa7e00212e1e2a989b021d1 Mon Sep 17 00:00:00 2001 From: Kentaro Ohkouchi Date: Fri, 8 Sep 2023 15:36:44 +0900 Subject: [PATCH 1/2] Using ShoppingException --- GraphQL/Error/ShoppingException.php | 44 ++++++++++++++++++++++ GraphQL/Mutation/PaymentMethodMutation.php | 12 +++--- GraphQL/Mutation/PurchaseMutation.php | 22 ++++++----- GraphQL/Mutation/ShoppingMutation.php | 30 ++++++--------- 4 files changed, 75 insertions(+), 33 deletions(-) create mode 100644 GraphQL/Error/ShoppingException.php diff --git a/GraphQL/Error/ShoppingException.php b/GraphQL/Error/ShoppingException.php new file mode 100644 index 0000000..3879396 --- /dev/null +++ b/GraphQL/Error/ShoppingException.php @@ -0,0 +1,44 @@ +orderHelper->getPurchaseProcessingOrder($preOrderId); if (!$Order) { - log_info('[注文確認] 購入処理中の受注が存在しません.', [$preOrderId]); - throw new InvalidArgumentException(); + $message = '[注文確認] 購入処理中の受注が存在しません.'; + log_info($message, [$preOrderId]); + throw new ShoppingException($message); } if (!empty($args['payment_method_id'])) { /** @var Payment|null $Payment */ $Payment = $this->entityManager->find(Payment::class, $args['payment_method_id']); if (!$Payment) { - log_info('[注文確認] 支払い方法が存在しません.', [$args['payment_method_id']]); - throw new InvalidArgumentException(); + $message = '[注文確認] 支払い方法が存在しません.'; + log_info($message, [$args['payment_method_id']]); + throw new ShoppingException($message); } log_info('[注文確認] 支払い方法を変更します.', [$Payment->getMethod()]); $Order->setPayment($Payment); diff --git a/GraphQL/Mutation/PurchaseMutation.php b/GraphQL/Mutation/PurchaseMutation.php index f1581aa..d1ea77d 100644 --- a/GraphQL/Mutation/PurchaseMutation.php +++ b/GraphQL/Mutation/PurchaseMutation.php @@ -84,20 +84,22 @@ public function purchaseMutation() { $Customer = $this->securityContext->getLoginUser(); if (!$Customer instanceof Customer) { - throw new InvalidArgumentException('ログインしていません'); + throw new ShoppingException('ログインしていません'); } // ログイン状態のチェック. if ($this->orderHelper->isLoginRequired()) { - log_info('[注文処理] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.'); - throw new InvalidArgumentException(); + $message = '[注文処理] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.'; + log_info($message); + throw new ShoppingException($message); } // 受注の存在チェック $preOrderId = $this->cartService->getPreOrderId(); $Order = $this->orderHelper->getPurchaseProcessingOrder($preOrderId); if (!$Order) { - log_info('[注文処理] 購入処理中の受注が存在しません.', [$preOrderId]); - throw new InvalidArgumentException(); + $message = '[注文処理] 購入処理中の受注が存在しません.'; + log_info($message, [$preOrderId]); + throw new ShoppingException($message); } log_info('[注文処理] 注文処理を開始します.', [$Order->getId()]); @@ -163,13 +165,13 @@ public function purchaseMutation() $this->entityManager->rollback(); - throw new InvalidArgumentException($e->getMessage()); + throw new ShoppingException($e->getMessage()); } catch (\Exception $e) { log_error('[注文処理] 予期しないエラーが発生しました.', [$e->getMessage()]); // $this->entityManager->rollback(); FIXME ユニットテストで There is no active transaction エラーになってしまう - throw new InvalidArgumentException($e->getMessage()); + throw new ShoppingException($e->getMessage()); } // カート削除 @@ -216,10 +218,10 @@ protected function executePurchaseFlow(ItemHolderInterface $itemHolder, $returnR /** @var PurchaseFlowResult $flowResult */ $flowResult = $this->purchaseFlow->validate($itemHolder, new PurchaseContext(clone $itemHolder, $itemHolder->getCustomer())); foreach ($flowResult->getWarning() as $warning) { - throw new InvalidArgumentException(); + throw new InvalidArgumentException(); // FIXME AbstractMutation::addWarning()を実装する } foreach ($flowResult->getErrors() as $error) { - throw new InvalidArgumentException(); + throw new ShoppingException($error->getMessage()); } if (!$returnResponse) { @@ -307,7 +309,7 @@ protected function executeCheckout(PaymentMethodInterface $paymentMethod) if (!$PaymentResult->isSuccess()) { $this->entityManager->rollback(); foreach ($PaymentResult->getErrors() as $error) { - throw new InvalidArgumentException($error->getMessage()); + throw new ShoppingException($error->getMessage()); } log_info('[注文処理] PaymentMethod::checkoutのエラーのため, 購入エラー画面へ遷移します.', [$PaymentResult->getErrors()]); diff --git a/GraphQL/Mutation/ShoppingMutation.php b/GraphQL/Mutation/ShoppingMutation.php index c34f512..cab04ca 100644 --- a/GraphQL/Mutation/ShoppingMutation.php +++ b/GraphQL/Mutation/ShoppingMutation.php @@ -26,6 +26,7 @@ use Eccube\Service\PurchaseFlow\PurchaseFlow; use Eccube\Service\PurchaseFlow\PurchaseFlowResult; use Plugin\Api42\GraphQL\Error\InvalidArgumentException; +use Plugin\Api42\GraphQL\Error\ShoppingException; use Plugin\Api42\GraphQL\Mutation; use Plugin\Api42\GraphQL\Types; @@ -80,15 +81,17 @@ public function orderMutation($root, $args): ?Order // ログイン状態のチェック. if ($this->orderHelper->isLoginRequired()) { - log_info('[注文手続] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.'); - throw new InvalidArgumentException(); + $message = '[注文手続] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.'; + log_info($mssage); + throw new ShoppingException($message); } // カートチェック. $Cart = $this->cartService->getCart(); if (!($Cart && $this->orderHelper->verifyCart($Cart))) { - log_info('[注文手続] カートが購入フローへ遷移できない状態のため, カート画面に遷移します.'); - throw new InvalidArgumentException(); + $message = '[注文手続] カートが購入フローへ遷移できない状態のため, カート画面に遷移します.'; + log_info($mssage); + throw new ShoppingException($message); } // 受注の初期化. @@ -102,8 +105,9 @@ public function orderMutation($root, $args): ?Order $this->entityManager->flush(); if ($flowResult->hasError()) { - log_info('[注文手続] Errorが発生したため購入エラー画面へ遷移します.', [$flowResult->getErrors()]); - throw new InvalidArgumentException(); + $message = '[注文手続] Errorが発生したため購入エラー画面へ遷移します.'; + log_info($message, [$flowResult->getErrors()]); + throw new ShoppingException($message); } if ($flowResult->hasWarning()) { @@ -138,26 +142,16 @@ protected function executePurchaseFlow(ItemHolderInterface $itemHolder, bool $re { $flowResult = $this->cartPurchaseFlow->validate($itemHolder, new PurchaseContext(clone $itemHolder, $itemHolder->getCustomer())); foreach ($flowResult->getWarning() as $warning) { - throw new InvalidArgumentException(); + throw new InvalidArgumentException(); // TODO AbstractMutation::addWaring を使用する } foreach ($flowResult->getErrors() as $error) { - throw new InvalidArgumentException(); + throw new ShoppingException($error->getMessage()); } if (!$returnResponse) { return $flowResult; } - if ($flowResult->hasError()) { - log_info('Errorが発生したため購入エラー画面へ遷移します.', [$flowResult->getErrors()]); - throw new InvalidArgumentException(); - } - - if ($flowResult->hasWarning()) { - log_info('Warningが発生したため注文手続き画面へ遷移します.', [$flowResult->getWarning()]); - throw new InvalidArgumentException(); - } - return null; } } From 15d5403c8a8dad74068b55fd2d7b1e0f58472150 Mon Sep 17 00:00:00 2001 From: Kentaro Ohkouchi Date: Wed, 13 Sep 2023 09:46:54 +0900 Subject: [PATCH 2/2] Use extends AbstractMutation --- GraphQL/Mutation/AbstractMutation.php | 17 ++++++++++------ GraphQL/Mutation/PurchaseMutation.php | 28 ++++++++++++++------------- GraphQL/Mutation/ShoppingMutation.php | 27 +++++++++++++++----------- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/GraphQL/Mutation/AbstractMutation.php b/GraphQL/Mutation/AbstractMutation.php index f321b63..64cb3cd 100644 --- a/GraphQL/Mutation/AbstractMutation.php +++ b/GraphQL/Mutation/AbstractMutation.php @@ -58,6 +58,7 @@ protected function getInputObject(FormInterface $form): InputObjectType { $fields = []; $this->convertArgs($form, $fields); + return new InputObjectType([ 'name' => $form->getName().'Input', 'fields' => $fields, @@ -133,16 +134,18 @@ protected function convertArgs(FormInterface $form, array &$args = []): void public function getMutation(): array { + $args = []; $builder = $this->formFactory->createBuilder($this->getArgsType(), null, ['csrf_protection' => false]); $form = $builder->getForm(); + if ($form->getName() !== 'form') { + $args['input'] = [ + 'type' => $this->getInputObject($form), + ]; + } return [ 'type' => $this->types->get($this->getTypesClass()), - 'args' => [ - 'input' => [ - 'type' => $this->getInputObject($form), - ], - ], + 'args' => $args, 'resolve' => function ($value, array $args, $context, ResolveInfo $info) use ($form) { return $this->resolver($value, $args, $context, $info, $form); } @@ -198,7 +201,9 @@ protected function convertFormValues(FormInterface $form, &$formValues = [], $i protected function resolver($value, array $args, $context, ResolveInfo $info, FormInterface $form): mixed { $formValues = []; - $this->convertFormValues($form, $formValues, $args['input']); + if (array_key_exists('input', $args)) { + $this->convertFormValues($form, $formValues, $args['input']); + } $form->submit($formValues); if (!$form->isValid()) { diff --git a/GraphQL/Mutation/PurchaseMutation.php b/GraphQL/Mutation/PurchaseMutation.php index d1ea77d..e307b29 100644 --- a/GraphQL/Mutation/PurchaseMutation.php +++ b/GraphQL/Mutation/PurchaseMutation.php @@ -31,13 +31,12 @@ use Eccube\Service\PurchaseFlow\PurchaseFlow; use Eccube\Service\PurchaseFlow\PurchaseFlowResult; use Plugin\Api42\GraphQL\Error\InvalidArgumentException; -use Plugin\Api42\GraphQL\Mutation; use Plugin\Api42\GraphQL\Types; +use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\FormFactoryInterface; -class PurchaseMutation implements Mutation +class PurchaseMutation extends AbstractMutation { - private Types $types; - private EntityManager $entityManager; private CartService $cartService; private OrderHelper $orderHelper; @@ -55,8 +54,8 @@ public function __construct( PurchaseFlow $cartPurchaseFlow, PaymentMethodLocator $locator, MailService $mailService, + FormFactoryInterface $formFactory, ) { - $this->types = $types; $this->entityManager = $entityManager; $this->cartService = $cartService; $this->orderHelper = $orderHelper; @@ -64,6 +63,8 @@ public function __construct( $this->cartPurchaseFlow = $cartPurchaseFlow; $this->locator = $locator; $this->mailService = $mailService; + $this->setTypes($types); + $this->setFormFactory($formFactory); } public function getName(): string @@ -71,16 +72,17 @@ public function getName(): string return 'purchaseMutation'; } - public function getMutation(): array + public function getTypesClass(): string + { + return Order::class; + } + + public function getArgsType(): string { - return [ - 'type' => $this->types->get(Order::class), - 'args' => [], - 'resolve' => [$this, 'purchaseMutation'], - ]; + return FormType::class; } - public function purchaseMutation() + public function executeMutation($root, array $args): mixed { $Customer = $this->securityContext->getLoginUser(); if (!$Customer instanceof Customer) { @@ -218,7 +220,7 @@ protected function executePurchaseFlow(ItemHolderInterface $itemHolder, $returnR /** @var PurchaseFlowResult $flowResult */ $flowResult = $this->purchaseFlow->validate($itemHolder, new PurchaseContext(clone $itemHolder, $itemHolder->getCustomer())); foreach ($flowResult->getWarning() as $warning) { - throw new InvalidArgumentException(); // FIXME AbstractMutation::addWarning()を実装する + $this->addWarning($warning->getMessage()); } foreach ($flowResult->getErrors() as $error) { throw new ShoppingException($error->getMessage()); diff --git a/GraphQL/Mutation/ShoppingMutation.php b/GraphQL/Mutation/ShoppingMutation.php index cab04ca..affe844 100644 --- a/GraphQL/Mutation/ShoppingMutation.php +++ b/GraphQL/Mutation/ShoppingMutation.php @@ -27,10 +27,11 @@ use Eccube\Service\PurchaseFlow\PurchaseFlowResult; use Plugin\Api42\GraphQL\Error\InvalidArgumentException; use Plugin\Api42\GraphQL\Error\ShoppingException; -use Plugin\Api42\GraphQL\Mutation; use Plugin\Api42\GraphQL\Types; +use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\FormFactoryInterface; -class ShoppingMutation implements Mutation +class ShoppingMutation extends AbstractMutation { private Types $types; @@ -47,13 +48,15 @@ public function __construct( OrderHelper $orderHelper, SecurityContext $securityContext, PurchaseFlow $cartPurchaseFlow, + FormFactoryInterface $formFactory, ) { - $this->types = $types; $this->entityManager = $entityManager; $this->cartService = $cartService; $this->orderHelper = $orderHelper; $this->securityContext = $securityContext; $this->cartPurchaseFlow = $cartPurchaseFlow; + $this->setTypes($types); + $this->setFormFactory($formFactory); } public function getName(): string @@ -61,21 +64,23 @@ public function getName(): string return 'orderMutation'; } - public function getMutation(): array + public function getTypesClass(): string { - return [ - 'type' => $this->types->get(Order::class), - 'args' => [], - 'resolve' => [$this, 'orderMutation'], - ]; + return Order::class; + } + + public function getArgsType(): string + { + return FormType::class; } /** + * @return Order|null * @throws InvalidArgumentException * @throws ORMException * @throws ForeignKeyConstraintViolationException */ - public function orderMutation($root, $args): ?Order + public function executeMutation($root, $args): mixed { $user = $this->securityContext->getLoginUser(); @@ -142,7 +147,7 @@ protected function executePurchaseFlow(ItemHolderInterface $itemHolder, bool $re { $flowResult = $this->cartPurchaseFlow->validate($itemHolder, new PurchaseContext(clone $itemHolder, $itemHolder->getCustomer())); foreach ($flowResult->getWarning() as $warning) { - throw new InvalidArgumentException(); // TODO AbstractMutation::addWaring を使用する + $this->addWarning($warning->getMessage()); } foreach ($flowResult->getErrors() as $error) { throw new ShoppingException($error->getMessage());