- <?php
- /*
-  * This file is part of EC-CUBE
-  *
-  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
-  *
-  * http://www.ec-cube.co.jp/
-  *
-  * For the full copyright and license information, please view the LICENSE
-  * file that was distributed with this source code.
-  */
- namespace Eccube\Service;
- use Eccube\Entity\Master\OrderStatus;
- use Eccube\Entity\Order;
- use Eccube\Repository\Master\OrderStatusRepository;
- use Eccube\Service\PurchaseFlow\Processor\PointProcessor;
- use Eccube\Service\PurchaseFlow\Processor\StockReduceProcessor;
- use Eccube\Service\PurchaseFlow\PurchaseContext;
- use Symfony\Component\EventDispatcher\EventSubscriberInterface;
- use Symfony\Component\Workflow\Event\Event;
- use Symfony\Component\Workflow\StateMachine;
- class OrderStateMachine implements EventSubscriberInterface
- {
-     /**
-      * @var StateMachine
-      */
-     private $machine;
-     /**
-      * @var OrderStatusRepository
-      */
-     private $orderStatusRepository;
-     /**
-      * @var PointProcessor
-      */
-     private $pointProcessor;
-     /**
-      * @var StockReduceProcessor
-      */
-     private $stockReduceProcessor;
-     public function __construct(StateMachine $_orderStateMachine, OrderStatusRepository $orderStatusRepository, PointProcessor $pointProcessor, StockReduceProcessor $stockReduceProcessor)
-     {
-         $this->machine = $_orderStateMachine;
-         $this->orderStatusRepository = $orderStatusRepository;
-         $this->pointProcessor = $pointProcessor;
-         $this->stockReduceProcessor = $stockReduceProcessor;
-     }
-     /**
-      * 指定ステータスに遷移.
-      *
-      * @param Order $Order 受注
-      * @param OrderStatus $OrderStatus 遷移先ステータス
-      */
-     public function apply(Order $Order, OrderStatus $OrderStatus)
-     {
-         $context = $this->newContext($Order);
-         $transition = $this->getTransition($context, $OrderStatus);
-         if ($transition) {
-             $this->machine->apply($context, $transition->getName());
-         } else {
-             throw new \InvalidArgumentException();
-         }
-     }
-     /**
-      * 指定ステータスに遷移できるかどうかを判定.
-      *
-      * @param Order $Order 受注
-      * @param OrderStatus $OrderStatus 遷移先ステータス
-      *
-      * @return boolean 指定ステータスに遷移できる場合はtrue
-      */
-     public function can(Order $Order, OrderStatus $OrderStatus)
-     {
-         return !is_null($this->getTransition($this->newContext($Order), $OrderStatus));
-     }
-     private function getTransition(OrderStateMachineContext $context, OrderStatus $OrderStatus)
-     {
-         $transitions = $this->machine->getEnabledTransitions($context);
-         foreach ($transitions as $t) {
-             if (in_array($OrderStatus->getId(), $t->getTos())) {
-                 return $t;
-             }
-         }
-         return null;
-     }
-     /**
-      * {@inheritdoc}
-      */
-     public static function getSubscribedEvents()
-     {
-         return [
-             'workflow.order.completed' => ['onCompleted'],
-            // 'workflow.order.transition.pay' => ['updatePaymentDate'],
-             'workflow.order.transition.cancel' => [['rollbackStock'], ['rollbackUsePoint']],
-             'workflow.order.transition.back_to_in_progress' => [['commitStock'], ['commitUsePoint']],
-             //'workflow.order.transition.ship' => [['commitAddPoint']],
-             'workflow.order.transition.ship' => ['updatePaymentDate'],
-             'workflow.order.transition.return' => [['rollbackUsePoint'], ['rollbackAddPoint']],
-             'workflow.order.transition.cancel_return' => [['commitUsePoint'], ['commitAddPoint']],
-         ];
-     }
-     /*
-      * Event handlers.
-      */
-     /**
-      * 入金日を更新する.
-      *
-      * @param Event $event
-      */
-     public function updatePaymentDate(Event $event)
-     {
-         /* @var Order $Order */
-         $Order = $event->getSubject()->getOrder();
-         $Order->setPaymentDate(new \DateTime());
-     }
-     /**
-      * 会員の保有ポイントを減らす.
-      *
-      * @param Event $event
-      *
-      * @throws PurchaseFlow\PurchaseException
-      */
-     public function commitUsePoint(Event $event)
-     {
-         /* @var Order $Order */
-         $Order = $event->getSubject()->getOrder();
-         $this->pointProcessor->prepare($Order, new PurchaseContext());
-     }
-     /**
-      * 利用ポイントを会員に戻す.
-      *
-      * @param Event $event
-      */
-     public function rollbackUsePoint(Event $event)
-     {
-         /* @var Order $Order */
-         $Order = $event->getSubject()->getOrder();
-         $this->pointProcessor->rollback($Order, new PurchaseContext());
-     }
-     /**
-      * 在庫を減らす.
-      *
-      * @param Event $event
-      *
-      * @throws PurchaseFlow\PurchaseException
-      */
-     public function commitStock(Event $event)
-     {
-         /* @var Order $Order */
-         $Order = $event->getSubject()->getOrder();
-         $this->stockReduceProcessor->prepare($Order, new PurchaseContext());
-     }
-     /**
-      * 在庫を戻す.
-      *
-      * @param Event $event
-      */
-     public function rollbackStock(Event $event)
-     {
-         /* @var Order $Order */
-         $Order = $event->getSubject()->getOrder();
-         $this->stockReduceProcessor->rollback($Order, new PurchaseContext());
-     }
-     /**
-      * 会員に加算ポイントを付与する.
-      *
-      * @param Event $event
-      */
-     public function commitAddPoint(Event $event)
-     {
-         /* @var Order $Order */
-         $Order = $event->getSubject()->getOrder();
-         $Customer = $Order->getCustomer();
-         if ($Customer) {
-             $Customer->setPoint(intval($Customer->getPoint()) + intval($Order->getAddPoint()));
-         }
-     }
-     /**
-      * 会員に付与した加算ポイントを取り消す.
-      *
-      * @param Event $event
-      */
-     public function rollbackAddPoint(Event $event)
-     {
-         /* @var Order $Order */
-         $Order = $event->getSubject()->getOrder();
-         $Customer = $Order->getCustomer();
-         if ($Customer) {
-             $Customer->setPoint(intval($Customer->getPoint()) - intval($Order->getAddPoint()));
-         }
-     }
-     /**
-      * 受注ステータスを再設定.
-      * {@link StateMachine}によって遷移が終了したときには{@link Order#OrderStatus}のidが変更されるだけなのでOrderStatusを設定し直す.
-      *
-      * @param Event $event
-      */
-     public function onCompleted(Event $event)
-     {
-         /** @var $context OrderStateMachineContext */
-         $context = $event->getSubject();
-         $Order = $context->getOrder();
-         $CompletedOrderStatus = $this->orderStatusRepository->find($context->getStatus());
-         $Order->setOrderStatus($CompletedOrderStatus);
-     }
-     private function newContext(Order $Order)
-     {
-         return new OrderStateMachineContext((string) $Order->getOrderStatus()->getId(), $Order);
-     }
- }
- class OrderStateMachineContext
- {
-     /** @var string */
-     private $status;
-     /** @var Order */
-     private $Order;
-     /**
-      * OrderStateMachineContext constructor.
-      *
-      * @param string $status
-      * @param Order $Order
-      */
-     public function __construct($status, Order $Order)
-     {
-         $this->status = $status;
-         $this->Order = $Order;
-     }
-     /**
-      * @return string
-      */
-     public function getStatus()
-     {
-         return $this->status;
-     }
-     /**
-      * @param string $status
-      */
-     public function setStatus($status)
-     {
-         $this->status = $status;
-     }
-     /**
-      * @return Order
-      */
-     public function getOrder()
-     {
-         return $this->Order;
-     }
-     // order_state_machine.php の marking_store => property は、デフォルト値である marking を使用するよう強く推奨されている.
-     // EC-CUBE4.1 までは status を指定していたが、 Symfony5 よりエラーになるためエイリアスを作成して対応する.
-     /**
-      * Alias of getStatus()
-      */
-     public function getMarking(): string
-     {
-         return $this->getStatus();
-     }
-     /**
-      * Alias of setStatus()
-      */
-     public function setMarking(string $status): void
-     {
-         $this->setStatus($status);
-     }
- }
-