Failed Conditions
Push — experimental/sf ( c0fd88...ff71e4 )
by
unknown
269:51 queued 261:57
created

OrderStateMachine::can()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.co.jp/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Eccube\Service;
15
16
use Eccube\Entity\Master\OrderStatus;
17
use Eccube\Entity\Order;
18
use Eccube\Entity\Shipping;
19
use Eccube\Repository\Master\OrderStatusRepository;
20
use Eccube\Service\PurchaseFlow\Processor\PointProcessor;
21
use Eccube\Service\PurchaseFlow\Processor\StockReduceProcessor;
22
use Eccube\Service\PurchaseFlow\PurchaseContext;
23
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
24
use Symfony\Component\Workflow\Event\Event;
25
use Symfony\Component\Workflow\Event\GuardEvent;
26
use Symfony\Component\Workflow\StateMachine;
27
28
class OrderStateMachine implements EventSubscriberInterface
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
29
{
30
    /**
31
     * @var StateMachine
32
     */
33
    private $machine;
34
35
    /**
36
     * @var OrderStatusRepository
37
     */
38
    private $orderStatusRepository;
39
40
    /**
41
     * @var PointProcessor
42
     */
43
    private $pointProcessor;
44
    /**
45
     * @var StockReduceProcessor
46
     */
47
    private $stockReduceProcessor;
48
49 100
    public function __construct(StateMachine $_orderStateMachine, OrderStatusRepository $orderStatusRepository, PointProcessor $pointProcessor, StockReduceProcessor $stockReduceProcessor)
50
    {
51 100
        $this->machine = $_orderStateMachine;
52 100
        $this->orderStatusRepository = $orderStatusRepository;
53 100
        $this->pointProcessor = $pointProcessor;
54 100
        $this->stockReduceProcessor = $stockReduceProcessor;
55
    }
56
57
    /**
58
     * 指定ステータスに遷移.
59
     *
60
     * @param Order $Order 受注
0 ignored issues
show
introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
introduced by
Expected 7 spaces after parameter name; 1 found
Loading history...
61
     * @param OrderStatus $OrderStatus 遷移先ステータス
62
     */
63 6
    public function apply(Order $Order, OrderStatus $OrderStatus)
64
    {
65 6
        $transition = $this->getTransition($Order, $OrderStatus);
66 6
        if ($transition) {
67 6
            $this->machine->apply($Order, $transition->getName());
68
        } else {
69
            throw new \InvalidArgumentException();
70
        }
71
    }
72
73
    /**
74
     * 指定ステータスに遷移できるかどうかを判定.
75
     *
76
     * @param Order $Order 受注
0 ignored issues
show
introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
introduced by
Expected 7 spaces after parameter name; 1 found
Loading history...
77
     * @param OrderStatus $OrderStatus 遷移先ステータス
78
     *
79
     * @return boolean 指定ステータスに遷移できる場合はtrue
80
     */
81 37
    public function can(Order $Order, OrderStatus $OrderStatus)
82
    {
83 37
        return !is_null($this->getTransition($Order, $OrderStatus));
84
    }
85
86 43
    private function getTransition(Order $Order, OrderStatus $OrderStatus)
87
    {
88 43
        $transitions = $this->machine->getEnabledTransitions($Order);
89 43
        foreach ($transitions as $t) {
90 43
            if (in_array($OrderStatus->getId(), $t->getTos())) {
91 43
                return $t;
92
            }
93
        }
94
95 25
        return null;
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101 1
    public static function getSubscribedEvents()
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
102
    {
103
        return [
104 1
            'workflow.order.completed' => ['onCompleted'],
105
            'workflow.order.transition.pay' => ['updatePaymentDate'],
106
            'workflow.order.transition.cancel' => [['rollbackStock'], ['rollbackUsePoint']],
107
            'workflow.order.transition.back_to_in_progress' => [['commitStock'], ['commitUsePoint']],
108
            'workflow.order.transition.ship' => ['commitAddPoint'],
109
            'workflow.order.transition.return' => [['rollbackUsePoint'], ['rollbackAddPoint']],
110
            'workflow.order.transition.cancel_return' => [['commitUsePoint'], ['commitAddPoint']],
111
            'workflow.order.guard.ship' => ['guardShip'],
112
        ];
113
    }
114
115
    /*
116
     * Event handlers.
117
     */
118
119
    /**
120
     * 購入日を更新する.
121
     *
122
     * @param Event $event
123
     */
124 1
    public function updatePaymentDate(Event $event)
125
    {
126
        /* @var Order $Order */
127 1
        $Order = $event->getSubject();
128 1
        $Order->setPaymentDate(new \DateTime());
129
    }
130
131
    /**
132
     * 会員の保有ポイントを減らす.
133
     *
134
     * @param Event $event
135
     *
136
     * @throws PurchaseFlow\PurchaseException
137
     */
138 2
    public function commitUsePoint(Event $event)
139
    {
140
        /* @var Order $Order */
141 2
        $Order = $event->getSubject();
142 2
        $this->pointProcessor->prepare($Order, new PurchaseContext());
143
    }
144
145
    /**
146
     * 利用ポイントを会員に戻す.
147
     *
148
     * @param Event $event
149
     */
150 2
    public function rollbackUsePoint(Event $event)
151
    {
152
        /* @var Order $Order */
153 2
        $Order = $event->getSubject();
154 2
        $this->pointProcessor->rollback($Order, new PurchaseContext());
155
    }
156
157
    /**
158
     * 在庫を減らす.
159
     *
160
     * @param Event $event
161
     *
162
     * @throws PurchaseFlow\PurchaseException
163
     */
164 1
    public function commitStock(Event $event)
165
    {
166
        /* @var Order $Order */
167 1
        $Order = $event->getSubject();
168 1
        $this->stockReduceProcessor->prepare($Order, new PurchaseContext());
169
    }
170
171
    /**
172
     * 在庫を戻す.
173
     *
174
     * @param Event $event
175
     */
176 1
    public function rollbackStock(Event $event)
177
    {
178
        /* @var Order $Order */
179 1
        $Order = $event->getSubject();
180 1
        $this->stockReduceProcessor->rollback($Order, new PurchaseContext());
181
    }
182
183
    /**
184
     * 会員に加算ポイントを付与する.
185
     *
186
     * @param Event $event
187
     */
188 2 View Code Duplication
    public function commitAddPoint(Event $event)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
    {
190
        /* @var Order $Order */
191 2
        $Order = $event->getSubject();
192 2
        $Customer = $Order->getCustomer();
193 2
        if ($Customer) {
194 2
            $Customer->setPoint(intval($Customer->getPoint()) + intval($Order->getAddPoint()));
195
        }
196
    }
197
198
    /**
199
     * 会員に付与した加算ポイントを取り消す.
200
     *
201
     * @param Event $event
202
     */
203 1 View Code Duplication
    public function rollbackAddPoint(Event $event)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
204
    {
205
        /* @var Order $Order */
206 1
        $Order = $event->getSubject();
207 1
        $Customer = $Order->getCustomer();
208 1
        if ($Customer) {
209 1
            $Customer->setPoint(intval($Customer->getPoint()) - intval($Order->getAddPoint()));
210
        }
211
    }
212
213
    /**
214
     * 受注ステータスを再設定.
215
     * {@link StateMachine}によって遷移が終了したときには{@link Order#OrderStatus}のidが変更されるだけなのでOrderStatusを設定し直す.
216
     *
217
     * @param Event $event
218
     */
219 6
    public function onCompleted(Event $event)
220
    {
221
        /** @var Order $Order */
222 6
        $Order = $event->getSubject();
223 6
        $OrderStatusId = $Order->getOrderStatus()->getId();
224 6
        $CompletedOrderStatus = $this->orderStatusRepository->find($OrderStatusId);
225 6
        $Order->setOrderStatus($CompletedOrderStatus);
226
    }
227
228
    /**
229
     * すべての出荷が発送済みなら、受注も発送済みに遷移できる.
230
     *
231
     * @param GuardEvent $event
232
     */
233 23
    public function guardShip(GuardEvent $event)
234
    {
235
        /** @var Order $Order */
236 23
        $Order = $event->getSubject();
237 23
        $UnShipped = $Order->getShippings()->filter(function (Shipping $Shipping) {
238 5
            return $Shipping->getShippingDate() == null;
239 23
        });
240 23
        if (!$UnShipped->isEmpty()) {
241 4
            $event->setBlocked(true);
242
        }
243
    }
244
}
245