CartService   D
last analyzed

Complexity

Total Complexity 83

Size/Duplication

Total Lines 694
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 7

Test Coverage

Coverage 91.18%

Importance

Changes 0
Metric Value
dl 0
loc 694
rs 4.472
c 0
b 0
f 0
ccs 93
cts 102
cp 0.9118
wmc 83
lcom 2
cbo 7

32 Methods

Rating   Name   Duplication   Size   Complexity  
A isLocked() 0 4 1
A addProduct() 0 7 1
A __construct() 0 16 2
A loadProductClassFromCart() 0 15 2
A loadProductClassFromCartItem() 0 13 3
A setCanAddProductType() 0 8 2
A save() 0 4 1
A unlock() 0 6 1
A lock() 0 6 1
A setPreOrderId() 0 6 1
A getPreOrderId() 0 4 1
A clear() 0 9 1
A getCanAddProductType() 0 4 1
A getProductQuantity() 0 9 2
D setProductQuantity() 0 80 14
A canAddProduct() 0 15 2
B canAddProductPayment() 0 38 6
B getCartObj() 0 24 4
C getCart() 0 42 7
B removeProduct() 0 26 3
B addError() 0 23 4
A upProductQuantity() 0 7 1
A downProductQuantity() 0 9 2
A getProductTypes() 0 13 2
A getErrors() 0 4 1
A getMessages() 0 4 1
A setMessage() 0 6 1
A getError() 0 4 1
A setError() 0 7 1
A getProductName() 0 15 3
A isProductDisplay() 0 12 2
C setProductLimit() 0 62 8

How to fix   Complexity   

Complex Class

Complex classes like CartService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CartService, and based on these observations, apply Extract Interface, too.

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 72
77
    public function __construct(\Eccube\Application $app)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
78 72
    {
79
        $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 72
89
        $this->loadProductClassFromCart();
90
91
        $this->BaseInfo = $app['eccube.repository.base_info']->get();
92
    }
93
94
    /**
95
     * カートに保存されている商品の ProductClass エンティティを読み込み、カートへ設定します。
96 72
     */
97
    protected function loadProductClassFromCart()
98
    {
99
        /* @var $softDeleteFilter \Eccube\Doctrine\Filter\SoftDeleteFilter */
100
        $softDeleteFilter = $this->entityManager->getFilters()->getFilter('soft_delete');
101
        $excludes = $softDeleteFilter->getExcludes();
102 46
        $softDeleteFilter->setExcludes(array(
103
            'Eccube\Entity\ProductClass',
104
        ));
105 46
106
        foreach ($this->cart->getCartItems() as $CartItem) {
107
            $this->loadProductClassFromCartItem($CartItem);
108 38
        }
109 38
110
        $softDeleteFilter->setExcludes($excludes);
111
    }
112
113
    /**
114
     * CartItem に対応する ProductClass を設定します。
115
     *
116 1
     * @param CartItem $CartItem
117
     */
118 1
    protected function loadProductClassFromCartItem(CartItem $CartItem)
119 1
    {
120
        $ProductClass = $this
121 1
            ->entityManager
122
            ->getRepository($CartItem->getClassName())
123 1
            ->find($CartItem->getClassId());
124
125 1
        $CartItem->setObject($ProductClass);
126 1
127
        if (is_null($this->ProductType) && $ProductClass->getDelFlg() == Constant::DISABLED) {
128 1
            $this->setCanAddProductType($ProductClass->getProductType());
129
        }
130
    }
131
132
    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...
133
    {
134
        if (is_null($this->ProductType)) {
135
            $this->ProductType = $ProductType;
136
        }
137
138
        return $this;
139
    }
140
141
    public function save()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
142 7
    {
143
        return $this->session->set('cart', $this->cart);
144
    }
145
146 7
    public function unlock()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
147
    {
148
        $this->cart
149
            ->setLock(false)
150
            ->setPreOrderId(null);
151
    }
152
153
    public function lock()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
154
    {
155
        $this->cart
156
            ->setLock(true)
157
            ->setPreOrderId(null);
158
    }
159
160 3
    /**
161
     * @return bool
162 3
     */
163 3
    public function isLocked()
164 3
    {
165
        return $this->cart->getLock();
166
    }
167 3
168
    /**
169
     * @param  string $pre_order_id
170 1
     * @return \Eccube\Service\CartService
171
     */
172 1
    public function setPreOrderId($pre_order_id)
173
    {
174
        $this->cart->setPreOrderId($pre_order_id);
175
176
        return $this;
177
    }
178
179
    /**
180
     * @return string
181 5
     */
182
    public function getPreOrderId()
183
    {
184
        return $this->cart->getPreOrderId();
185
    }
186 5
187 3
    /**
188
     * @return \Eccube\Service\CartService
189
     */
190
    public function clear()
191
    {
192
        $this->cart
193 7
            ->setPreOrderId(null)
194
            ->setLock(false)
195
            ->clearCartItems();
196 6
197
        return $this;
198
    }
199 7
200
    public function getCanAddProductType()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
201
    {
202
        return $this->ProductType;
203
    }
204
205
    /**
206
     *
207
     * @param  string $productClassId
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
208
     * @param  integer $quantity
209 39
     * @return \Eccube\Service\CartService
210
     */
211 39
    public function addProduct($productClassId, $quantity = 1)
212 34
    {
213 34
        $quantity += $this->getProductQuantity($productClassId);
214
        $this->setProductQuantity($productClassId, $quantity);
215 34
216
        return $this;
217
    }
218
219
    /**
220
     * @param  string $productClassId
221
     * @return integer
222
     */
223
    public function getProductQuantity($productClassId)
224
    {
225
        $CartItem = $this->cart->getCartItemByIdentifier('Eccube\Entity\ProductClass', (string)$productClassId);
0 ignored issues
show
Coding Style introduced by
As per coding-style, a cast statement should be followed by a single space.
Loading history...
226
        if ($CartItem) {
227
            return $CartItem->getQuantity();
228
        } else {
229
            return 0;
230
        }
231
    }
232
233
    /**
234
     * @param  \Eccube\Entity\ProductClass|integer $ProductClass
235
     * @param  integer $quantity
0 ignored issues
show
introduced by
Expected 29 spaces after parameter type; 1 found
Loading history...
236
     * @return \Eccube\Service\CartService
237 38
     * @throws CartException
238
     */
239 39
    public function setProductQuantity($ProductClass, $quantity)
240 39
    {
241
        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...
242
            $ProductClass = $this->entityManager
243
                ->getRepository('Eccube\Entity\ProductClass')
244
                ->find($ProductClass);
245
            if (!$ProductClass) {
246
                throw new CartException('cart.product.delete');
247 39
            }
248
        }
249
250
        if (!$this->isProductDisplay($ProductClass)) {
251
            throw new CartException('cart.product.not.status');
252 1
        }
253
254 34
        $productName = $this->getProductName($ProductClass);
255 1
256 39
        // 商品種別に紐づく配送業者を取得
257
        $deliveries = $this->app['eccube.repository.delivery']->getDeliveries($ProductClass->getProductType());
258 39
259
        if (count($deliveries) == 0) {
260
            // 商品種別が存在しなければエラー
261
            $this->removeProduct($ProductClass->getId());
262
            $this->addError('cart.product.not.producttype', $productName);
263
            throw new CartException('cart.product.not.producttype');
264
        }
265
266
        $this->setCanAddProductType($ProductClass->getProductType());
267
268
        if ($this->BaseInfo->getOptionMultipleShipping() != Constant::ENABLED) {
269
            if (!$this->canAddProduct($ProductClass->getId())) {
270
                // 複数配送対応でなければ商品種別が異なればエラー
271
                throw new CartException('cart.product.type.kind');
272
            }
273
        } else {
274
            // 複数配送の場合、同一支払方法がなければエラー
275
            if (!$this->canAddProductPayment($ProductClass->getProductType())) {
276
                throw new CartException('cart.product.payment.kind');
277
            }
278 1
        }
279
280
        $tmp_subtotal = 0;
281
        $tmp_quantity = 0;
282
        foreach ($this->getCartObj()->getCartItems() as $cartitem) {
283
            $pc = $cartitem->getObject();
284 39
            if ($pc->getId() != $ProductClass->getId()) {
285 2
                // 追加された商品以外のtotal priceをセット
286
                $tmp_subtotal += $cartitem->getTotalPrice();
287
            }
288
        }
289
        for ($i = 0; $i < $quantity; $i++) {
290 39
            $tmp_subtotal += $ProductClass->getPrice02IncTax();
291
            if ($tmp_subtotal > $this->app['config']['max_total_fee']) {
292
                $this->setError('cart.over.price_limit');
293
                break;
294
            }
295
            $tmp_quantity++;
296
        }
297 39
        if ($tmp_quantity == 0) {
298
            // 数量が0の場合、エラー
299
            throw new CartException('cart.over.price_limit');
300
        }
301
302
        // 制限数チェック(在庫不足の場合は、処理の中でカート内商品を削除している)
303
        $quantity = $this->setProductLimit($ProductClass, $productName, $tmp_quantity);
304 37
305
		// 新しい数量でカート内商品を登録する
306
        if (0 < $quantity) {
307 37
            $CartItem = new CartItem();
308 37
            $CartItem
309
                ->setClassName('Eccube\Entity\ProductClass')
310
                ->setClassId((string)$ProductClass->getId())
0 ignored issues
show
Coding Style introduced by
As per coding-style, a cast statement should be followed by a single space.
Loading history...
311
                ->setPrice($ProductClass->getPrice02IncTax())
312 37
                ->setQuantity($quantity);
313
314
            $this->cart->setCartItem($CartItem);
315
        }
316
317
        return $this;
318
    }
319 5
320
    /**
321
     * @param  string $productClassId
322 1
     * @return boolean
323 1
     */
324
    public function canAddProduct($productClassId)
325
    {
326
        $ProductClass = $this
327
            ->entityManager
328
            ->getRepository('\Eccube\Entity\ProductClass')
329
            ->find($productClassId);
330
331
        if (!$ProductClass) {
332 5
            return false;
333
        }
334
335
        $ProductType = $ProductClass->getProductType();
336 2
337
        return $this->ProductType == $ProductType;
338
    }
339
340 1
    /**
341 1
     * @param \Eccube\Entity\Master\ProductType $ProductType
342
     * @return bool
343
     */
344
    public function canAddProductPayment(\Eccube\Entity\Master\ProductType $ProductType)
345
    {
346
        $deliveries = $this
347
            ->entityManager
348 1
            ->getRepository('\Eccube\Entity\Delivery')
349
            ->findBy(array('ProductType' => $ProductType));
350
351
        // 支払方法を取得
352 1
        $payments = $this->entityManager->getRepository('Eccube\Entity\Payment')->findAllowedPayments($deliveries);
353
354 1
        if ($this->getCart()->getTotalPrice() < 1) {
355
            // カートになければ支払方法を全て設定
356 42
            $this->getCart()->setPayments($payments);
357
358
            return true;
359
        }
360
361
        // カートに存在している支払方法と追加された商品の支払方法チェック
362
        $arr = array();
363
        foreach ($payments as $payment) {
364 42
            foreach ($this->getCart()->getPayments() as $p) {
365
                if ($payment['id'] == $p['id']) {
366 3
                    $arr[] = $payment;
367
                    break;
368
                }
369
            }
370
        }
371
372
        if (count($arr) > 0) {
373
            $this->getCart()->setPayments($arr);
374
375 3
            return true;
376
        }
377
378
        // 支払条件に一致しない
379
        return false;
380
381
    }
382
383 3
    /**
384
     * カートブロックに表示するカートを取得します。
385
     * ブロックに表示するカートはチェックを行わず、セットされているカートを返します。
386
     *
387
     * @return \Eccube\Entity\Cart
388
     */
389
    public function getCartObj()
390
    {
391
392
        foreach ($this->cart->getCartItems() as $CartItem) {
393
394
            /** @var \Eccube\Entity\ProductClass $ProductClass */
395
            $ProductClass = $CartItem->getObject();
396
            if (!$ProductClass) {
397
                $this->loadProductClassFromCartItem($CartItem);
398
399 3
                $ProductClass = $CartItem->getObject();
400
            }
401 42
402
            if ($ProductClass->getDelFlg()) {
403 42
                // 商品情報が削除されていたらエラー
404
                $this->setError('cart.product.delete');
405
                // カートから削除
406
                $this->removeProduct($ProductClass->getId());
407
            }
408
        }
409
410 6
        return $this->cart;
411
412
    }
413
414
    /**
415
     * カートを取得します。
416
     *
417
     * @return \Eccube\Entity\Cart
418 1
     */
419
    public function getCart()
420
    {
421
        foreach ($this->cart->getCartItems() as $CartItem) {
422
423
            /** @var \Eccube\Entity\ProductClass $ProductClass */
424
            $ProductClass = $CartItem->getObject();
425
            if (!$ProductClass) {
426
                $this->loadProductClassFromCartItem($CartItem);
427
428
                $ProductClass = $CartItem->getObject();
429
            }
430
431
            if ($ProductClass->getDelFlg() == Constant::DISABLED) {
432
                // 商品情報が有効
433
434 6
                if (!$this->isProductDisplay($ProductClass)) {
435
                    $this->setError('cart.product.not.status');
436
                } else {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
437
438
                    $productName = $this->getProductName($ProductClass);
439
440
                    // 制限数チェック(在庫不足の場合は、処理の中でカート内商品を削除している)
441
                    $quantity = $this->setProductLimit($ProductClass, $productName, $CartItem->getQuantity());
442 6
443
                    /// 個数が異なれば、新しい数量でカート内商品を更新する
444 6
                    if ((0 < $quantity) && ($CartItem->getQuantity() != $quantity)) {
445
                        // 個数が異なれば更新
446
                        $CartItem->setQuantity($quantity);
447
                        $this->cart->setCartItem($CartItem);
448
                    }
449 6
                }
450
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
451
            } else {
452
                // 商品情報が削除されていたらエラー
453
                $this->setError('cart.product.delete');
454
                // カートから削除
455
                $this->removeProduct($ProductClass->getId());
456 2
            }
457
        }
458
459
        return $this->cart;
460
    }
461 2
462
    /**
463
     * @param  string $productClassId
464
     * @return \Eccube\Service\CartService
465
     */
466
    public function removeProduct($productClassId)
467
    {
468 3
        $this->cart->removeCartItemByIdentifier('Eccube\Entity\ProductClass', (string)$productClassId);
0 ignored issues
show
Coding Style introduced by
As per coding-style, a cast statement should be followed by a single space.
Loading history...
469
470
        // 支払方法の再設定
471
        if ($this->BaseInfo->getOptionMultipleShipping() == Constant::ENABLED) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
472 3
473
            // 複数配送対応
474
            $productTypes = array();
475
            foreach ($this->getCart()->getCartItems() as $item) {
476 1
                /* @var $ProductClass \Eccube\Entity\ProductClass */
477
                $ProductClass = $item->getObject();
478 3
                $productTypes[] = $ProductClass->getProductType();
479
            }
480
481
            // 配送業者を取得
482
            $deliveries = $this->entityManager->getRepository('Eccube\Entity\Delivery')->getDeliveries($productTypes);
483
484 7
            // 支払方法を取得
485
            $payments = $this->entityManager->getRepository('Eccube\Entity\Payment')->findAllowedPayments($deliveries);
486
487 7
            $this->getCart()->setPayments($payments);
488
        }
489
490
        return $this;
491
    }
492
493
    /**
494
     * @param  string $error
495
     * @param  string $productName
496
     * @return \Eccube\Service\CartService
497
     */
498
    public function addError($error = null, $productName = null)
499
    {
500 2
        // Filter duplicate
501
        $arrError = $this->session->getFlashBag()->peek('eccube.front.request.error');
502 2
        $arrProduct = $this->session->getFlashBag()->peek('eccube.front.request.product');
503
        if (in_array($error, $arrError) && in_array($productName, $arrProduct)) {
504
            return $this;
505
        }
506
507
        $this->errors[] = $error;
508
        $this->session->getFlashBag()->add('eccube.front.request.error', $error);
509
        if (!is_null($productName)) {
510
            // 追加されているエラーのキーを取得する
511
            $cnt = $this->session->getFlashBag()->peek('eccube.front.request.error');
512
            end($cnt);
513
            $key = key($cnt);
514
            // エラーと同じキー商品名を設定する
515
            $arrProduct[$key] = $productName;
516
            $this->session->getFlashBag()->set('eccube.front.request.product', $arrProduct);
517
        }
518
519
        return $this;
520
    }
521
522
    /**
523
     * @param  string $productClassId
524
     * @return \Eccube\Service\CartService
525
     */
526
    public function upProductQuantity($productClassId)
527 1
    {
528
        $quantity = $this->getProductQuantity($productClassId) + 1;
529 1
        $this->setProductQuantity($productClassId, $quantity);
530
531
        return $this;
532
    }
533
534
    /**
535
     * @param  string $productClassId
536 1
     * @return \Eccube\Service\CartService
537
     */
538 1
    public function downProductQuantity($productClassId)
539
    {
540 1
        $quantity = $this->getProductQuantity($productClassId) - 1;
541
        if ($quantity > 0) {
542
            $this->setProductQuantity($productClassId, $quantity);
543
        }
544
545
        return $this;
546
    }
547
548
    /**
549
     * @return array
550
     */
551
    public function getProductTypes()
552
    {
553
554
        $productTypes = array();
555
        foreach ($this->getCart()->getCartItems() as $item) {
556
            /* @var $ProductClass \Eccube\Entity\ProductClass */
557
            $ProductClass = $item->getObject();
558
            $productTypes[] = $ProductClass->getProductType();
559
        }
560
561
        return array_unique($productTypes);
562
563
    }
564
565
    /**
566
     * @return string[]
567
     */
568
    public function getErrors()
569
    {
570
        return $this->errors;
571
    }
572
573
    /**
574
     * @return string[]
575
     */
576
    public function getMessages()
577
    {
578
        return $this->messages;
579
    }
580
581
    /**
582
     * @param  string $message
583
     * @return \Eccube\Service\CartService
584
     */
585
    public function setMessage($message)
586
    {
587
        $this->messages[] = $message;
588
589
        return $this;
590
    }
591
592
    /**
593
     * @return string
594
     */
595
    public function getError()
596
    {
597
        return $this->error;
598
    }
599
600
    /**
601
     * @param  string $error
602
     * @return \Eccube\Service\CartService
603
     */
604
    public function setError($error = null)
605
    {
606
        $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...
607
        $this->session->getFlashBag()->set('eccube.front.request.error', $error);
608
609
        return $this;
610
    }
611
612
    /**
613
     * 商品名を取得
614
     *
615
     * @param ProductClass $ProductClass
616
     * @return string
617
     */
618
    private function getProductName(ProductClass $ProductClass)
619
    {
620
621
        $productName = $ProductClass->getProduct()->getName();
622
623
        if ($ProductClass->hasClassCategory1()) {
624
            $productName .= " - ".$ProductClass->getClassCategory1()->getName();
625
        }
626
627
        if ($ProductClass->hasClassCategory2()) {
628
            $productName .= " - ".$ProductClass->getClassCategory2()->getName();
629
        }
630
631
        return $productName;
632
    }
633
634
635
    /**
636
     * 非公開商品の場合、カートから削除
637
     *
638
     * @param ProductClass $ProductClass
639
     * @return bool
640
     */
641
    private function isProductDisplay(ProductClass $ProductClass)
642
    {
643
644
        if ($ProductClass->getProduct()->getStatus()->getId() !== Disp::DISPLAY_SHOW) {
645
            // 非公開の商品はカートから削除
646
            $this->removeProduct($ProductClass->getId());
647
648
            return false;
649
        }
650
651
        return true;
652
    }
653
654
655
    /**
656
     * 在庫数と販売制限数のチェック
657
     * 在庫数または販売制限数以上の個数が設定されていれば、それぞれの個数にセットし、
658
     * 在庫数と販売制限数ともに個数が超えていれば、少ない方を適用させてメッセージを表示する
659
     *
660
     * @param ProductClass $ProductClass
661
     * @param $productName
662
     * @param $quantity
663
     * @return int チェック後に更新した個数
664
     */
665
    private function setProductLimit(ProductClass $ProductClass, $productName, $quantity)
666
    {
667
668
        /**
669
         * 実際の在庫は ProductClass::ProductStock だが、購入時にロックがかかるため、
670
         * ここでは ProductClass::stock で在庫のチェックをする
671
         */
672
673
        // 在庫数(在庫無制限の場合、null)
674
        $stock = $ProductClass->getStock();
675
        // 在庫無制限(在庫無制限の場合、1)
676
        $stockUnlimited = $ProductClass->getStockUnlimited();
677
678
        // 販売制限数(設定されていなければnull)
679
        $saleLimit = $ProductClass->getSaleLimit();
680
681
        if ($stockUnlimited) {
682
            // 在庫無制限
683
684
            if ($saleLimit && $saleLimit < $quantity) {
685
                // 販売制限数を超えていれば販売制限数をセット
686
                $this->addError('cart.over.sale_limit', $productName);
687
688
                return $saleLimit;
689
            }
690
        } else {
691
            // 在庫制限あり
692
693
            if ($stock < 1) {
694
                // 在庫がなければカートから削除
695
                $this->addError('cart.zero.stock', $productName);
696
                $this->removeProduct($ProductClass->getId());
697
698
                return 0;
699
            } else {
700
                // 在庫数チェックと販売制限数チェックどちらを適用するか設定
701
                $message = 'cart.over.stock';
702
                if ($saleLimit) {
703
                    if ($stock > $saleLimit) {
704
                        // 販売制限数チェック
705
                        $limit = $saleLimit;
706
                        $message = 'cart.over.sale_limit';
707
                    } else {
708
                        // 在庫数チェック
709
                        $limit = $stock;
710
                    }
711
                } else {
712
                    // 在庫数チェック
713
                    $limit = $stock;
714
                }
715
716
                if ($limit < $quantity) {
717
                    // 在庫数、販売制限数を超えていれば購入可能数までをセット
718
                    $this->addError($message, $productName);
719
720
                    return $limit;
721
                }
722
            }
723
        }
724
725
        return $quantity;
726
    }
727
728
}
729