Completed
Push — master ( eec493...b2acb8 )
by Aimeos
02:39
created

Select::addProduct()   B

Complexity

Conditions 6
Paths 17

Size

Total Lines 57
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 34
c 4
b 0
f 0
dl 0
loc 57
rs 8.7537
cc 6
nc 17
nop 8

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2017-2018
6
 * @package Controller
7
 * @subpackage Frontend
8
 */
9
10
11
namespace Aimeos\Controller\Frontend\Basket\Decorator;
12
13
14
/**
15
 * Selection product handling
16
 *
17
 * @package Controller
18
 * @subpackage Frontend
19
 */
20
class Select
21
	extends \Aimeos\Controller\Frontend\Basket\Decorator\Base
22
	implements \Aimeos\Controller\Frontend\Basket\Iface, \Aimeos\Controller\Frontend\Common\Decorator\Iface
23
{
24
	/**
25
	 * Adds a product to the basket of the customer stored in the session
26
	 *
27
	 * @param \Aimeos\MShop\Product\Item\Iface $product Product to add including texts, media, prices, attributes, etc.
28
	 * @param integer $quantity Amount of products that should by added
29
	 * @param array $variant List of variant-building attribute IDs that identify an article in a selection product
30
	 * @param array $config List of configurable attribute IDs the customer has chosen from
31
	 * @param array $custom Associative list of attribute IDs as keys and arbitrary values that will be added to the ordered product
32
	 * @param string $stocktype Unique code of the stock type to deliver the products from
33
	 * @param string|null $supplier Unique supplier code the product is from
34
	 * @param string|null $siteid Unique site ID the product is from or null for siteid of the product item
35
	 * @return \Aimeos\Controller\Frontend\Basket\Iface Basket frontend object for fluent interface
36
	 * @throws \Aimeos\Controller\Frontend\Basket\Exception If the product isn't available
37
	 */
38
	public function addProduct( \Aimeos\MShop\Product\Item\Iface $product, $quantity = 1,
39
		array $variant = [], array $config = [], array $custom = [], $stocktype = 'default', $supplier = null, $siteid = null )
40
	{
41
		if( $product->getType() !== 'select' )
42
		{
43
			$this->getController()->addProduct( $product, $quantity, $variant, $config, $custom, $stocktype, $supplier, $siteid );
44
			return $this;
45
		}
46
47
		$attr = [];
48
		$prodId = $product->getId();
49
		$prices = $product->getRefItems( 'price', 'default', 'default' );
50
		$hidden = $product->getRefItems( 'attribute', null, 'hidden' );
51
52
		$orderBaseProductItem = \Aimeos\MShop::create( $this->getContext(), 'order/base/product' )->createItem();
53
		$orderBaseProductItem = $orderBaseProductItem->copyFrom( $product );
54
55
		$product = $this->getArticle( $product, $variant );
56
		$orderBaseProductItem->setProductCode( $product->getCode() );
57
58
		$attributeMap = ['custom' => array_keys( $custom ), 'config' => array_keys( $config )];
59
		$this->checkListRef( [$prodId, $product->getId()], 'attribute', $attributeMap );
60
61
		if( ( $subprices = $product->getRefItems( 'price', 'default', 'default' ) ) !== [] ) {
62
			$prices = $subprices;
63
		}
64
65
		if( ( $mediaItems = $product->getRefItems( 'media', 'default', 'default' ) ) !== [] ) {
66
			$orderBaseProductItem->setMediaUrl( current( $mediaItems )->getPreview() );
67
		}
68
69
		$hidden += $product->getRefItems( 'attribute', null, 'hidden' );
70
71
		$orderProductAttrManager = \Aimeos\MShop::create( $this->getContext(), 'order/base/product/attribute' );
72
		$attributes = $product->getRefItems( 'attribute', null, 'variant' );
73
74
		foreach( $this->getAttributes( array_keys( $attributes ), ['text'] ) as $attrItem ) {
75
			$attr[] = $orderProductAttrManager->createItem()->copyFrom( $attrItem )->setType( 'variant' );
76
		}
77
78
		$custAttr = $this->getOrderProductAttributes( 'custom', array_keys( $custom ), $custom );
79
		$confAttr = $this->getOrderProductAttributes( 'config', array_keys( $config ), [], $config );
80
		$hideAttr = $this->getOrderProductAttributes( 'hidden', array_keys( $hidden ) );
81
82
		$orderBaseProductItem = $orderBaseProductItem->setQuantity( $quantity )
83
			->setAttributeItems( array_merge( $attr, $custAttr, $confAttr, $hideAttr ) )
84
			->setPrice( $this->calcPrice( $orderBaseProductItem, $prices, $quantity ) )
85
			->setStockType( $stocktype )->setSupplierCode( $supplier );
86
87
		if( $siteid ) {
88
			$orderBaseProductItem->setSiteId( $siteid );
89
		}
90
91
		$this->getController()->get()->addProduct( $orderBaseProductItem );
92
		$this->getController()->save();
93
94
		return $this;
95
	}
96
97
98
	/**
99
	 * Returns the variant attributes and updates the price list if necessary.
100
	 *
101
	 * @param \Aimeos\MShop\Product\Item\Iface $productItem Product item which is replaced if necessary
102
	 * @param array $variantAttributeIds List of product variant attribute IDs
103
	 * @return \Aimeos\MShop\Product\Item\Iface Product variant article
104
	 * @throws \Aimeos\Controller\Frontend\Basket\Exception If no product variant is found
105
	 */
106
	protected function getArticle( \Aimeos\MShop\Product\Item\Iface $productItem, array $variant )
107
	{
108
		$items = [];
109
		$context = $this->getContext();
110
111
		/** controller/frontend/basket/require-variant
112
		 * A variant of a selection product must be chosen
113
		 *
114
		 * Selection products normally consist of several article variants and
115
		 * by default exactly one article variant of a selection product can be
116
		 * put into the basket.
117
		 *
118
		 * By setting this option to false, the selection product including the
119
		 * chosen attributes (if any attribute values were selected) can be put
120
		 * into the basket as well. This makes it possible to get all articles
121
		 * or a subset of articles (e.g. all of a color) at once.
122
		 *
123
		 * This option replace the "client/html/basket/require-variant" setting.
124
		 *
125
		 * @param boolean True if a variant must be chosen, false if also the selection product with attributes can be added
126
		 * @since 2018.01
127
		 * @category Developer
128
		 * @category User
129
		 */
130
		$requireVariant = $context->getConfig()->get( 'controller/frontend/basket/require-variant', true );
131
132
		foreach( $productItem->getRefItems( 'product', 'default', 'default' ) as $item )
133
		{
134
			foreach( $variant as $id )
135
			{
136
				if( $item->getListItem( 'attribute', 'variant', $id ) === null ) {
137
					continue 2;
138
				}
139
			}
140
141
			$items[] = $item;
142
		}
143
144
		if( count( $items ) > 1 )
145
		{
146
			$msg = $context->getI18n()->dt( 'controller/frontend', 'No unique article found for selected attributes and product ID "%1$s"' );
147
			throw new \Aimeos\Controller\Frontend\Basket\Exception( sprintf( $msg, $productItem->getId() ) );
148
		}
149
150
		if( empty( $items ) && $requireVariant != false ) // count == 0
151
		{
152
			$msg = $context->getI18n()->dt( 'controller/frontend', 'No article found for selected attributes and product ID "%1$s"' );
153
			throw new \Aimeos\Controller\Frontend\Basket\Exception( sprintf( $msg, $productItem->getId() ) );
154
		}
155
156
		return current( $items ) ?: $productItem;
157
	}
158
}
159