Completed
Push — master ( b46c0d...fe698d )
by Aimeos
06:27
created

Select::addProduct()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 40
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 40
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 26
nc 2
nop 8

How to fix   Many Parameters   

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
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
2 ignored issues
show
Coding Style introduced by
The extends keyword must be on the same line as the class name
Loading history...
Coding Style introduced by
Expected 0 spaces between "Base" and comma; 1 found
Loading history...
22
	implements \Aimeos\Controller\Frontend\Basket\Iface, \Aimeos\Controller\Frontend\Common\Decorator\Iface
1 ignored issue
show
Coding Style introduced by
The implements keyword must be on the same line as the class name
Loading history...
23
{
24
	/**
25
	 * Adds a selection product to the basket of the user stored in the session.
26
	 *
27
	 * @param string $prodid ID of the base product to add
28
	 * @param integer $quantity Amount of products that should by added
29
	 * @param array $options Possible options are: 'stock'=>true|false and 'variant'=>true|false
30
	 * 	The 'stock'=>false option allows adding products without being in stock.
31
	 * 	The 'variant'=>false option allows adding the selection product to the basket
32
	 * 	instead of the specific sub-product if the variant-building attribute IDs
33
	 * 	doesn't match a specific sub-product or if the attribute IDs are missing.
34
	 * @param array $variantAttributeIds List of variant-building attribute IDs that identify a specific product
35
	 * 	in a selection products
36
	 * @param array $configAttributeIds  List of attribute IDs that doesn't identify a specific product in a
37
	 * 	selection of products but are stored together with the product (e.g. for configurable products)
38
	 * @param array $hiddenAttributeIds List of attribute IDs that should be stored along with the product in the order
39
	 * @param array $customAttributeValues Associative list of attribute IDs and arbitrary values that should be stored
40
	 * 	along with the product in the order
41
	 * @param string $stocktype Unique code of the stock type to deliver the products from
42
	 * @throws \Aimeos\Controller\Frontend\Basket\Exception If the product isn't available
43
	 */
44
	public function addProduct( $prodid, $quantity = 1, array $options = array(), array $variantAttributeIds = array(),
45
		array $configAttributeIds = array(), array $hiddenAttributeIds = array(), array $customAttributeValues = array(),
46
		$stocktype = 'default' )
47
	{
48
		$context = $this->getContext();
49
		$productManager = \Aimeos\MShop\Factory::createManager( $context, 'product' );
50
		$productItem = $productManager->getItem( $prodid, array( 'media', 'supplier', 'price', 'product', 'text' ) );
51
52
		if( $productItem->getType() !== 'select' )
53
		{
54
			return $this->getController()->addProduct(
55
				$prodid, $quantity, $options, $variantAttributeIds, $configAttributeIds,
56
				$hiddenAttributeIds, $customAttributeValues, $stocktype
57
			);
58
		}
59
60
		$orderBaseProductItem = \Aimeos\MShop\Factory::createManager( $context, 'order/base/product' )->createItem();
61
		$orderBaseProductItem->copyFrom( $productItem );
62
		$orderBaseProductItem->setQuantity( $quantity );
63
		$orderBaseProductItem->setStockType( $stocktype );
64
65
		$prices = $productItem->getRefItems( 'price', 'default', 'default' );
66
		$attr = $this->getVariantDetails( $orderBaseProductItem, $productItem, $prices, $variantAttributeIds, $options );
67
68
		$priceManager = \Aimeos\MShop\Factory::createManager( $context, 'price' );
69
		$price = $priceManager->getLowestPrice( $prices, $quantity );
70
71
		$attr = array_merge( $attr, $this->createOrderProductAttributes( $price, $prodid, $quantity, $configAttributeIds, 'config' ) );
72
		$attr = array_merge( $attr, $this->createOrderProductAttributes( $price, $prodid, $quantity, $hiddenAttributeIds, 'hidden' ) );
73
		$attr = array_merge( $attr, $this->createOrderProductAttributes( $price, $prodid, $quantity, array_keys( $customAttributeValues ), 'custom', $customAttributeValues ) );
74
75
		// remove product rebate of original price in favor to rebates granted for the order
76
		$price->setRebate( '0.00' );
77
78
		$orderBaseProductItem->setPrice( $price );
79
		$orderBaseProductItem->setAttributes( $attr );
80
81
		$this->getController()->get()->addProduct( $orderBaseProductItem );
82
		$this->getController()->save();
83
	}
84
85
86
	/**
87
	 * Returns the variant attributes and updates the price list if necessary.
88
	 *
89
	 * @param \Aimeos\MShop\Order\Item\Base\Product\Iface $orderBaseProductItem Order product item
90
	 * @param \Aimeos\MShop\Product\Item\Iface &$productItem Product item which is replaced if necessary
91
	 * @param array &$prices List of product prices that will be updated if necessary
92
	 * @param array $variantAttributeIds List of product variant attribute IDs
93
	 * @param array $options Associative list of options
94
	 * @return \Aimeos\MShop\Order\Item\Base\Product\Attribute\Iface[] List of order product attributes
95
	 * @throws \Aimeos\Controller\Frontend\Basket\Exception If no product variant is found
96
	 */
97
	protected function getVariantDetails( \Aimeos\MShop\Order\Item\Base\Product\Iface $orderBaseProductItem,
98
		\Aimeos\MShop\Product\Item\Iface &$productItem, array &$prices, array $variantAttributeIds, array $options )
99
	{
100
		$attr = array();
101
		$productItems = $this->getProductVariants( $productItem, $variantAttributeIds );
102
103
		if( count( $productItems ) > 1 )
104
		{
105
			$msg = sprintf( 'No unique article found for selected attributes and product ID "%1$s"', $productItem->getId() );
106
			throw new \Aimeos\Controller\Frontend\Basket\Exception( $msg );
107
		}
108
		else if( ( $result = reset( $productItems ) ) !== false ) // count == 1
109
		{
110
			$productItem = $result;
111
			$orderBaseProductItem->setProductCode( $productItem->getCode() );
112
113
			$subprices = $productItem->getRefItems( 'price', 'default', 'default' );
114
115
			if( !empty( $subprices ) ) {
116
				$prices = $subprices;
117
			}
118
119
			$submedia = $productItem->getRefItems( 'media', 'default', 'default' );
120
121
			if( ( $mediaItem = reset( $submedia ) ) !== false ) {
122
				$orderBaseProductItem->setMediaUrl( $mediaItem->getPreview() );
123
			}
124
125
			$orderProductAttrManager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'order/base/product/attribute' );
126
			$variantAttributes = $productItem->getRefItems( 'attribute', null, 'variant' );
127
128
			foreach( $this->getAttributes( array_keys( $variantAttributes ), array( 'text' ) ) as $attrItem )
129
			{
130
				$orderAttributeItem = $orderProductAttrManager->createItem();
131
				$orderAttributeItem->copyFrom( $attrItem );
132
				$orderAttributeItem->setType( 'variant' );
133
134
				$attr[] = $orderAttributeItem;
135
			}
136
		}
137
		else if( !isset( $options['variant'] ) || $options['variant'] != false ) // count == 0
138
		{
139
			$msg = sprintf( 'No article found for selected attributes and product ID "%1$s"', $productItem->getId() );
140
			throw new \Aimeos\Controller\Frontend\Basket\Exception( $msg );
141
		}
142
143
		return $attr;
144
	}
145
}
146