Failed Conditions
Pull Request — experimental/3.1 (#2273)
by
unknown
38:41
created

CartService::addCartItem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 7
ccs 3
cts 3
cp 1
crap 1
rs 9.4285
c 1
b 0
f 0
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 182
    public function __construct(\Eccube\Application $app)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
78
    {
79 182
        $this->app = $app;
80 182
        $this->session = $app['session'];
81 182
        $this->entityManager = $app['orm.em'];
82
83 182
        if ($this->session->has('cart')) {
84
            $this->cart = $this->session->get('cart');
85
        } else {
86 182
            $this->cart = new \Eccube\Entity\Cart();
87
        }
88
89 182
        $this->loadProductClassFromCart();
90
91 182
        $this->BaseInfo = $app['eccube.repository.base_info']->get();
92
    }
93
94
    /**
95
     * カートに保存されている商品の ProductClass エンティティを読み込み、カートへ設定します。
96
     */
97
    protected function loadProductClassFromCart()
98
    {
99
        /* @var $softDeleteFilter \Eccube\Doctrine\Filter\SoftDeleteFilter */
100
        // $softDeleteFilter = $this->entityManager->getFilters()->getFilter('soft_delete');
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
101
        // $excludes = $softDeleteFilter->getExcludes();
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
102
        // $softDeleteFilter->setExcludes(array(
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
103
        //     'Eccube\Entity\ProductClass',
104
        // ));
105
106
        // foreach ($this->cart->getCartItems() as $CartItem) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
107
        //     $this->loadProductClassFromCartItem($CartItem);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
108
        // }
109
110
        // $softDeleteFilter->setExcludes($excludes);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
111
    }
112
113
    /**
114
     * CartItem に対応する ProductClass を設定します。
115
     *
116
     * @param CartItem $CartItem
117
     */
118 48
    protected function loadProductClassFromCartItem(CartItem $CartItem)
119
    {
120
        $ProductClass = $this
121 48
            ->entityManager
122 48
            ->getRepository($CartItem->getClassName())
123 48
            ->find($CartItem->getClassId());
124
125 48
        $CartItem->setObject($ProductClass);
126
127 48
        if (is_null($this->ProductType) && $ProductClass->getDelFlg() == Constant::DISABLED) {
128
            $this->setCanAddProductType($ProductClass->getProductType());
129
        }
130
    }
131
132 88
    public function setCanAddProductType(\Eccube\Entity\Master\ProductType $ProductType)
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
introduced by
Missing function doc comment
Loading history...
133
    {
134 88
        if (is_null($this->ProductType)) {
135 88
            $this->ProductType = $ProductType;
136
        }
137
138 88
        return $this;
139
    }
140
141 82
    public function save()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
142
    {
143 82
        return $this->session->set('cart', $this->cart);
144
    }
145
146 4
    public function unlock()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
147
    {
148 4
        $this->cart
149 4
            ->setLock(false)
150 4
            ->setPreOrderId(null);
151
    }
152
153 38
    public function lock()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
154
    {
155 38
        $this->cart
156 38
            ->setLock(true)
157 38
            ->setPreOrderId(null);
158
    }
159
160
    /**
161
     * @return bool
162
     */
163 45
    public function isLocked()
164
    {
165 45
        return $this->cart->getLock();
166
    }
167
168
    /**
169
     * @param  string $pre_order_id
170
     * @return \Eccube\Service\CartService
171
     */
172 20
    public function setPreOrderId($pre_order_id)
173
    {
174 20
        $this->cart->setPreOrderId($pre_order_id);
175
176 20
        return $this;
177
    }
178
179
    /**
180
     * @return string
181
     */
182 39
    public function getPreOrderId()
183
    {
184 39
        return $this->cart->getPreOrderId();
185
    }
186
187
    /**
188
     * @return \Eccube\Service\CartService
189
     */
190 4
    public function clear()
191
    {
192 4
        $this->cart
193 4
            ->setPreOrderId(null)
194 4
            ->setLock(false)
195 4
            ->clearCartItems();
196
197 4
        return $this;
198
    }
199
200 1
    public function getCanAddProductType()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
201
    {
202 1
        return $this->ProductType;
203
    }
204
205
    /**
206
     * @param ProductClass|integer $ProductClass 商品規格エンティティ、またはそのID
207
     * @return CartItem
208
     * @throws CartException
209
     */
210
    public function generateCartItem($ProductClass)
211 44
    {
212 View Code Duplication
        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...
Duplication introduced by
This code seems to be duplicated across 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...
213 44
            $ProductClass = $this->entityManager
214 44
                ->getRepository('Eccube\Entity\ProductClass')
215
                ->find($ProductClass);
216 43
            if (!$ProductClass) {
217
                throw new CartException('cart.product.delete');
218
            }
219
        }
220
        $CartItem = new CartItem();
221
        $CartItem
222
            ->setClassName('Eccube\Entity\ProductClass')
223 53
            ->setObject($ProductClass)
224
            ->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...
225 53
            ->setPrice($ProductClass->getPrice02IncTax())
226 53
            ->setQuantity(1);
227 7
        return $CartItem;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
228
    }
229 51
230
    /**
231
     * カート商品を追加する
232
     *
233
     * @param  CartItem $CartItem
234
     * @return \Eccube\Service\CartService
235
     */
236
    public function addCartItem($CartItem)
237
    {
238
        $quantity = $CartItem->getQuantity() + $this->getCartItemQuantity($CartItem);
239 91
        $this->setCartItemQuantity($CartItem, $quantity);
240
241 91
        return $this;
242 86
    }
243 86
244 86
    /**
245 86
     * カート商品の数量を取得する
246 3
     *
247
     * @param CartItem $CartItem
248
     * @return int
249 88
     */
250 1
    public function getCartItemQuantity($CartItem)
251 1
    {
252
        $compareService = $this->generateCartCompareService();
253
        $ExistsCartItem = $compareService->getExistsCartItem($CartItem);
254 87
        return $ExistsCartItem ?
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
255 87
            $ExistsCartItem->getQuantity() :
256 87
            0;
257
    }
258 87
259 85
    /**
260
     * @param  CartItem $CartItem
261
     * @param  integer $quantity
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
262
     * @return \Eccube\Service\CartService
263 87
     * @throws CartException
264
     */
265 87
    public function setCartItemQuantity($CartItem, $quantity)
266
    {
267
        /** @var ProductClass $ProductClass */
268
        $ProductClass = $CartItem->getObject();
269
270
        if (!$this->isProductDisplay($ProductClass)) {
271
            throw new CartException('cart.product.not.status');
272 87
        }
273
274 87
        $productName = $this->getProductName($ProductClass);
275 79
276
        // 商品種別に紐づく配送業者を取得
277 79
        $deliveries = $this->app['eccube.repository.delivery']->getDeliveries($ProductClass->getProductType());
278
279
        if (count($deliveries) == 0) {
280
            // 商品種別が存在しなければエラー
281 8
            $this->removeCartItem($CartItem);
282 1
            $this->addError('cart.product.not.producttype', $productName);
283
            throw new CartException('cart.product.not.producttype');
284
        }
285
286
        $this->setCanAddProductType($ProductClass->getProductType());
287 87
288 87 View Code Duplication
        if ($this->BaseInfo->getOptionMultipleShipping() != Constant::ENABLED) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
289 87
            if (!$this->canAddProduct($ProductClass->getId())) {
290 8
                // 複数配送対応でなければ商品種別が異なればエラー
291 8
                throw new CartException('cart.product.type.kind');
292
            }
293 87
        } else {
294
            // 複数配送の場合、同一支払方法がなければエラー
295
            if (!$this->canAddProductPayment($ProductClass->getProductType())) {
296 87
                throw new CartException('cart.product.payment.kind');
297 87
            }
298 87
        }
299 1
300 1
        $compareService = $this->generateCartCompareService();
301
        $tmp_subtotal = 0;
302 86
        $tmp_quantity = 0;
303
        foreach ($this->getCartObj()->getCartItems() as $CurrentCartItem) {
304 87
            if (!$compareService->compare($CartItem, $CurrentCartItem)) {
305
                // 追加された商品以外のtotal priceをセット
306 87
                $tmp_subtotal += $CurrentCartItem->getTotalPrice();
307
            }
308
        }
309 View Code Duplication
        for ($i = 0; $i < $quantity; $i++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
310
            $tmp_subtotal += $ProductClass->getPrice02IncTax();
311
            if ($tmp_subtotal > $this->app['config']['max_total_fee']) {
312 87
                $this->setError('cart.over.price_limit');
313 2
                break;
314 1
            }
315 1
            $tmp_quantity++;
316
        }
317 1
        if ($tmp_quantity == 0) {
318 1
            // 数量が0の場合、エラー
319
            throw new CartException('cart.over.price_limit');
320
        }
321 87
322 2
        // 制限数チェック(在庫不足の場合は、処理の中でカート内商品を削除している)
323 2
        $quantity = $this->setProductLimit($ProductClass, $productName, $tmp_quantity);
324
325 87
        // 新しい数量でカート内商品を登録する
326 3
        if (0 < $quantity) {
327
            $CartItem->setQuantity($quantity);
328
            $this->cart->setCartItem($CartItem, $compareService);
329 87
        }
330
331 87
        return $this;
332 87
    }
333 87
334 87
    /**
335
     * @param  CartItem $CartItem
336 87
     * @return \Eccube\Service\CartService
337
     */
338 87 View Code Duplication
    public function removeCartItem($CartItem)
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...
339
    {
340
        $compareService = $this->generateCartCompareService();
341
        $this->cart->removeCartItemByCartItem($CartItem, $compareService);
342
343
        // 支払方法の再設定
344
        if ($this->BaseInfo->getOptionMultipleShipping() == Constant::ENABLED) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
345 79
346
            // 複数配送対応
347
            $productTypes = array();
348 79
            foreach ($this->getCart()->getCartItems() as $item) {
349 79
                /* @var $ProductClass \Eccube\Entity\ProductClass */
350 79
                $ProductClass = $item->getObject();
351
                $productTypes[] = $ProductClass->getProductType();
352 79
            }
353
354
            // 配送業者を取得
355
            $deliveries = $this->entityManager->getRepository('Eccube\Entity\Delivery')->getDeliveries($productTypes);
356 79
357
            // 支払方法を取得
358 79
            $payments = $this->entityManager->getRepository('Eccube\Entity\Payment')->findAllowedPayments($deliveries);
359
360
            $this->getCart()->setPayments($payments);
361
        }
362
363
        return $this;
364
    }
365 9
366
    /**
367
     *
368 9
     * @param  string $productClassId
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
369 9
     * @param  integer $quantity
370 9
     * @return \Eccube\Service\CartService
371
     */
372
    public function addProduct($productClassId, $quantity = 1)
373 9
    {
374
        $quantity += $this->getProductQuantity($productClassId);
375 9
        $this->setProductQuantity($productClassId, $quantity);
376
377 9
        return $this;
378 9
    }
379
380
    /**
381
     * @param  string $productClassId
382 7
     * @return integer
383 7
     */
384 7
    public function getProductQuantity($productClassId)
385 7
    {
386 6
        $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...
387 7
        if ($CartItem) {
388
            return $CartItem->getQuantity();
389
        } else {
390
            return 0;
391
        }
392 7
    }
393 6
394 6
    /**
395
     * @param  \Eccube\Entity\ProductClass|integer $ProductClass
396
     * @param  integer $quantity
0 ignored issues
show
introduced by
Expected 29 spaces after parameter type; 1 found
Loading history...
397
     * @return \Eccube\Service\CartService
398 1
     * @throws CartException
399
     */
400
    public function setProductQuantity($ProductClass, $quantity)
401
    {
402 View Code Duplication
        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...
Duplication introduced by
This code seems to be duplicated across 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...
403
            $ProductClass = $this->entityManager
404
                ->getRepository('Eccube\Entity\ProductClass')
405
                ->find($ProductClass);
406
            if (!$ProductClass) {
407 158
                throw new CartException('cart.product.delete');
408
            }
409 158
        }
410 48
411 48
        if (!$this->isProductDisplay($ProductClass)) {
412 48
            throw new CartException('cart.product.not.status');
413
        }
414 48
415
        $productName = $this->getProductName($ProductClass);
416
417 48
        // 商品種別に紐づく配送業者を取得
418
        $deliveries = $this->app['eccube.repository.delivery']->getDeliveries($ProductClass->getProductType());
419 48
420 48
        if (count($deliveries) == 0) {
421
            // 商品種別が存在しなければエラー
422
            $this->removeProduct($ProductClass->getId());
423
            $this->addError('cart.product.not.producttype', $productName);
424
            throw new CartException('cart.product.not.producttype');
425 48
        }
426 48
427 48
        $this->setCanAddProductType($ProductClass->getProductType());
428
429 View Code Duplication
        if ($this->BaseInfo->getOptionMultipleShipping() != Constant::ENABLED) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
430 48
            if (!$this->canAddProduct($ProductClass->getId())) {
431
                // 複数配送対応でなければ商品種別が異なればエラー
432 48
                throw new CartException('cart.product.type.kind');
433
            }
434
        } else {
435
            // 複数配送の場合、同一支払方法がなければエラー
436
            if (!$this->canAddProductPayment($ProductClass->getProductType())) {
437
                throw new CartException('cart.product.payment.kind');
438
            }
439 158
        }
440
441
        $tmp_subtotal = 0;
442
        $tmp_quantity = 0;
443 158
        foreach ($this->getCartObj()->getCartItems() as $cartitem) {
444
            $pc = $cartitem->getObject();
445
            if ($pc->getId() != $ProductClass->getId()) {
446
                // 追加された商品以外のtotal priceをセット
447
                $tmp_subtotal += $cartitem->getTotalPrice();
448
            }
449
        }
450 9 View Code Duplication
        for ($i = 0; $i < $quantity; $i++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
451
            $tmp_subtotal += $ProductClass->getPrice02IncTax();
452 9
            if ($tmp_subtotal > $this->app['config']['max_total_fee']) {
453
                $this->setError('cart.over.price_limit');
454
                break;
455 9
            }
456
            $tmp_quantity++;
457
        }
458 1
        if ($tmp_quantity == 0) {
459 1
            // 数量が0の場合、エラー
460
            throw new CartException('cart.over.price_limit');
461 1
        }
462 1
463
        // 制限数チェック(在庫不足の場合は、処理の中でカート内商品を削除している)
464
        $quantity = $this->setProductLimit($ProductClass, $productName, $tmp_quantity);
465
466 1
		// 新しい数量でカート内商品を登録する
467
        if (0 < $quantity) {
468
            $CartItem = new CartItem();
469 1
            $CartItem
470
                ->setClassName('Eccube\Entity\ProductClass')
471 1
                ->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...
472
                ->setPrice($ProductClass->getPrice02IncTax())
473
                ->setQuantity($quantity);
474 9
475
            $this->cart->setCartItem($CartItem, $this->generateCartCompareService());
476
        }
477
478
        return $this;
479
    }
480
481
    /**
482 4
     * @param  string $productClassId
483
     * @return boolean
484 4
     */
485 4
    public function canAddProduct($productClassId)
486 4
    {
487 3
        $ProductClass = $this
488
            ->entityManager
489 4
            ->getRepository('\Eccube\Entity\ProductClass')
490
            ->find($productClassId);
491
492
        if (!$ProductClass) {
493
            return false;
494
        }
495
496 4
        $ProductType = $ProductClass->getProductType();
497
498 4
        return $this->ProductType == $ProductType;
499 4
    }
500
501 3
    /**
502
     * @param \Eccube\Entity\Master\ProductType $ProductType
503
     * @return bool
504
     */
505
    public function canAddProductPayment(\Eccube\Entity\Master\ProductType $ProductType)
506
    {
507
        $deliveries = $this
508 5
            ->entityManager
509
            ->getRepository('\Eccube\Entity\Delivery')
510 5
            ->findBy(array('ProductType' => $ProductType));
511
512 5
        // 支払方法を取得
513 1
        $payments = $this->entityManager->getRepository('Eccube\Entity\Payment')->findAllowedPayments($deliveries);
514
515 4
        if ($this->getCart()->getTotalPrice() < 1) {
516
            // カートになければ支払方法を全て設定
517
            $this->getCart()->setPayments($payments);
518 5
519
            return true;
520
        }
521
522
        // カートに存在している支払方法と追加された商品の支払方法チェック
523
        $arr = array();
524 20
        foreach ($payments as $payment) {
525
            foreach ($this->getCart()->getPayments() as $p) {
526
                if ($payment['id'] == $p['id']) {
527 20
                    $arr[] = $payment;
528 20
                    break;
529
                }
530 20
            }
531 20
        }
532
533 20
        if (count($arr) > 0) {
534
            $this->getCart()->setPayments($arr);
535
536
            return true;
537
        }
538
539
        // 支払条件に一致しない
540 3
        return false;
541
542 3
    }
543
544
    /**
545
     * カートブロックに表示するカートを取得します。
546
     * ブロックに表示するカートはチェックを行わず、セットされているカートを返します。
547
     *
548 1
     * @return \Eccube\Entity\Cart
549
     */
550 1
    public function getCartObj()
551
    {
552
553
        foreach ($this->cart->getCartItems() as $CartItem) {
554
555
            /** @var \Eccube\Entity\ProductClass $ProductClass */
556
            $ProductClass = $CartItem->getObject();
557 1
            if (!$ProductClass) {
558
                $this->loadProductClassFromCartItem($CartItem);
559 1
560
                $ProductClass = $CartItem->getObject();
561 1
            }
562
563
            if ($ProductClass->getDelFlg()) {
564
                // 商品情報が削除されていたらエラー
565
                $this->setError('cart.product.delete');
566
                // カートから削除
567 1
                $this->removeProduct($ProductClass->getId());
568
            }
569 1
        }
570
571
        return $this->cart;
572
573
    }
574
575
    /**
576 1
     * カートを取得します。
577
     *
578 1
     * @return \Eccube\Entity\Cart
579 1
     */
580 1
    public function getCart()
581
    {
582
        foreach ($this->cart->getCartItems() as $CartItem) {
583
584
            /** @var \Eccube\Entity\ProductClass $ProductClass */
585
            $ProductClass = $CartItem->getObject();
586
            if (!$ProductClass) {
587
                $this->loadProductClassFromCartItem($CartItem);
588
589
                $ProductClass = $CartItem->getObject();
590
            }
591
592
            if ($ProductClass->getDelFlg() == Constant::DISABLED) {
593
                // 商品情報が有効
594
595
                if (!$this->isProductDisplay($ProductClass)) {
596
                    $this->setError('cart.product.not.status');
597
                } else {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
598
599
                    $productName = $this->getProductName($ProductClass);
600
601
                    // 制限数チェック(在庫不足の場合は、処理の中でカート内商品を削除している)
602
                    $quantity = $this->setProductLimit($ProductClass, $productName, $CartItem->getQuantity());
603
604
                    /// 個数が異なれば、新しい数量でカート内商品を更新する
605
                    if ((0 < $quantity) && ($CartItem->getQuantity() != $quantity)) {
606
                        // 個数が異なれば更新
607
                        $CartItem->setQuantity($quantity);
608
                        $this->cart->setCartItem($CartItem, $this->generateCartCompareService());
609
                    }
610
                }
611
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
612
            } else {
613
                // 商品情報が削除されていたらエラー
614
                $this->setError('cart.product.delete');
615
                // カートから削除
616
                $this->removeProduct($ProductClass->getId());
617
            }
618
        }
619
620
        return $this->cart;
621
    }
622
623
    /**
624
     * @param  string $productClassId
625
     * @return \Eccube\Service\CartService
626
     */
627 View Code Duplication
    public function removeProduct($productClassId)
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...
628
    {
629
        $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...
630
631
        // 支払方法の再設定
632
        if ($this->BaseInfo->getOptionMultipleShipping() == Constant::ENABLED) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
633
634
            // 複数配送対応
635
            $productTypes = array();
636
            foreach ($this->getCart()->getCartItems() as $item) {
637
                /* @var $ProductClass \Eccube\Entity\ProductClass */
638
                $ProductClass = $item->getObject();
639
                $productTypes[] = $ProductClass->getProductType();
640
            }
641
642
            // 配送業者を取得
643
            $deliveries = $this->entityManager->getRepository('Eccube\Entity\Delivery')->getDeliveries($productTypes);
644
645
            // 支払方法を取得
646
            $payments = $this->entityManager->getRepository('Eccube\Entity\Payment')->findAllowedPayments($deliveries);
647
648
            $this->getCart()->setPayments($payments);
649
        }
650
651
        return $this;
652
    }
653
654
    /**
655
     * @param  string $error
656
     * @param  string $productName
657
     * @return \Eccube\Service\CartService
658
     */
659
    public function addError($error = null, $productName = null)
660
    {
661
        $this->errors[] = $error;
662
        $this->session->getFlashBag()->add('eccube.front.request.error', $error);
663
        if (!is_null($productName)) {
664
            $this->session->getFlashBag()->add('eccube.front.request.product', $productName);
665
        }
666
667
        return $this;
668
    }
669
670
    /**
671
     * @param  string $productClassId
672
     * @return \Eccube\Service\CartService
673
     */
674
    public function upProductQuantity($productClassId)
675
    {
676
        $quantity = $this->getProductQuantity($productClassId) + 1;
677
        $this->setProductQuantity($productClassId, $quantity);
678
679
        return $this;
680
    }
681
682
    /**
683
     * @param  string $productClassId
684
     * @return \Eccube\Service\CartService
685
     */
686
    public function downProductQuantity($productClassId)
687
    {
688
        $quantity = $this->getProductQuantity($productClassId) - 1;
689
        if ($quantity > 0) {
690
            $this->setProductQuantity($productClassId, $quantity);
691
        }
692
693
        return $this;
694
    }
695
696
    /**
697
     * @return array
698
     */
699
    public function getProductTypes()
700
    {
701
702
        $productTypes = array();
703
        foreach ($this->getCart()->getCartItems() as $item) {
704
            /* @var $ProductClass \Eccube\Entity\ProductClass */
705
            $ProductClass = $item->getObject();
706
            $productTypes[] = $ProductClass->getProductType();
707
        }
708
709
        return array_unique($productTypes);
710
711
    }
712
713
    /**
714
     * @return string[]
715
     */
716
    public function getErrors()
717
    {
718
        return $this->errors;
719
    }
720
721
    /**
722
     * @return string[]
723
     */
724
    public function getMessages()
725
    {
726
        return $this->messages;
727
    }
728
729
    /**
730
     * @param  string $message
731
     * @return \Eccube\Service\CartService
732
     */
733
    public function setMessage($message)
734
    {
735
        $this->messages[] = $message;
736
737
        return $this;
738
    }
739
740
    /**
741
     * @return string
742
     */
743
    public function getError()
744
    {
745
        return $this->error;
746
    }
747
748
    /**
749
     * @param  string $error
750
     * @return \Eccube\Service\CartService
751
     */
752
    public function setError($error = null)
753
    {
754
        $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...
755
        $this->session->getFlashBag()->set('eccube.front.request.error', $error);
756
757
        return $this;
758
    }
759
760
    /**
761
     * 商品名を取得
762
     *
763
     * @param ProductClass $ProductClass
764
     * @return string
765
     */
766
    private function getProductName(ProductClass $ProductClass)
767
    {
768
769
        $productName = $ProductClass->getProduct()->getName();
770
771
        if ($ProductClass->hasClassCategory1()) {
772
            $productName .= " - ".$ProductClass->getClassCategory1()->getName();
773
        }
774
775
        if ($ProductClass->hasClassCategory2()) {
776
            $productName .= " - ".$ProductClass->getClassCategory2()->getName();
777
        }
778
779
        return $productName;
780
    }
781
782
783
    /**
784
     * 非公開商品の場合、カートから削除
785
     *
786
     * @param ProductClass $ProductClass
787
     * @return bool
788
     */
789
    private function isProductDisplay(ProductClass $ProductClass)
790
    {
791
792
        if ($ProductClass->getProduct()->getStatus()->getId() !== Disp::DISPLAY_SHOW) {
793
            // 非公開の商品はカートから削除
794
            $this->removeProduct($ProductClass->getId());
795
796
            return false;
797
        }
798
799
        return true;
800
    }
801
802
803
    /**
804
     * 在庫数と販売制限数のチェック
805
     * 在庫数または販売制限数以上の個数が設定されていれば、それぞれの個数にセットし、
806
     * 在庫数と販売制限数ともに個数が超えていれば、少ない方を適用させてメッセージを表示する
807
     *
808
     * @param ProductClass $ProductClass
809
     * @param $productName
810
     * @param $quantity
811
     * @return int チェック後に更新した個数
812
     */
813
    private function setProductLimit(ProductClass $ProductClass, $productName, $quantity)
814
    {
815
816
        /**
817
         * 実際の在庫は ProductClass::ProductStock だが、購入時にロックがかかるため、
818
         * ここでは ProductClass::stock で在庫のチェックをする
819
         */
820
821
        // 在庫数(在庫無制限の場合、null)
822
        $stock = $ProductClass->getStock();
823
        // 在庫無制限(在庫無制限の場合、1)
824
        $stockUnlimited = $ProductClass->getStockUnlimited();
825
826
        // 販売制限数(設定されていなければnull)
827
        $saleLimit = $ProductClass->getSaleLimit();
828
829
        if ($stockUnlimited) {
830
            // 在庫無制限
831
832
            if ($saleLimit && $saleLimit < $quantity) {
833
                // 販売制限数を超えていれば販売制限数をセット
834
                $this->addError('cart.over.sale_limit', $productName);
835
836
                return $saleLimit;
837
            }
838
        } else {
839
            // 在庫制限あり
840
841
            if ($stock < 1) {
842
                // 在庫がなければカートから削除
843
                $this->addError('cart.zero.stock', $productName);
844
                $this->removeProduct($ProductClass->getId());
845
846
                return 0;
847
            } else {
848
                // 在庫数チェックと販売制限数チェックどちらを適用するか設定
849
                $message = 'cart.over.stock';
850
                if ($saleLimit) {
851
                    if ($stock > $saleLimit) {
852
                        // 販売制限数チェック
853
                        $limit = $saleLimit;
854
                        $message = 'cart.over.sale_limit';
855
                    } else {
856
                        // 在庫数チェック
857
                        $limit = $stock;
858
                    }
859
                } else {
860
                    // 在庫数チェック
861
                    $limit = $stock;
862
                }
863
864
                if ($limit < $quantity) {
865
                    // 在庫数、販売制限数を超えていれば購入可能数までをセット
866
                    $this->addError($message, $productName);
867
868
                    return $limit;
869
                }
870
            }
871
        }
872
873
        return $quantity;
874
    }
875
876
    /**
877
     * @return \Eccube\Service\CartCompareService
878
     */
879
    public function generateCartCompareService()
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
880
    {
881
        return $this->app['eccube.service.cart.compare']($this->getCart());
882
    }
883
}
884