Failed Conditions
Pull Request — experimental/sf (#3385)
by chihiro
62:56 queued 51:03
created

OrderStateMachine::getTransition()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

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