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 @@ +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/PaymentMethodMutation.php b/GraphQL/Mutation/PaymentMethodMutation.php index a03b71d..2fd4bb8 100644 --- a/GraphQL/Mutation/PaymentMethodMutation.php +++ b/GraphQL/Mutation/PaymentMethodMutation.php @@ -21,7 +21,7 @@ use Eccube\Service\CartService; use Eccube\Service\OrderHelper; use GraphQL\Type\Definition\Type; -use Plugin\Api42\GraphQL\Error\InvalidArgumentException; +use Plugin\Api42\GraphQL\Error\ShoppingException; use Plugin\Api42\GraphQL\Mutation; use Plugin\Api42\GraphQL\Types; @@ -70,16 +70,18 @@ public function paymentMethodMutation($root, $args) /** @var Order|null $Order */ $Order = $this->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..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,33 +72,36 @@ 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) { - 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 +167,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 +220,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(); + $this->addWarning($warning->getMessage()); } foreach ($flowResult->getErrors() as $error) { - throw new InvalidArgumentException(); + throw new ShoppingException($error->getMessage()); } if (!$returnResponse) { @@ -307,7 +311,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..affe844 100644 --- a/GraphQL/Mutation/ShoppingMutation.php +++ b/GraphQL/Mutation/ShoppingMutation.php @@ -26,10 +26,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\Error\ShoppingException; 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; @@ -46,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 @@ -60,35 +64,39 @@ 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(); // ログイン状態のチェック. 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 +110,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 +147,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(); + $this->addWarning($warning->getMessage()); } 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; } }