Failed Conditions
Push — master ( 0f3867...8d5d22 )
by Kentaro
17:02
created

CartService::getCart()   D

Complexity

Conditions 10
Paths 11

Size

Total Lines 38
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 10

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 38
ccs 8
cts 8
cp 1
rs 4.8197
cc 10
eloc 22
nc 11
nop 0
crap 10

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * This file is part of EC-CUBE
4
 *
5
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
6
 *
7
 * http://www.lockon.co.jp/
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version 2
12
 * of the License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
 */
23
24
25
namespace Eccube\Service;
26
27
use Doctrine\ORM\EntityManager;
28
use Eccube\Common\Constant;
29
use Eccube\Entity\CartItem;
30
use Eccube\Entity\Master\Disp;
31
use Eccube\Entity\ProductClass;
32
use Eccube\Exception\CartException;
33
use Symfony\Component\HttpFoundation\Session\Session;
34
35
class CartService
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
36
{
37
    /** @var \Eccube\Application */
38
    public $app;
39
40
    /**
41
     * @var Session
42
     */
43
    private $session;
44
45
    /**
46
     * @var EntityManager
47
     */
48
    private $entityManager;
49
50
    /**
51
     * @var \Eccube\Entity\Cart
52
     */
53
    private $cart;
54
55
    /**
56
     * @var \Eccube\Entity\BaseInfo
57
     */
58
    private $BaseInfo;
59
60
    /**
61
     * @var array
62
     */
63
    private $errors = array();
64
65
    private $ProductType = null;
66
67
    /**
68
     * @var array
69
     */
70
    private $messages = array();
71
72
    /**
73
     * @var array
74
     */
75
    private $error;
76
77 109
    public function __construct(\Eccube\Application $app)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
78
    {
79 109
        $this->app = $app;
80
        $this->session = $app['session'];
81
        $this->entityManager = $app['orm.em'];
82
83
        if ($this->session->has('cart')) {
84
            $this->cart = $this->session->get('cart');
85
        } else {
86
            $this->cart = new \Eccube\Entity\Cart();
87
        }
88
89
        $this->loadProductClassFromCart();
90
91
        $this->BaseInfo = $app['eccube.repository.base_info']->get();
92
    }
93
94
    /**
95
     * カートに保存されている商品の ProductClass エンティティを読み込み、カートへ設定します。
96
     */
97 109
    protected function loadProductClassFromCart()
98
    {
99
        /* @var $softDeleteFilter \Eccube\Doctrine\Filter\SoftDeleteFilter */
100
        $softDeleteFilter = $this->entityManager->getFilters()->getFilter('soft_delete');
101
        $softDeleteFilter->setExcludes(array(
102
            'Eccube\Entity\ProductClass',
103
        ));
104
105 109
        foreach ($this->cart->getCartItems() as $CartItem) {
106
            $this->loadProductClassFromCartItem($CartItem);
107 109
        }
108
109
        $softDeleteFilter->setExcludes(array());
110 109
    }
111
112
    /**
113
     * CartItem に対応する ProductClass を設定します。
114
     *
115
     * @param CartItem $CartItem
116
     */
117 28
    protected function loadProductClassFromCartItem(CartItem $CartItem)
118
    {
119
        $ProductClass = $this
120 28
            ->entityManager
121
            ->getRepository($CartItem->getClassName())
122
            ->find($CartItem->getClassId());
123
124
        $CartItem->setObject($ProductClass);
125
126
        if (is_null($this->ProductType) && $ProductClass->getDelFlg() == Constant::DISABLED) {
127
            $this->setCanAddProductType($ProductClass->getProductType());
128
        }
129
    }
130
131 67
    public function setCanAddProductType(\Eccube\Entity\Master\ProductType $ProductType)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
132
    {
133
        if (is_null($this->ProductType)) {
134 67
            $this->ProductType = $ProductType;
135
        }
136
137 59
        return $this;
138 59
    }
139
140
    public function save()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
141
    {
142
        return $this->session->set('cart', $this->cart);
143
    }
144
145 3
    public function unlock()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
146
    {
147 3
        $this->cart
148 3
            ->setLock(false)
149
            ->setPreOrderId(null);
150 3
    }
151
152 13
    public function lock()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
153
    {
154 13
        $this->cart
155 13
            ->setLock(true)
156
            ->setPreOrderId(null);
157 13
    }
158
159
    /**
160
     * @return bool
161
     */
162
    public function isLocked()
163
    {
164
        return $this->cart->getLock();
165
    }
166
167
    /**
168
     * @param  string $pre_order_id
169
     * @return \Eccube\Service\CartService
170
     */
171 17
    public function setPreOrderId($pre_order_id)
172
    {
173
        $this->cart->setPreOrderId($pre_order_id);
174
175 17
        return $this;
176
    }
177
178
    /**
179
     * @return string
180
     */
181
    public function getPreOrderId()
182
    {
183
        return $this->cart->getPreOrderId();
184
    }
185
186
    /**
187
     * @return \Eccube\Service\CartService
188
     */
189 7
    public function clear()
190
    {
191 7
        $this->cart
192 7
            ->setPreOrderId(null)
193 7
            ->setLock(false)
194
            ->clearCartItems();
195
196 7
        return $this;
197
    }
198
199 1
    public function getCanAddProductType()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
200
    {
201 1
        return $this->ProductType;
202
    }
203
204
    /**
205
     *
206
     * @param  string $productClassId
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
207
     * @param  integer $quantity
208
     * @return \Eccube\Service\CartService
209
     */
210 24
    public function addProduct($productClassId, $quantity = 1)
211
    {
212
        $quantity += $this->getProductQuantity($productClassId);
213
        $this->setProductQuantity($productClassId, $quantity);
214
215 24
        return $this;
216 3
    }
217
218
    /**
219
     * @param  string $productClassId
220
     * @return integer
221
     */
222 26
    public function getProductQuantity($productClassId)
223
    {
224
        $CartItem = $this->cart->getCartItemByIdentifier('Eccube\Entity\ProductClass', (string) $productClassId);
225 25
        if ($CartItem) {
226
            return $CartItem->getQuantity();
227
        } else {
228 26
            return 0;
229
        }
230
    }
231
232
    /**
233
     * @param  \Eccube\Entity\ProductClass|integer $ProductClass
234
     * @param  integer $quantity
0 ignored issues
show
introduced by
Expected 29 spaces after parameter type; 1 found
Loading history...
235
     * @return \Eccube\Service\CartService
236
     * @throws CartException
237
     */
238 60
    public function setProductQuantity($ProductClass, $quantity)
239
    {
240 60
        if (!$ProductClass instanceof ProductClass) {
0 ignored issues
show
Bug introduced by
The class Eccube\Entity\ProductClass does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
241 55
            $ProductClass = $this->entityManager
242 55
                ->getRepository('Eccube\Entity\ProductClass')
243
                ->find($ProductClass);
244 55
            if (!$ProductClass) {
245
                throw new CartException('cart.product.delete');
246
            }
247
        }
248
        if ($ProductClass->getProduct()->getStatus()->getId() !== Disp::DISPLAY_SHOW) {
249
            $this->removeProduct($ProductClass->getId());
250
            throw new CartException('cart.product.not.status');
251
        }
252
253
        $productName = $ProductClass->getProduct()->getName();
254
        if ($ProductClass->hasClassCategory1()) {
255
            $productName .= " - ".$ProductClass->getClassCategory1()->getName();
256
        }
257
        if ($ProductClass->hasClassCategory2()) {
258
            $productName .= " - ".$ProductClass->getClassCategory2()->getName();
259
        }
260
261
        // 商品種別に紐づく配送業者を取得
262
        $deliveries = $this->app['eccube.repository.delivery']->getDeliveries($ProductClass->getProductType());
263
264
        if (count($deliveries) == 0) {
265
            // 商品種別が存在しなければエラー
266
            $this->removeProduct($ProductClass->getId());
267
            $this->addError('cart.product.not.producttype', $productName);
268
            throw new CartException('cart.product.not.producttype');
269
        }
270
271
        $this->setCanAddProductType($ProductClass->getProductType());
272
273
        if ($this->BaseInfo->getOptionMultipleShipping() != Constant::ENABLED) {
274
            if (!$this->canAddProduct($ProductClass->getId())) {
275
                // 複数配送対応でなければ商品種別が異なればエラー
276
                throw new CartException('cart.product.type.kind');
277
            }
278
        } else {
279
            // 複数配送の場合、同一支払方法がなければエラー
280
            if (!$this->canAddProductPayment($ProductClass->getProductType())) {
281
                throw new CartException('cart.product.payment.kind');
282
            }
283
284 59
        }
285
286 60
        $tmp_subtotal = 0;
287 60
        $tmp_quantity = 0;
288
        foreach ($this->getCart()->getCartItems() as $cartitem) {
289
            $pc = $cartitem->getObject();
290
            if ($pc->getId() != $ProductClass->getId()) {
291
                // まず、追加された商品以外のtotal priceをセット
292
                $tmp_subtotal += $cartitem->getTotalPrice();
293
            }
294 60
        }
295
        for ($i = 0; $i < $quantity; $i++) {
296
            $tmp_subtotal += $ProductClass->getPrice02IncTax();
297
            if ($tmp_subtotal > $this->app['config']['max_total_fee']) {
298
                $this->setError('cart.over.price_limit');
299 1
                break;
300
            }
301 55
            $tmp_quantity++;
302 1
        }
303 60
        $quantity = $tmp_quantity;
304
305 60
        $tmp_quantity = 0;
306
307
        /*
308
         * 実際の在庫は ProductClass::ProductStock だが、購入時にロックがかかるため、
309
         * ここでは ProductClass::stock で在庫のチェックをする
310
         */
311
        if (!$ProductClass->getStockUnlimited() && $quantity > $ProductClass->getStock()) {
312
            if ($ProductClass->getSaleLimit() && $ProductClass->getStock() > $ProductClass->getSaleLimit()) {
313
                $tmp_quantity = $ProductClass->getSaleLimit();
314
                $this->addError('cart.over.sale_limit', $productName);
315
            } else {
316
                $tmp_quantity = $ProductClass->getStock();
317
                $this->addError('cart.over.stock', $productName);
318 1
            }
319
        }
320
        if ($ProductClass->getSaleLimit() && $quantity > $ProductClass->getSaleLimit()) {
321
            $tmp_quantity = $ProductClass->getSaleLimit();
322
            $this->addError('cart.over.sale_limit', $productName);
323
        }
324 60
        if ($tmp_quantity) {
325 2
            $quantity = $tmp_quantity;
326
        }
327
328
        $CartItem = new CartItem();
329
        $CartItem
330 60
            ->setClassName('Eccube\Entity\ProductClass')
331
            ->setClassId((string) $ProductClass->getId())
332
            ->setPrice($ProductClass->getPrice02IncTax())
333
            ->setQuantity($quantity);
334
335
        $this->cart->setCartItem($CartItem);
336
337 60
        return $this;
338
    }
339
340
    /**
341
     * @param  string $productClassId
342
     * @return boolean
343
     */
344 58
    public function canAddProduct($productClassId)
345
    {
346
        $ProductClass = $this
347 58
            ->entityManager
348 58
            ->getRepository('\Eccube\Entity\ProductClass')
349
            ->find($productClassId);
350
351 58
        if (!$ProductClass) {
352
            return false;
353
        }
354
355
        $ProductType = $ProductClass->getProductType();
356
357 58
        return $this->ProductType == $ProductType;
358
    }
359
360
    /**
361
     * @param \Eccube\Entity\Master\ProductType $ProductType
362
     * @return bool
363
     */
364 5
    public function canAddProductPayment(\Eccube\Entity\Master\ProductType $ProductType)
365
    {
366
        $deliveries = $this
367 1
            ->entityManager
368 1
            ->getRepository('\Eccube\Entity\Delivery')
369
            ->findBy(array('ProductType' => $ProductType));
370
371
        // 支払方法を取得
372
        $payments = $this->entityManager->getRepository('Eccube\Entity\Payment')->findAllowedPayments($deliveries);
373
374
        if ($this->getCart()->getTotalPrice() < 1) {
375
            // カートになければ支払方法を全て設定
376
            $this->getCart()->setPayments($payments);
377 5
            return true;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
378
        }
379
380
        // カートに存在している支払方法と追加された商品の支払方法チェック
381 2
        $arr = array();
382
        foreach ($payments as $payment) {
383
            foreach ($this->getCart()->getPayments() as $p) {
384
                if ($payment['id'] == $p['id']) {
385 1
                    $arr[] = $payment;
386 1
                    break;
387
                }
388
            }
389
        }
390
391
        if (count($arr) > 0) {
392
            $this->getCart()->setPayments($arr);
393 1
            return true;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
394
        }
395
396
        // 支払条件に一致しない
397 1
        return false;
398
399 1
    }
400
401
    /**
402
     * カートを取得します。
403
     *
404
     * @return \Eccube\Entity\Cart
405
     */
406 56
    public function getCart()
407
    {
408 56
        foreach ($this->cart->getCartItems() as $CartItem) {
409
            $ProductClass = $CartItem->getObject();
410 3
            if (!$ProductClass) {
411
                $this->loadProductClassFromCartItem($CartItem);
412
413
                $ProductClass = $CartItem->getObject();
414
            }
415
416
            if ($ProductClass->getDelFlg() == Constant::DISABLED) {
417
                // 商品情報が有効
418
                $stockUnlimited = $ProductClass->getStockUnlimited();
419 3
                if ($stockUnlimited == Constant::DISABLED && $ProductClass->getStock() < 1) {
420
                    // 在庫がなければカートから削除
421
                    $this->setError('cart.zero.stock');
422
                    $this->removeProduct($ProductClass->getId());
423
                } else {
424
                    $quantity = $CartItem->getQuantity();
425
                    $saleLimit = $ProductClass->getSaleLimit();
426 3
                    if ($stockUnlimited == Constant::DISABLED && $ProductClass->getStock() < $quantity) {
427
                        // 購入数が在庫数を超えている場合、メッセージを表示
428
                        $this->setError('cart.over.stock');
429
                    } elseif (!is_null($saleLimit) && $saleLimit < $quantity) {
430
                        // 購入数が販売制限数を超えている場合、メッセージを表示
431
                        $this->setError('cart.over.sale_limit');
432
                    }
433
                }
434
            } else {
435
                // 商品情報が削除されていたらエラー
436
                $this->setError('cart.product.delete');
437
                // カートから削除
438
                $this->removeProduct($ProductClass->getId());
439 3
            }
440 56
        }
441
442 56
        return $this->cart;
443
    }
444
445
    /**
446
     * @param  string $productClassId
447
     * @return \Eccube\Service\CartService
448
     */
449 6
    public function removeProduct($productClassId)
450
    {
451
        $this->cart->removeCartItemByIdentifier('Eccube\Entity\ProductClass', (string) $productClassId);
452
453
        // 支払方法の再設定
454
        if ($this->BaseInfo->getOptionMultipleShipping() == Constant::ENABLED) {
455
456
            // 複数配送対応
457 1
            $productTypes = array();
458
            foreach ($this->getCart()->getCartItems() as $item) {
459
                /* @var $ProductClass \Eccube\Entity\ProductClass */
460
                $ProductClass = $item->getObject();
461
                $productTypes[] = $ProductClass->getProductType();
462
            }
463
464
            // 配送業者を取得
465
            $deliveries = $this->entityManager->getRepository('Eccube\Entity\Delivery')->getDeliveries($productTypes);
466
467
            // 支払方法を取得
468
            $payments = $this->entityManager->getRepository('Eccube\Entity\Payment')->findAllowedPayments($deliveries);
469
470
            $this->getCart()->setPayments($payments);
471
        }
472
473 6
        return $this;
474
    }
475
476
    /**
477
     * @param  string $error
478
     * @param  string $productName
479
     * @return \Eccube\Service\CartService
480
     */
481 6
    public function addError($error = null, $productName = null)
482
    {
483 6
        $this->errors[] = $error;
484
        $this->session->getFlashBag()->add('eccube.front.request.error', $error);
485
        if (!is_null($productName)) {
486
            $this->session->getFlashBag()->add('eccube.front.request.product', $productName);
487
        }
488 6
        return $this;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
489
    }
490
491
    /**
492
     * @param  string $productClassId
493
     * @return \Eccube\Service\CartService
494
     */
495 2
    public function upProductQuantity($productClassId)
496
    {
497
        $quantity = $this->getProductQuantity($productClassId) + 1;
498
        $this->setProductQuantity($productClassId, $quantity);
499
500 2
        return $this;
501
    }
502
503
    /**
504
     * @param  string $productClassId
505
     * @return \Eccube\Service\CartService
506
     */
507 3
    public function downProductQuantity($productClassId)
508
    {
509
        $quantity = $this->getProductQuantity($productClassId) - 1;
510
511 3
        if ($quantity > 0) {
512
            $this->setProductQuantity($productClassId, $quantity);
513
        } else {
514
            $this->removeProduct($productClassId);
515 1
        }
516
517 3
        return $this;
518
    }
519
520
    /**
521
     * @return array
522
     */
523 17
    public function getProductTypes()
524
    {
525
526 17
        $productTypes = array();
527
        foreach ($this->getCart()->getCartItems() as $item) {
528
            /* @var $ProductClass \Eccube\Entity\ProductClass */
529
            $ProductClass = $item->getObject();
530
            $productTypes[] = $ProductClass->getProductType();
531
        }
532
        return array_unique($productTypes);
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
533
534
    }
535
536
    /**
537
     * @return string[]
538
     */
539 2
    public function getErrors()
540
    {
541 2
        return $this->errors;
542
    }
543
544
    /**
545
     * @return string[]
546
     */
547
    public function getMessages()
548
    {
549
        return $this->messages;
550
    }
551
552
    /**
553
     * @param  string $message
554
     * @return \Eccube\Service\CartService
555
     */
556
    public function setMessage($message)
557
    {
558
        $this->messages[] = $message;
559
560
        return $this;
561
    }
562
563
    /**
564
     * @return string
565
     */
566 1
    public function getError()
567
    {
568 1
        return $this->error;
569
    }
570
571
    /**
572
     * @param  string $error
573
     * @return \Eccube\Service\CartService
574
     */
575 1
    public function setError($error = null)
576
    {
577 1
        $this->error = $error;
0 ignored issues
show
Documentation Bug introduced by
It seems like $error of type string or null is incompatible with the declared type array of property $error.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
578
        $this->session->getFlashBag()->set('eccube.front.request.error', $error);
579 1
        return $this;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
580
    }
581
582
}
583