Failed Conditions
Branch experimental/sf (68db07)
by Kentaro
42:17 queued 33:39
created

OrderHelper   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 336
Duplicated Lines 7.14 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 99.29%

Importance

Changes 0
Metric Value
dl 24
loc 336
rs 10
c 0
b 0
f 0
ccs 139
cts 140
cp 0.9929
wmc 22
lcom 1
cbo 11

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 23 1
A createProcessingOrder() 0 37 3
A convertToCart() 0 17 2
A createPreOrderId() 10 16 2
A setCustomer() 0 16 2
A createOrderItemsFromCartItems() 0 43 3
A createShippingFromCustomer() 0 27 1
A setDefaultDelivery() 5 20 2
A setDefaultPayment() 9 32 4
A addOrderItems() 0 9 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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\Common\Collections\ArrayCollection;
17
use Doctrine\ORM\EntityManager;
18
use Doctrine\ORM\EntityManagerInterface;
19
use Eccube\Common\EccubeConfig;
20
use Eccube\Entity\Cart;
21
use Eccube\Entity\CartItem;
22
use Eccube\Entity\Customer;
23
use Eccube\Entity\Master\OrderItemType;
24
use Eccube\Entity\Master\OrderStatus;
25
use Eccube\Entity\Master\ShippingStatus;
26
use Eccube\Entity\Master\TaxDisplayType;
27
use Eccube\Entity\Master\TaxType;
28
use Eccube\Entity\Order;
29
use Eccube\Entity\OrderItem;
30
use Eccube\Entity\Shipping;
31
use Eccube\Repository\DeliveryFeeRepository;
32
use Eccube\Repository\DeliveryRepository;
33
use Eccube\Repository\Master\OrderItemTypeRepository;
34
use Eccube\Repository\Master\OrderStatusRepository;
35
use Eccube\Repository\Master\ShippingStatusRepository;
36
use Eccube\Repository\OrderRepository;
37
use Eccube\Repository\PaymentRepository;
38
use Eccube\Repository\TaxRuleRepository;
39
use Eccube\Util\StringUtil;
40
41
/**
42
 * OrderやOrderに関連するエンティティを構築するクラス
43
 * namespaceやクラス名は要検討
44
 */
45
class OrderHelper
46
{
47
    /**
48
     * @var OrderItemTypeRepository
49
     */
50
    protected $orderItemTypeRepository;
51
52
    /**
53
     * @var OrderStatusRepository
54
     */
55
    protected $orderStatusRepository;
56
57
    /**
58
     * @var TaxRuleRepository
59
     */
60
    protected $taxRuleRepository;
61
62
    /**
63
     * @var DeliveryFeeRepository
64
     */
65
    protected $deliveryFeeRepository;
66
67
    /**
68
     * @var DeliveryRepository
69
     */
70
    protected $deliveryRepository;
71
72
    /**
73
     * @var PaymentRepository
74
     */
75
    protected $paymentRepository;
76
77
    /**
78
     * @var OrderRepository
79
     */
80
    protected $orderRepository;
81
82
    /**
83
     * @var ShippingStatusRepository
84
     */
85
    protected $shippingStatusRepository;
86
87
    /**
88
     * @var EntityManager
89
     */
90
    protected $entityManager;
91
92
    /**
93
     * @var EccubeConfig
94
     */
95
    protected $eccubeConfig;
96
97
    /**
98
     * OrderHelper constructor.
99
     *
100
     * @param OrderItemTypeRepository $orderItemTypeRepository
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
101
     * @param OrderStatusRepository $orderStatusRepository
0 ignored issues
show
introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
102
     * @param TaxRuleRepository $taxRuleRepository
0 ignored issues
show
introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
103
     * @param DeliveryFeeRepository $deliveryFeeRepository
0 ignored issues
show
introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
104
     * @param DeliveryRepository $deliveryRepository
0 ignored issues
show
introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
105
     * @param PaymentRepository $paymentRepository
0 ignored issues
show
introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
106
     * @param OrderRepository $orderRepository
0 ignored issues
show
introduced by
Expected 10 spaces after parameter type; 1 found
Loading history...
107
     * @param ShippingStatusRepository $shippingStatusRepository
108
     * @param EntityManager $entityManager
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
109
     * @param EccubeConfig $eccubeConfig
0 ignored issues
show
introduced by
Expected 13 spaces after parameter type; 1 found
Loading history...
110
     */
111 173
    public function __construct(
112
        OrderItemTypeRepository $orderItemTypeRepository,
113
        OrderStatusRepository $orderStatusRepository,
114
        TaxRuleRepository $taxRuleRepository,
115
        DeliveryFeeRepository $deliveryFeeRepository,
116
        DeliveryRepository $deliveryRepository,
117
        PaymentRepository $paymentRepository,
118
        OrderRepository $orderRepository,
119
        ShippingStatusRepository $shippingStatusRepository,
120
        EntityManagerInterface $entityManager,
121
        EccubeConfig $eccubeConfig
122
    ) {
123 173
        $this->orderItemTypeRepository = $orderItemTypeRepository;
124 173
        $this->orderStatusRepository = $orderStatusRepository;
125 173
        $this->taxRuleRepository = $taxRuleRepository;
126 173
        $this->deliveryFeeRepository = $deliveryFeeRepository;
127 173
        $this->deliveryRepository = $deliveryRepository;
128 173
        $this->paymentRepository = $paymentRepository;
129 173
        $this->orderRepository = $orderRepository;
130 173
        $this->shippingStatusRepository = $shippingStatusRepository;
131 173
        $this->entityManager = $entityManager;
0 ignored issues
show
Documentation Bug introduced by
$entityManager is of type object<Doctrine\ORM\EntityManagerInterface>, but the property $entityManager was declared to be of type object<Doctrine\ORM\EntityManager>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
132 173
        $this->eccubeConfig = $eccubeConfig;
133
    }
134
135
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$preOrderId" missing
Loading history...
136
     * 購入処理中の受注データを生成する.
137
     *
138
     * @param Customer $Customer
139
     * @param array $CartItems
0 ignored issues
show
introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
140
     *
141
     * @return Order
142
     */
143 51
    public function createProcessingOrder(Customer $Customer, $CartItems, $preOrderId = null)
144
    {
145 51
        $OrderStatus = $this->orderStatusRepository->find(OrderStatus::PROCESSING);
146 51
        $Order = new Order($OrderStatus);
147
148 51
        if (!$preOrderId) {
149
            // pre_order_idを生成
150 51
            $Order->setPreOrderId($this->createPreOrderId());
151
        }
152
153
        // 顧客情報の設定
154 51
        $this->setCustomer($Order, $Customer);
155
156
        // 明細情報の設定
157 51
        $OrderItems = $this->createOrderItemsFromCartItems($CartItems);
0 ignored issues
show
Documentation introduced by
$CartItems is of type array, but the function expects a object<Doctrine\Common\C...ctions\ArrayCollection>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
158 51
        $OrderItemsGroupBySaleType = array_reduce($OrderItems, function ($result, $item) {
159
            /* @var OrderItem $item */
160 51
            $saleTypeId = $item->getProductClass()->getSaleType()->getId();
161 51
            $result[$saleTypeId][] = $item;
162
163 51
            return $result;
164 51
        }, []);
165
166 51
        foreach ($OrderItemsGroupBySaleType as $OrderItems) {
167 51
            $Shipping = $this->createShippingFromCustomer($Customer);
168 51
            $this->addOrderItems($Order, $Shipping, $OrderItems);
169 51
            $this->setDefaultDelivery($Shipping);
170 51
            $this->entityManager->persist($Shipping);
171
        }
172
173 51
        $this->setDefaultPayment($Order);
174
175 51
        $this->entityManager->persist($Order);
176 51
        $this->entityManager->flush();
177
178 51
        return $Order;
179
    }
180
181
    /**
182
     * OrderをCartに変換します.
183
     *
184
     * @param Order $Order
185
     *
186
     * @return Cart
187
     */
188 2
    public function convertToCart(Order $Order)
189
    {
190 2
        $Cart = new Cart();
191 2
        $Cart->setPreOrderId($Order->getPreOrderId());
192
        /** @var OrderItem $OrderItem */
193 2
        foreach ($Order->getProductOrderItems() as $OrderItem) {
194 1
            $CartItem = new CartItem();
195 1
            $ProductClass = $OrderItem->getProductClass();
196 1
            $this->entityManager->refresh($ProductClass);
197 1
            $CartItem->setProductClass($ProductClass);
198 1
            $CartItem->setPrice($OrderItem->getPriceIncTax());
199 1
            $CartItem->setQuantity($OrderItem->getQuantity());
200 1
            $Cart->addCartItem($CartItem);
201
        }
202
203 2
        return $Cart;
204
    }
205
206 51
    private function createPreOrderId()
207
    {
208
        // ランダムなpre_order_idを作成
209 View Code Duplication
        do {
210 51
            $preOrderId = sha1(StringUtil::random(32));
211
212 51
            $Order = $this->orderRepository->findOneBy(
213
                [
214 51
                    'pre_order_id' => $preOrderId,
215
                    'OrderStatus' => OrderStatus::PROCESSING,
216
                ]
217
            );
218 51
        } while ($Order);
219
220 51
        return $preOrderId;
221
    }
222
223 51
    private function setCustomer(Order $Order, Customer $Customer)
224
    {
225 51
        if ($Customer->getId()) {
226 34
            $Order->setCustomer($Customer);
227
        }
228
229 51
        $Order->copyProperties(
230 51
            $Customer,
231
            [
232 51
                'id',
233
                'create_date',
234
                'update_date',
235
                'del_flg',
236
            ]
237
        );
238
    }
239
240
    /**
241
     * @param ArrayCollection $CartItems
242
     *
243
     * @return OrderItem[]
244
     */
245 51
    private function createOrderItemsFromCartItems($CartItems)
246
    {
247 51
        $ProductItemType = $this->orderItemTypeRepository->find(OrderItemType::PRODUCT);
248
        // TODO
249 51
        $TaxExclude = $this->entityManager->getRepository(TaxDisplayType::class)->find(TaxDisplayType::EXCLUDED);
250 51
        $Taxion = $this->entityManager->getRepository(TaxType::class)->find(TaxType::TAXATION);
251
252 51
        return array_map(function ($item) use ($ProductItemType, $TaxExclude, $Taxion) {
253
            /* @var $item CartItem */
254
            /* @var $ProductClass \Eccube\Entity\ProductClass */
255 51
            $ProductClass = $item->getProductClass();
256
            /* @var $Product \Eccube\Entity\Product */
257 51
            $Product = $ProductClass->getProduct();
258 51
            $TaxRule = $this->taxRuleRepository->getByRule($Product, $ProductClass);
259
260 51
            $OrderItem = new OrderItem();
261
            $OrderItem
262 51
                ->setProduct($Product)
263 51
                ->setProductClass($ProductClass)
264 51
                ->setProductName($Product->getName())
265 51
                ->setProductCode($ProductClass->getCode())
266 51
                ->setPrice($ProductClass->getPrice02())
267 51
                ->setQuantity($item->getQuantity())
268 51
                ->setTaxRule($TaxRule->getId())
269 51
                ->setTaxRate($TaxRule->getTaxRate())
270 51
                ->setOrderItemType($ProductItemType)
271 51
                ->setTaxDisplayType($TaxExclude)
272 51
                ->setTaxType($Taxion);
273
274 51
            $ClassCategory1 = $ProductClass->getClassCategory1();
275 51
            if (!is_null($ClassCategory1)) {
276 51
                $OrderItem->setClasscategoryName1($ClassCategory1->getName());
277 51
                $OrderItem->setClassName1($ClassCategory1->getClassName()->getName());
278
            }
279 51
            $ClassCategory2 = $ProductClass->getClassCategory2();
280 51
            if (!is_null($ClassCategory2)) {
281 38
                $OrderItem->setClasscategoryName2($ClassCategory2->getName());
282 38
                $OrderItem->setClassName2($ClassCategory2->getClassName()->getName());
283
            }
284
285 51
            return $OrderItem;
286 51
        }, $CartItems->toArray());
287
    }
288
289 51
    private function createShippingFromCustomer(Customer $Customer)
290
    {
291 51
        $Shipping = new Shipping();
292
        $Shipping
293 51
            ->setName01($Customer->getName01())
294 51
            ->setName02($Customer->getName02())
295 51
            ->setKana01($Customer->getKana01())
296 51
            ->setKana02($Customer->getKana02())
297 51
            ->setCompanyName($Customer->getCompanyName())
298 51
            ->setTel01($Customer->getTel01())
299 51
            ->setTel02($Customer->getTel02())
300 51
            ->setTel03($Customer->getTel03())
301 51
            ->setFax01($Customer->getFax01())
302 51
            ->setFax02($Customer->getFax02())
303 51
            ->setFax03($Customer->getFax03())
304 51
            ->setZip01($Customer->getZip01())
305 51
            ->setZip02($Customer->getZip02())
306 51
            ->setZipCode($Customer->getZip01().$Customer->getZip02())
307 51
            ->setPref($Customer->getPref())
308 51
            ->setAddr01($Customer->getAddr01())
309 51
            ->setAddr02($Customer->getAddr02());
310
311 51
        $ShippingStatus = $this->shippingStatusRepository->find(ShippingStatus::PREPARED);
312 51
        $Shipping->setShippingStatus($ShippingStatus);
313
314 51
        return $Shipping;
315
    }
316
317 51
    private function setDefaultDelivery(Shipping $Shipping)
318
    {
319
        // 配送商品に含まれる販売種別を抽出.
320 51
        $OrderItems = $Shipping->getOrderItems();
321 51
        $SaleTypes = [];
322
        /** @var OrderItem $OrderItem */
323 51 View Code Duplication
        foreach ($OrderItems as $OrderItem) {
324 51
            $ProductClass = $OrderItem->getProductClass();
325 51
            $SaleType = $ProductClass->getSaleType();
326 51
            $SaleTypes[$SaleType->getId()] = $SaleType;
327
        }
328
329
        // 販売種別に紐づく配送業者を取得.
330 51
        $Deliveries = $this->deliveryRepository->getDeliveries($SaleTypes);
331
332
        // 初期の配送業者を設定
333 51
        $Delivery = current($Deliveries);
334 51
        $Shipping->setDelivery($Delivery);
335 51
        $Shipping->setShippingDeliveryName($Delivery->getName());
336
    }
337
338 51
    private function setDefaultPayment(Order $Order)
339
    {
340 51
        $OrderItems = $Order->getOrderItems();
341
342
        // 受注明細に含まれる販売種別を抽出.
343 51
        $SaleTypes = [];
344
        /** @var OrderItem $OrderItem */
345 51 View Code Duplication
        foreach ($OrderItems as $OrderItem) {
346 51
            $ProductClass = $OrderItem->getProductClass();
347 51
            if (is_null($ProductClass)) {
348
                // 商品明細のみ対象とする. 送料明細等はスキップする.
349
                continue;
350
            }
351 51
            $SaleType = $ProductClass->getSaleType();
352 51
            $SaleTypes[$SaleType->getId()] = $SaleType;
353
        }
354
355
        // 販売種別に紐づく配送業者を抽出
356 51
        $Deliveries = $this->deliveryRepository->getDeliveries($SaleTypes);
357
358
        // 利用可能な支払い方法を抽出.
359 51
        $Payments = $this->paymentRepository->findAllowedPayments($Deliveries, true);
360
361
        // 初期の支払い方法を設定.
362 51
        $Payment = current($Payments);
363 51
        if ($Payment) {
364 51
            $Order->setPayment($Payment);
365 51
            $Order->setPaymentMethod($Payment->getMethod());
366
        }
367
        // TODO CalculateChargeStrategy でセットする
368
        // $Order->setCharge($Payment->getCharge());
369
    }
370
371 51
    private function addOrderItems(Order $Order, Shipping $Shipping, array $OrderItems)
372
    {
373 51
        foreach ($OrderItems as $OrderItem) {
374 51
            $Shipping->addOrderItem($OrderItem);
375 51
            $Order->addOrderItem($OrderItem);
376 51
            $OrderItem->setOrder($Order);
377 51
            $OrderItem->setShipping($Shipping);
378
        }
379
    }
380
}
381