app/Customize/Service/OrderStateMachine.php line 196

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Customize\Service;
  13. use Eccube\Entity\Master\OrderStatus;
  14. use Eccube\Entity\Order;
  15. use Eccube\Repository\Master\OrderStatusRepository;
  16. use Eccube\Service\PurchaseFlow\Processor\PointProcessor;
  17. use Eccube\Service\PurchaseFlow\Processor\StockReduceProcessor;
  18. use Eccube\Service\PurchaseFlow\PurchaseContext;
  19. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  20. use Symfony\Component\Workflow\Event\Event;
  21. use Symfony\Component\Workflow\StateMachine;
  22. class OrderStateMachine implements EventSubscriberInterface
  23. {
  24.     /**
  25.      * @var StateMachine
  26.      */
  27.     private $machine;
  28.     /**
  29.      * @var OrderStatusRepository
  30.      */
  31.     private $orderStatusRepository;
  32.     /**
  33.      * @var PointProcessor
  34.      */
  35.     private $pointProcessor;
  36.     /**
  37.      * @var StockReduceProcessor
  38.      */
  39.     private $stockReduceProcessor;
  40.     public function __construct(StateMachine $_orderStateMachineOrderStatusRepository $orderStatusRepositoryPointProcessor $pointProcessorStockReduceProcessor $stockReduceProcessor)
  41.     {
  42.         $this->machine $_orderStateMachine;
  43.         $this->orderStatusRepository $orderStatusRepository;
  44.         $this->pointProcessor $pointProcessor;
  45.         $this->stockReduceProcessor $stockReduceProcessor;
  46.     }
  47.     /**
  48.      * 指定ステータスに遷移.
  49.      *
  50.      * @param Order $Order 受注
  51.      * @param OrderStatus $OrderStatus 遷移先ステータス
  52.      */
  53.     public function apply(Order $OrderOrderStatus $OrderStatus)
  54.     {
  55.         $context $this->newContext($Order);
  56.         $transition $this->getTransition($context$OrderStatus);
  57.         if ($transition) {
  58.             $this->machine->apply($context$transition->getName());
  59.         } else {
  60.             throw new \InvalidArgumentException();
  61.         }
  62.     }
  63.     /**
  64.      * 指定ステータスに遷移できるかどうかを判定.
  65.      *
  66.      * @param Order $Order 受注
  67.      * @param OrderStatus $OrderStatus 遷移先ステータス
  68.      *
  69.      * @return boolean 指定ステータスに遷移できる場合はtrue
  70.      */
  71.     public function can(Order $OrderOrderStatus $OrderStatus)
  72.     {
  73.         return !is_null($this->getTransition($this->newContext($Order), $OrderStatus));
  74.     }
  75.     private function getTransition(OrderStateMachineContext $contextOrderStatus $OrderStatus)
  76.     {
  77.         $transitions $this->machine->getEnabledTransitions($context);
  78.         foreach ($transitions as $t) {
  79.             if (in_array($OrderStatus->getId(), $t->getTos())) {
  80.                 return $t;
  81.             }
  82.         }
  83.         return null;
  84.     }
  85.     /**
  86.      * {@inheritdoc}
  87.      */
  88.     public static function getSubscribedEvents()
  89.     {
  90.         return [
  91.             'workflow.order.completed' => ['onCompleted'],
  92.             'workflow.order.transition.pay' => ['updatePaymentDate'],
  93.             'workflow.order.transition.cancel' => [['rollbackStock'], ['rollbackUsePoint'], ['updateCancelDate']],
  94.             'workflow.order.transition.back_to_in_progress' => [['commitStock'], ['commitUsePoint']],
  95.             'workflow.order.transition.ship' => [['commitAddPoint']],
  96.             'workflow.order.transition.return' => [['rollbackUsePoint'], ['rollbackAddPoint'], ['updateReturnDate']],
  97.             'workflow.order.transition.cancel_return' => [['commitUsePoint'], ['commitAddPoint'], ['resetReturnDate']],
  98.         ];
  99.     }
  100.     /*
  101.      * Event handlers.
  102.      */
  103.     /**
  104.      * 入金日を更新する.
  105.      *
  106.      * @param Event $event
  107.      */
  108.     public function updatePaymentDate(Event $event)
  109.     {
  110.         /* @var Order $Order */
  111.         $Order $event->getSubject()->getOrder();
  112.         $Order->setPaymentDate(new \DateTime());
  113.     }
  114.     /**
  115.      * 返品日を更新する.
  116.      *
  117.      * @param Event $event
  118.      */
  119.     public function updateReturnDate(Event $event)
  120.     {
  121.         /* @var Order $Order */
  122.         $Order $event->getSubject()->getOrder();
  123.         $Order->setReturnDate(new \DateTime());
  124.     }
  125.     /**
  126.      * 返品日を更新する.(null)
  127.      *
  128.      * @param Event $event
  129.      */
  130.     public function resetReturnDate(Event $event)
  131.     {
  132.         /* @var Order $Order */
  133.         $Order $event->getSubject()->getOrder();
  134.         $Order->setReturnDate(null);
  135.     }
  136.     /**
  137.      * 取消日を更新する.
  138.      *
  139.      * @param Event $event
  140.      */
  141.     public function updateCancelDate(Event $event)
  142.     {
  143.         /* @var Order $Order */
  144.         $Order $event->getSubject()->getOrder();
  145.         $Order->setCancelDate(new \DateTime());
  146.     }
  147.     /**
  148.      * 取消日を更新する.(null)
  149.      *
  150.      * @param Event $event
  151.      */
  152.     public function resetCancelDate(Event $event)
  153.     {
  154.         /* @var Order $Order */
  155.         $Order $event->getSubject()->getOrder();
  156.         $Order->setCancelDate(null);
  157.     }
  158.     /**
  159.      * 会員の保有ポイントを減らす.
  160.      *
  161.      * @param Event $event
  162.      *
  163.      * @throws PurchaseFlow\PurchaseException
  164.      */
  165.     public function commitUsePoint(Event $event)
  166.     {
  167.         /* @var Order $Order */
  168.         $Order $event->getSubject()->getOrder();
  169.         $this->pointProcessor->prepare($Order, new PurchaseContext());
  170.     }
  171.     /**
  172.      * 利用ポイントを会員に戻す.
  173.      *
  174.      * @param Event $event
  175.      */
  176.     public function rollbackUsePoint(Event $event)
  177.     {
  178.         /* @var Order $Order */
  179.         $Order $event->getSubject()->getOrder();
  180.         $this->pointProcessor->rollback($Order, new PurchaseContext());
  181.     }
  182.     /**
  183.      * 在庫を減らす.
  184.      *
  185.      * @param Event $event
  186.      *
  187.      * @throws PurchaseFlow\PurchaseException
  188.      */
  189.     public function commitStock(Event $event)
  190.     {
  191.         /* @var Order $Order */
  192.         $Order $event->getSubject()->getOrder();
  193.         $this->stockReduceProcessor->prepare($Order, new PurchaseContext());
  194.     }
  195.     /**
  196.      * 在庫を戻す.
  197.      *
  198.      * @param Event $event
  199.      */
  200.     public function rollbackStock(Event $event)
  201.     {
  202.         /* @var Order $Order */
  203.         $Order $event->getSubject()->getOrder();
  204.         $this->stockReduceProcessor->rollback($Order, new PurchaseContext());
  205.     }
  206.     /**
  207.      * 会員に加算ポイントを付与する.
  208.      *
  209.      * @param Event $event
  210.      */
  211.     public function commitAddPoint(Event $event)
  212.     {
  213.         /* @var Order $Order */
  214.         $Order $event->getSubject()->getOrder();
  215.         $Customer $Order->getCustomer();
  216.         if ($Customer) {
  217.             $Customer->setPoint(intval($Customer->getPoint()) + intval($Order->getAddPoint()));
  218.         }
  219.     }
  220.     /**
  221.      * 会員に付与した加算ポイントを取り消す.
  222.      *
  223.      * @param Event $event
  224.      */
  225.     public function rollbackAddPoint(Event $event)
  226.     {
  227.         /* @var Order $Order */
  228.         $Order $event->getSubject()->getOrder();
  229.         $Customer $Order->getCustomer();
  230.         if ($Customer) {
  231.             $Customer->setPoint(intval($Customer->getPoint()) - intval($Order->getAddPoint()));
  232.         }
  233.     }
  234.     /**
  235.      * 受注ステータスを再設定.
  236.      * {@link StateMachine}によって遷移が終了したときには{@link Order#OrderStatus}のidが変更されるだけなのでOrderStatusを設定し直す.
  237.      *
  238.      * @param Event $event
  239.      */
  240.     public function onCompleted(Event $event)
  241.     {
  242.         /** @var $context OrderStateMachineContext */
  243.         $context $event->getSubject();
  244.         $Order $context->getOrder();
  245.         $CompletedOrderStatus $this->orderStatusRepository->find($context->getStatus());
  246.         $Order->setOrderStatus($CompletedOrderStatus);
  247.     }
  248.     private function newContext(Order $Order)
  249.     {
  250.         return new OrderStateMachineContext((string) $Order->getOrderStatus()->getId(), $Order);
  251.     }
  252. }
  253. class OrderStateMachineContext
  254. {
  255.     /** @var string */
  256.     private $status;
  257.     /** @var Order */
  258.     private $Order;
  259.     /**
  260.      * OrderStateMachineContext constructor.
  261.      *
  262.      * @param string $status
  263.      * @param Order $Order
  264.      */
  265.     public function __construct($statusOrder $Order)
  266.     {
  267.         $this->status $status;
  268.         $this->Order $Order;
  269.     }
  270.     /**
  271.      * @return string
  272.      */
  273.     public function getStatus()
  274.     {
  275.         return $this->status;
  276.     }
  277.     /**
  278.      * @param string $status
  279.      */
  280.     public function setStatus($status)
  281.     {
  282.         $this->status $status;
  283.     }
  284.     /**
  285.      * @return Order
  286.      */
  287.     public function getOrder()
  288.     {
  289.         return $this->Order;
  290.     }
  291. }