Failed Conditions
Pull Request — experimental/3.1 (#2322)
by Kentaro
51:06
created

OrderHelper   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 360
Duplicated Lines 6.67 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 98%

Importance

Changes 0
Metric Value
dl 24
loc 360
ccs 147
cts 150
cp 0.98
rs 10
c 0
b 0
f 0
wmc 30
lcom 1
cbo 8

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
B createProcessingOrder() 0 34 2
A createPreOrderId() 10 16 2
A setCustomer() 0 16 2
B createShipmentItemsFromCartItems() 0 38 3
B createOrderDetailsFromCartItems() 0 39 4
A addOrderDetails() 0 8 2
B createShippingFromCustomerAddress() 0 25 1
A addShipping() 0 6 1
A setDefaultDelivery() 5 23 2
B setDefaultPayment() 9 29 3
B createShipmentItemsFromOrderDetails() 0 38 5
A addShipmentItems() 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
namespace Eccube\Service;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\ORM\EntityManager;
7
use Eccube\Application;
8
use Eccube\Common\Constant;
9
use Eccube\Entity\CartItem;
10
use Eccube\Entity\Customer;
11
use Eccube\Entity\CustomerAddress;
12
use Eccube\Entity\Master\OrderItemType;
13
use Eccube\Entity\Order;
14
use Eccube\Entity\OrderDetail;
15
use Eccube\Entity\ShipmentItem;
16
use Eccube\Entity\Shipping;
17
use Eccube\Repository\DeliveryRepository;
18
use Eccube\Repository\Master\OrderItemTypeRepository;
19
use Eccube\Repository\Master\OrderStatusRepository;
20
use Eccube\Repository\Master\TaxruleRepository;
21
use Eccube\Repository\OrderRepository;
22
use Eccube\Repository\PaymentRepository;
23
use Eccube\Util\Str;
24
25
/**
26
 * OrderやOrderに関連するエンティティを構築するクラス
27
 * namespaceやクラス名は要検討
28
 *
29
 * @package Eccube\Service
30
 */
31
class OrderHelper
32
{
33
    /** @var array */
34
    protected $config;
35
36
    /** @var EntityManager */
37
    protected $em;
38
39
    /** @var OrderRepository */
40
    protected $orderRepository;
41
42
    /** @var DeliveryRepository */
43
    protected $deliveryRepository;
44
45
    /** @var DeliveryFeeRepository */
46
    protected $deliveryFeeRepository;
47
48
    /** @var PaymentRepository */
49
    protected $paymentRepository;
50
51
    /** @var TaxruleRepository */
52
    protected $taxRuleRepository;
53 32
54
    /** @var  OrderStatusRepository */
55 32
    protected $orderStatusRepository;
56 32
57 32
    /** @var OrderItemTypeRepository */
58 32
    protected $orderItemTypeRepository;
59 32
60 32
    public function __construct(Application $app)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
61 32
    {
62 32
        $this->config = $app['config'];
63
        $this->em = $app['orm.em'];
64
        $this->orderRepository = $app['eccube.repository.order'];
65
        $this->paymentRepository = $app['eccube.repository.payment'];
66
        $this->deliveryRepository = $app['eccube.repository.delivery'];
67
        $this->deliveryFeeRepository = $app['eccube.repository.delivery_fee'];
68
        $this->taxRuleRepository = $app['eccube.repository.tax_rule'];
69
        $this->orderStatusRepository = $app['eccube.repository.order_status'];
70
        $this->orderItemTypeRepository = $app['eccube.repository.master.order_item_type'];
71
    }
72
73 12
    /**
74
     * 購入処理中の受注データを生成する.
75 12
     *
76 12
     * @param Customer $Customer
0 ignored issues
show
introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
77
     * @param CustomerAddress $CustomerAddress
78
     * @param array $CartItems
0 ignored issues
show
introduced by
Expected 11 spaces after parameter type; 1 found
Loading history...
79 12
     * @return Order
80
     */
81
    public function createProcessingOrder(Customer $Customer, CustomerAddress $CustomerAddress, $CartItems)
82 12
    {
83
        $OrderStatus = $this->orderStatusRepository->find($this->config['order_processing']);
84
        $Order = new Order($OrderStatus);
85 12
86 12
        // pre_order_idを生成
87
        $Order->setPreOrderId($this->createPreOrderId());
88 12
89
        // 顧客情報の設定
90 12
        $this->setCustomer($Order, $Customer);
91 12
92 12
        // 明細情報の設定
93 12
        $ShipmentItems = $this->createShipmentItemsFromCartItems($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...
94 12
        $ShipmentItemsGroupByProductType = array_reduce($ShipmentItems, function($result, $item) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
95
            /* @var ShipmentItem $item */
96
            $productTypeId = $item->getProductClass()->getProductType()->getId();
97 12
            $result[$productTypeId][] = $item;
98
            return $result;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
99 12
        }, []);
100 12
101
        foreach ($ShipmentItemsGroupByProductType as $ShipmentItems) {
102
            $Shipping = $this->createShippingFromCustomerAddress($CustomerAddress);
103
            $this->addShipmentItems($Order, $Shipping, $ShipmentItems);
104
            $this->setDefaultDelivery($Shipping);
105 12
            $this->em->persist($Shipping);
106
        }
107
108
        $this->setDefaultPayment($Order);
109 12
110
        $this->em->persist($Order);
111 12
        $this->em->flush();
112
113 12
        return $Order;
114 12
    }
115
116
    public function createPreOrderId()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
117 12
    {
118
        // ランダムなpre_order_idを作成
119 12 View Code Duplication
        do {
120
            $preOrderId = sha1(Str::random(32));
121
122 12
            $Order = $this->orderRepository->findOneBy(
123
                [
124 12
                    'pre_order_id' => $preOrderId,
125
                    'OrderStatus' => $this->config['order_processing'],
126
                ]
127
            );
128 12
        } while ($Order);
129
130
        return $preOrderId;
131 12
    }
132
133
    public function setCustomer(Order $Order, Customer $Customer)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
134
    {
135
        if ($Customer->getId()) {
136
            $Order->setCustomer($Customer);
137
        }
138
139 12
        $Order->copyProperties(
140
            $Customer,
141 12
            [
142
                'id',
143 12
                'create_date',
144
                'update_date',
145 12
                'del_flg',
146
            ]
147 12
        );
148
    }
149 12
150 12
    /**
151
     * @param ArrayCollection $CartItems
152 12
     * @return ShipmentItem[]
153 12
     */
154 12
    private function createShipmentItemsFromCartItems($CartItems)
155 12
    {
156 12
        $ProductItemType = $this->orderItemTypeRepository->find(OrderItemType::PRODUCT);
157 12
158 12
        return array_map(function($item) use ($ProductItemType) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
159 12
            /* @var $item CartItem */
160
            /* @var $ProductClass \Eccube\Entity\ProductClass */
161 12
            $ProductClass = $item->getObject();
162 12
            /* @var $Product \Eccube\Entity\Product */
163 12
            $Product = $ProductClass->getProduct();
164 12
            $TaxRule = $this->taxRuleRepository->getByRule($Product, $ProductClass);
0 ignored issues
show
Documentation Bug introduced by
The method getByRule does not exist on object<Eccube\Repository...ster\TaxruleRepository>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
165
166 12
            $ShipmentItem = new ShipmentItem();
167 12
            $ShipmentItem
168 12
                ->setProduct($Product)
169 12
                ->setProductClass($ProductClass)
170
                ->setProductName($Product->getName())
171
                ->setProductCode($ProductClass->getCode())
172 12
                ->setPrice($ProductClass->getPrice02())
173
                ->setQuantity($item->getQuantity())
174
                ->setTaxRule($TaxRule->getId())
175 12
                ->setTaxRate($TaxRule->getTaxRate())
176
                ->setOrderItemType($ProductItemType);
177
178 12
            $ClassCategory1 = $ProductClass->getClassCategory1();
179
            if (!is_null($ClassCategory1)) {
180 12
                $ShipmentItem->setClasscategoryName1($ClassCategory1->getName());
181 12
                $ShipmentItem->setClassName1($ClassCategory1->getClassName()->getName());
182 12
            }
183
            $ClassCategory2 = $ProductClass->getClassCategory2();
184
            if (!is_null($ClassCategory2)) {
185
                $ShipmentItem->setClasscategoryName2($ClassCategory2->getName());
186 12
                $ShipmentItem->setClassName2($ClassCategory2->getClassName()->getName());
187
            }
188 12
189
            return $ShipmentItem;
190 12
        }, $CartItems->toArray());
191 12
    }
192 12
193 12
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$CartItems" missing
Loading history...
194 12
     * @deprecated
195 12
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
196 12
    public function createOrderDetailsFromCartItems($CartItems)
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
197 12
    {
198 12
        @trigger_error('The '.__METHOD__.' method is deprecated.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
199 12
        $OrderDetails = [];
200 12
201 12
        foreach ($CartItems as $item) {
202 12
            /* @var $ProductClass \Eccube\Entity\ProductClass */
203 12
            $ProductClass = $item->getObject();
204 12
            /* @var $Product \Eccube\Entity\Product */
205 12
            $Product = $ProductClass->getProduct();
206 12
207 12
            $OrderDetail = new OrderDetail();
208
            $TaxRule = $this->taxRuleRepository->getByRule($Product, $ProductClass);
0 ignored issues
show
Documentation Bug introduced by
The method getByRule does not exist on object<Eccube\Repository...ster\TaxruleRepository>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
209 12
            $OrderDetail
210
                ->setProduct($Product)
211
                ->setProductClass($ProductClass)
212 12
                ->setProductName($Product->getName())
213
                ->setProductCode($ProductClass->getCode())
214 12
                ->setPrice($ProductClass->getPrice02())
215 12
                ->setQuantity($item->getQuantity())
216
                ->setTaxRule($TaxRule->getId())
217
                ->setTaxRate($TaxRule->getTaxRate());
218 12
219
            $ClassCategory1 = $ProductClass->getClassCategory1();
220
            if (!is_null($ClassCategory1)) {
221 12
                $OrderDetail->setClasscategoryName1($ClassCategory1->getName());
222 12
                $OrderDetail->setClassName1($ClassCategory1->getClassName()->getName());
223 12
            }
224 12
            $ClassCategory2 = $ProductClass->getClassCategory2();
225 12
            if (!is_null($ClassCategory2)) {
226 12
                $OrderDetail->setClasscategoryName2($ClassCategory2->getName());
227
                $OrderDetail->setClassName2($ClassCategory2->getClassName()->getName());
228
            }
229
230 12
            $OrderDetails[] = $OrderDetail;
231
        }
232
233 12
        return $OrderDetails;
234 12
    }
235 12
236
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$Order" missing
Loading history...
introduced by
Doc comment for parameter "$OrderDetails" missing
Loading history...
237
     * @deprecated
238 12
     */
239 12
    public function addOrderDetails(Order $Order, array $OrderDetails)
240
    {
241
        @trigger_error('The '.__METHOD__.' method is deprecated.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
242 12
        foreach ($OrderDetails as $OrderDetail) {
243
            $Order->addOrderDetail($OrderDetail);
244 12
            $OrderDetail->setOrder($Order);
245
        }
246
    }
247 12
248 12
    public function createShippingFromCustomerAddress(CustomerAddress $CustomerAddress)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
249 12
    {
250 12
        $Shipping = new Shipping();
251
        $Shipping
252
            ->setName01($CustomerAddress->getName01())
253
            ->setName02($CustomerAddress->getName02())
254 12
            ->setKana01($CustomerAddress->getKana01())
255 12
            ->setKana02($CustomerAddress->getKana02())
256
            ->setCompanyName($CustomerAddress->getCompanyName())
257
            ->setTel01($CustomerAddress->getTel01())
258
            ->setTel02($CustomerAddress->getTel02())
259 12
            ->setTel03($CustomerAddress->getTel03())
260
            ->setFax01($CustomerAddress->getFax01())
261
            ->setFax02($CustomerAddress->getFax02())
262 12
            ->setFax03($CustomerAddress->getFax03())
263
            ->setZip01($CustomerAddress->getZip01())
264
            ->setZip02($CustomerAddress->getZip02())
265 12
            ->setZipCode($CustomerAddress->getZip01().$CustomerAddress->getZip02())
266 12
            ->setPref($CustomerAddress->getPref())
267 12
            ->setAddr01($CustomerAddress->getAddr01())
268 12
            ->setAddr02($CustomerAddress->getAddr02())
269
            ->setDelFlg(Constant::DISABLED);
270
271 12
        return $Shipping;
272
    }
273 12
274
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$Order" missing
Loading history...
introduced by
Doc comment for parameter "$Shipping" missing
Loading history...
275 12
     * @deprecated
276 12
     */
277 12
    public function addShipping(Order $Order, Shipping $Shipping)
278 12
    {
279
        @trigger_error('The '.__METHOD__.' method is deprecated.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
280 12
        $Order->addShipping($Shipping);
281
        $Shipping->setOrder($Order);
282 12
    }
283 12
284 12
    public function setDefaultDelivery(Shipping $Shipping)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
285 12
    {
286 12
        // 配送商品に含まれる商品種別を抽出.
287 12
        $ShipmentItems = $Shipping->getShipmentItems();
288
        $ProductTypes = [];
289 12 View Code Duplication
        foreach ($ShipmentItems as $ShipmentItem) {
290 12
            $ProductClass = $ShipmentItem->getProductClass();
291 12
            $ProductType = $ProductClass->getProductType();
292 12
            $ProductTypes[$ProductType->getId()] = $ProductType;
293
        }
294 12
295 12
        // 商品種別に紐づく配送業者を取得.
296 12
        $Deliveries = $this->deliveryRepository->getDeliveries($ProductTypes);
297 12
298
        // 初期の配送業者を設定
299 12
        $Delivery = current($Deliveries);
300 12
        $Shipping->setDelivery($Delivery);
301
        $Shipping->setShippingDeliveryName($Delivery->getName());
302 12
303
        // TODO 配送料の取得方法はこれで良いか要検討
304
        $deliveryFee = $this->deliveryFeeRepository->findOneBy(array('Delivery' => $Delivery, 'Pref' => $Shipping->getPref()));
305
        $Shipping->setShippingDeliveryFee($deliveryFee->getFee());
306 12
    }
307
308
    public function setDefaultPayment(Order $Order)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
309 12
    {
310
        $ShipmentItems = $Order->getShipmentItems();
311 12
312 12
        // 受注明細に含まれる商品種別を抽出.
313 12
        $ProductTypes = [];
314 12
        /** @var ShipmentItem $ShipmentItem */
315 12 View Code Duplication
        foreach ($ShipmentItems as $ShipmentItem) {
316
            $ProductClass = $ShipmentItem->getProductClass();
317
            if (is_null($ProductClass)) {
318
                // 商品明細のみ対象とする. 送料明細等はスキップする.
319
                continue;
320
            }
321
            $ProductType = $ProductClass->getProductType();
322
            $ProductTypes[$ProductType->getId()] = $ProductType;
323
        }
324
325
        // 商品種別に紐づく配送業者を抽出
326
        $Deliveries = $this->deliveryRepository->getDeliveries($ProductTypes);
327
328
        // 利用可能な支払い方法を抽出.
329
        $Payments = $this->paymentRepository->findAllowedPayments($Deliveries, true);
330
331
        // 初期の支払い方法を設定.
332
        $Payment = current($Payments);
333
        $Order->setPayment($Payment);
334
        $Order->setPaymentMethod($Payment->getMethod());
335
        $Order->setCharge($Payment->getCharge());
336
    }
337
338
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$OrderDetails" missing
Loading history...
introduced by
Doc comment for parameter "$groupByProductType" missing
Loading history...
339
     * @deprecated
340
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
341
    public function createShipmentItemsFromOrderDetails($OrderDetails, $groupByProductType = true)
342
    {
343
        @trigger_error('The '.__METHOD__.' method is deprecated.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
344
        $ShipmentItems = [];
345
346
        foreach ($OrderDetails as $OrderDetail) {
347
            $Product = $OrderDetail->getProduct();
348
            $ProductClass = $OrderDetail->getProductClass();
349
            $ProductType = $ProductClass->getProductType();
350
351
            $ShipmentItem = new ShipmentItem();
352
            $ShipmentItem
353
                ->setProductClass($ProductClass)
354
                ->setProduct($Product)
355
                ->setProductName($Product->getName())
356
                ->setProductCode($ProductClass->getCode())
357
                ->setPrice($ProductClass->getPrice02())
358
                ->setQuantity($OrderDetail->getQuantity());
359
360
            $ClassCategory1 = $ProductClass->getClassCategory1();
361
            if (!is_null($ClassCategory1)) {
362
                $ShipmentItem->setClasscategoryName1($ClassCategory1->getName());
363
                $ShipmentItem->setClassName1($ClassCategory1->getClassName()->getName());
364
            }
365
            $ClassCategory2 = $ProductClass->getClassCategory2();
366
            if (!is_null($ClassCategory2)) {
367
                $ShipmentItem->setClasscategoryName2($ClassCategory2->getName());
368
                $ShipmentItem->setClassName2($ClassCategory2->getClassName()->getName());
369
            }
370
            if ($groupByProductType) {
371
                $ShipmentItems[$ProductType->getId()][] = $ShipmentItem;
372
            } else {
373
                $ShipmentItems[] = $ShipmentItem;
374
            }
375
        }
376
377
        return $ShipmentItems;
378
    }
379
380
    public function addShipmentItems(Order $Order, Shipping $Shipping, array $ShipmentItems)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
381
    {
382
        foreach ($ShipmentItems as $ShipmentItem) {
383
            $Shipping->addShipmentItem($ShipmentItem);
384
            $Order->addShipmentItem($ShipmentItem);
385
            $ShipmentItem->setOrder($Order);
386
            $ShipmentItem->setShipping($Shipping);
387
        }
388
    }
389
390
}
391