Completed
Pull Request — experimental/sf (#3402)
by Kiyotaka
45:23 queued 04:32
created

OrderStateMachineContext::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 5
ccs 3
cts 3
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\Repository\Master\OrderStatusRepository;
19
use Eccube\Service\PurchaseFlow\Processor\PointProcessor;
20
use Eccube\Service\PurchaseFlow\Processor\StockReduceProcessor;
21
use Eccube\Service\PurchaseFlow\PurchaseContext;
22
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
23
use Symfony\Component\Workflow\Event\Event;
24
use Symfony\Component\Workflow\StateMachine;
25
26
class OrderStateMachine implements EventSubscriberInterface
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
27
{
28
    /**
29
     * @var StateMachine
30
     */
31
    private $machine;
32
33
    /**
34
     * @var OrderStatusRepository
35
     */
36
    private $orderStatusRepository;
37
38
    /**
39
     * @var PointProcessor
40
     */
41
    private $pointProcessor;
42
    /**
43
     * @var StockReduceProcessor
44
     */
45
    private $stockReduceProcessor;
46
47 140
    public function __construct(StateMachine $_orderStateMachine, OrderStatusRepository $orderStatusRepository, PointProcessor $pointProcessor, StockReduceProcessor $stockReduceProcessor)
48
    {
49 140
        $this->machine = $_orderStateMachine;
50 140
        $this->orderStatusRepository = $orderStatusRepository;
51 140
        $this->pointProcessor = $pointProcessor;
52 140
        $this->stockReduceProcessor = $stockReduceProcessor;
53
    }
54
55
    /**
56
     * 指定ステータスに遷移.
57
     *
58
     * @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...
59
     * @param OrderStatus $OrderStatus 遷移先ステータス
60
     */
61 11
    public function apply(Order $Order, OrderStatus $OrderStatus)
62
    {
63 11
        $context = $this->newContext($Order);
64 11
        $transition = $this->getTransition($context, $OrderStatus);
65 11
        if ($transition) {
66 11
            $this->machine->apply($context, $transition->getName());
67
        } else {
68
            throw new \InvalidArgumentException();
69
        }
70
    }
71
72
    /**
73
     * 指定ステータスに遷移できるかどうかを判定.
74
     *
75
     * @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...
76
     * @param OrderStatus $OrderStatus 遷移先ステータス
77
     *
78
     * @return boolean 指定ステータスに遷移できる場合はtrue
79
     */
80 44
    public function can(Order $Order, OrderStatus $OrderStatus)
81
    {
82 44
        return !is_null($this->getTransition($this->newContext($Order), $OrderStatus));
83
    }
84
85 50
    private function getTransition(OrderStateMachineContext $context, OrderStatus $OrderStatus)
86
    {
87 50
        $transitions = $this->machine->getEnabledTransitions($context);
88 50
        foreach ($transitions as $t) {
89 47
            if (in_array($OrderStatus->getId(), $t->getTos())) {
90 47
                return $t;
91
            }
92
        }
93
94 30
        return null;
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100 1
    public static function getSubscribedEvents()
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
101
    {
102
        return [
103 1
            'workflow.order.completed' => ['onCompleted'],
104
            'workflow.order.transition.pay' => ['updatePaymentDate'],
105
            'workflow.order.transition.cancel' => [['rollbackStock'], ['rollbackUsePoint']],
106
            'workflow.order.transition.back_to_in_progress' => [['commitStock'], ['commitUsePoint']],
107
            'workflow.order.transition.ship' => [['commitAddPoint'], ['updateShippingDate']],
108
            'workflow.order.transition.return' => [['rollbackUsePoint'], ['rollbackAddPoint']],
109
            'workflow.order.transition.cancel_return' => [['commitUsePoint'], ['commitAddPoint']],
110
        ];
111
    }
112
113
    /*
114
     * Event handlers.
115
     */
116
117
    /**
118
     * 入金日を更新する.
119
     *
120
     * @param Event $event
121
     */
122 1
    public function updatePaymentDate(Event $event)
123
    {
124
        /* @var Order $Order */
125 1
        $Order = $event->getSubject()->getOrder();
126 1
        $Order->setPaymentDate(new \DateTime());
127
    }
128
129
    /**
130
     * 発送日を更新する.
131
     *
132
     * @param Event $event
133
     */
134 3
    public function updateShippingDate(Event $event)
135
    {
136
        // TODO: 出荷に出荷日を入れる処理は出荷ごとに実行される可能性があるのでステートマシン外で処理する必要がある
137
        /* @var Order $Order */
138 3
        $Order = $event->getSubject()->getOrder();
139 3
        foreach ($Order->getShippings() as $Shipping) {
140 3
            if (!$Shipping->getShippingDate()) {
141 3
                $Shipping->setShippingDate(new \DateTime());
142
            }
143
        }
144
    }
145
146
    /**
147
     * 会員の保有ポイントを減らす.
148
     *
149
     * @param Event $event
150
     *
151
     * @throws PurchaseFlow\PurchaseException
152
     */
153 2
    public function commitUsePoint(Event $event)
154
    {
155
        /* @var Order $Order */
156 2
        $Order = $event->getSubject()->getOrder();
157 2
        $this->pointProcessor->prepare($Order, new PurchaseContext());
158
    }
159
160
    /**
161
     * 利用ポイントを会員に戻す.
162
     *
163
     * @param Event $event
164
     */
165 2
    public function rollbackUsePoint(Event $event)
166
    {
167
        /* @var Order $Order */
168 2
        $Order = $event->getSubject()->getOrder();
169 2
        $this->pointProcessor->rollback($Order, new PurchaseContext());
170
    }
171
172
    /**
173
     * 在庫を減らす.
174
     *
175
     * @param Event $event
176
     *
177
     * @throws PurchaseFlow\PurchaseException
178
     */
179 1
    public function commitStock(Event $event)
180
    {
181
        /* @var Order $Order */
182 1
        $Order = $event->getSubject()->getOrder();
183 1
        $this->stockReduceProcessor->prepare($Order, new PurchaseContext());
184
    }
185
186
    /**
187
     * 在庫を戻す.
188
     *
189
     * @param Event $event
190
     */
191 1
    public function rollbackStock(Event $event)
192
    {
193
        /* @var Order $Order */
194 1
        $Order = $event->getSubject()->getOrder();
195 1
        $this->stockReduceProcessor->rollback($Order, new PurchaseContext());
196
    }
197
198
    /**
199
     * 会員に加算ポイントを付与する.
200
     *
201
     * @param Event $event
202
     */
203 4 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...
204
    {
205
        /* @var Order $Order */
206 4
        $Order = $event->getSubject()->getOrder();
207 4
        $Customer = $Order->getCustomer();
208 4
        if ($Customer) {
209 4
            $Customer->setPoint(intval($Customer->getPoint()) + intval($Order->getAddPoint()));
210
        }
211
    }
212
213
    /**
214
     * 会員に付与した加算ポイントを取り消す.
215
     *
216
     * @param Event $event
217
     */
218 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...
219
    {
220
        /* @var Order $Order */
221 1
        $Order = $event->getSubject()->getOrder();
222 1
        $Customer = $Order->getCustomer();
223 1
        if ($Customer) {
224 1
            $Customer->setPoint(intval($Customer->getPoint()) - intval($Order->getAddPoint()));
225
        }
226
    }
227
228
    /**
229
     * 受注ステータスを再設定.
230
     * {@link StateMachine}によって遷移が終了したときには{@link Order#OrderStatus}のidが変更されるだけなのでOrderStatusを設定し直す.
231
     *
232
     * @param Event $event
233
     */
234 11
    public function onCompleted(Event $event)
235
    {
236
        /** @var $context OrderStateMachineContext */
237 11
        $context = $event->getSubject();
238 11
        $Order = $context->getOrder();
239 11
        $CompletedOrderStatus = $this->orderStatusRepository->find($context->getStatus());
240 11
        $Order->setOrderStatus($CompletedOrderStatus);
241
    }
242
243 50
    private function newContext(Order $Order)
244
    {
245 50
        return new OrderStateMachineContext((string) $Order->getOrderStatus()->getId(), $Order);
246
    }
247
}
248
249
class OrderStateMachineContext
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
introduced by
Multiple classes defined in a single file
Loading history...
introduced by
Missing class doc comment
Loading history...
250
{
251
    /** @var string */
252
    private $status;
253
254
    /** @var Order */
255
    private $Order;
256
257
    /**
258
     * OrderStateMachineContext constructor.
259
     *
260
     * @param string $status
261
     * @param Order $Order
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
262
     */
263 50
    public function __construct($status, Order $Order)
264
    {
265 50
        $this->status = $status;
266 50
        $this->Order = $Order;
267
    }
268
269
    /**
270
     * @return string
271
     */
272 50
    public function getStatus()
273
    {
274 50
        return $this->status;
275
    }
276
277
    /**
278
     * @param string $status
279
     */
280 11
    public function setStatus($status)
281
    {
282 11
        $this->status = $status;
283
    }
284
285
    /**
286
     * @return Order
287
     */
288 11
    public function getOrder()
289
    {
290 11
        return $this->Order;
291
    }
292
}
293