Passed
Push — master ( beeae9...b3aaac )
by Aimeos
04:26
created

Base::setAttributeItems()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2022
7
 * @package MShop
8
 * @subpackage Order
9
 */
10
11
12
namespace Aimeos\MShop\Order\Item\Base\Service;
13
14
15
/**
16
 * Abstract class \Aimeos\MShop\Order\Item\Base\Service\Base.
17
 * @package MShop
18
 * @subpackage Order
19
 */
20
abstract class Base extends \Aimeos\MShop\Common\Item\Base implements Iface
21
{
22
	/**
23
	 * Delivery service.
24
	 */
25
	const TYPE_DELIVERY = 'delivery';
26
27
	/**
28
	 * Payment service.
29
	 */
30
	const TYPE_PAYMENT = 'payment';
31
32
33
	private $attributes;
34
	private $attributesMap;
35
	private $price;
36
37
38
	/**
39
	 * Initializes the order base service item
40
	 *
41
	 * @param \Aimeos\MShop\Price\Item\Iface $price
42
	 * @param array $values Values to be set on initialisation
43
	 * @param \Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface[] $attributes List of order service attribute items
44
	 */
45
	public function __construct( \Aimeos\MShop\Price\Item\Iface $price, array $values = [], array $attributes = [] )
46
	{
47
		parent::__construct( 'order.base.service.', $values );
48
49
		map( $attributes )->implements( \Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface::class, true );
50
51
		$this->attributes = $attributes;
52
		$this->price = $price;
53
	}
54
55
56
	/**
57
	 * Clones internal objects of the order base product item.
58
	 */
59
	public function __clone()
60
	{
61
		foreach( $this->attributes as $key => $item ) {
62
			$this->attributes[$key] = clone $item;
63
		}
64
65
		$this->price = clone $this->price;
66
	}
67
68
69
	/**
70
	 * Adds new and replaces existing attribute items for the service.
71
	 *
72
	 * @param \Aimeos\Map|\Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface[] $attributes List of order service attribute items
73
	 * @return \Aimeos\MShop\Order\Item\Base\Service\Iface Order base service item for chaining method calls
74
	 */
75
	public function addAttributeItems( iterable $attributes ) : \Aimeos\MShop\Order\Item\Base\Service\Iface
76
	{
77
		( $attributes = map( $attributes ) )->implements( \Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface::class, true );
78
79
		foreach( $attributes as $attrItem ) {
80
			$this->setAttributeItem( $attrItem );
81
		}
82
83
		return $this;
84
	}
85
86
87
	/**
88
	 * Returns the item type
89
	 *
90
	 * @return string Item type, subtypes are separated by slashes
91
	 */
92
	public function getResourceType() : string
93
	{
94
		return 'order/base/service';
95
	}
96
97
98
	/**
99
	 * Returns the value or list of values of the attribute item for the ordered service with the given code.
100
	 *
101
	 * @param string $code Code of the service attribute item
102
	 * @param array|string $type Type or list of types of the service attribute items
103
	 * @return array|string|null Value or list of values of the attribute item for the ordered service and the given code
104
	 */
105
	public function getAttribute( string $code, $type = '' )
106
	{
107
		$list = [];
108
		$map = $this->getAttributeMap();
109
110
		foreach( (array) $type as $key )
111
		{
112
			if( isset( $map[$key][$code] ) )
113
			{
114
				foreach( $map[$key][$code] as $item ) {
115
					$list[] = $item->getValue();
116
				}
117
			}
118
		}
119
120
		return count( $list ) > 1 ? $list : ( reset( $list ) ?: null );
121
	}
122
123
124
	/**
125
	 * Returns the attribute item or list of attribute items for the ordered service with the given code.
126
	 *
127
	 * @param string $code Code of the service attribute item
128
	 * @param array|string $type Type of the service attribute item
129
	 * @return \Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface|array|null
130
	 * 	Attribute item or list of items for the ordered service and the given code
131
	 */
132
	public function getAttributeItem( string $code, $type = '' )
133
	{
134
		$list = [];
135
		$map = $this->getAttributeMap();
136
137
		foreach( (array) $type as $key )
138
		{
139
			if( isset( $map[$key][$code] ) )
140
			{
141
				foreach( $map[$key][$code] as $item ) {
142
					$list[] = $item;
143
				}
144
			}
145
		}
146
147
		return count( $list ) > 1 ? $list : ( reset( $list ) ?: null );
148
	}
149
150
151
	/**
152
	 * Adds or replaces the attribute item in the list of service attributes.
153
	 *
154
	 * @param \Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface $item Service attribute item
155
	 * @return \Aimeos\MShop\Order\Item\Base\Service\Iface Order base service item for chaining method calls
156
	 */
157
	public function setAttributeItem( \Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface $item ) : \Aimeos\MShop\Order\Item\Base\Service\Iface
158
	{
159
		$this->getAttributeMap();
160
161
		$type = $item->getType();
162
		$code = $item->getCode();
163
		$attrId = $item->getAttributeId();
164
165
		if( !isset( $this->attributesMap[$type][$code][$attrId] ) )
166
		{
167
			$this->attributesMap[$type][$code][$attrId] = $item;
168
			$this->attributes[] = $item;
169
		}
170
171
		$this->attributesMap[$type][$code][$attrId]->setValue( $item->getValue() );
172
		$this->setModified();
173
174
		return $this;
175
	}
176
177
178
	/**
179
	 * Returns the list of attribute items for the service.
180
	 *
181
	 * @param string|null $type Filters returned attributes by the given type or null for no filtering
182
	 * @return \Aimeos\Map List of attribute items implementing \Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface
183
	 */
184
	public function getAttributeItems( string $type = null ) : \Aimeos\Map
185
	{
186
		if( $type === null ) {
187
			return map( $this->attributes );
188
		}
189
190
		$list = [];
191
192
		foreach( $this->attributes as $attrItem )
193
		{
194
			if( $attrItem->getType() === $type ) {
195
				$list[] = $attrItem;
196
			}
197
		}
198
199
		return map( $list );
200
	}
201
202
203
	/**
204
	 * Sets the new list of attribute items for the service.
205
	 *
206
	 * @param \Aimeos\Map|\Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface[] $attributes List of order service attribute items
207
	 * @return \Aimeos\MShop\Order\Item\Base\Service\Iface Order base service item for chaining method calls
208
	 */
209
	public function setAttributeItems( iterable $attributes ) : \Aimeos\MShop\Order\Item\Base\Service\Iface
210
	{
211
		( $attributes = map( $attributes ) )->implements( \Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface::class, true );
212
213
		$this->attributes = $attributes->all();
214
		$this->attributesMap = null;
215
		$this->setModified();
216
217
		return $this;
218
	}
219
220
221
	/**
222
	 * Returns the price item for the product.
223
	 *
224
	 * @return \Aimeos\MShop\Price\Item\Iface Price item with price, costs and rebate
225
	 */
226
	public function getPrice() : \Aimeos\MShop\Price\Item\Iface
227
	{
228
		return $this->price;
229
	}
230
231
232
	/**
233
	 * Sets the price item for the product.
234
	 *
235
	 * @param \Aimeos\MShop\Price\Item\Iface $price Price item containing price and additional costs
236
	 * @return \Aimeos\MShop\Order\Item\Base\Service\Iface Order base product item for chaining method calls
237
	 */
238
	public function setPrice( \Aimeos\MShop\Price\Item\Iface $price ) : \Aimeos\MShop\Order\Item\Base\Service\Iface
239
	{
240
		if( $price !== $this->price )
241
		{
242
			$this->price = $price;
243
			$this->setModified();
244
		}
245
246
		return $this;
247
	}
248
249
250
	/*
251
	 * Sets the item values from the given array and removes that entries from the list
252
	 *
253
	 * @param array &$list Associative list of item keys and their values
254
	 * @param bool True to set private properties too, false for public only
255
	 * @return \Aimeos\MShop\Order\Item\Base\Product\Iface Order service item for chaining method calls
256
	 */
257
	public function fromArray( array &$list, bool $private = false ) : \Aimeos\MShop\Common\Item\Iface
258
	{
259
		$item = parent::fromArray( $list, $private );
260
		$price = $item->getPrice();
261
262
		foreach( $list as $key => $value )
263
		{
264
			switch( $key )
265
			{
266
				case 'order.base.service.price': $price = $price->setValue( $value ); break;
267
				case 'order.base.service.costs': $price = $price->setCosts( $value ); break;
268
				case 'order.base.service.rebate': $price = $price->setRebate( $value ); break;
269
				case 'order.base.service.taxrate': $price = $price->setTaxRate( $value ); break;
270
				case 'order.base.service.taxrates': $price = $price->setTaxRates( (array) $value ); break;
271
				default: continue 2;
272
			}
273
274
			unset( $list[$key] );
275
		}
276
277
		return $item->setPrice( $price );
278
	}
279
280
281
	/**
282
	 * Returns the item values as associative list.
283
	 *
284
	 * @param bool True to return private properties, false for public only
285
	 * @return array Associative list of item properties and their values
286
	 */
287
	public function toArray( bool $private = false ) : array
288
	{
289
		$list = parent::toArray( $private );
290
291
		$list['order.base.service.price'] = $this->price->getValue();
292
		$list['order.base.service.costs'] = $this->price->getCosts();
293
		$list['order.base.service.rebate'] = $this->price->getRebate();
294
		$list['order.base.service.taxrate'] = $this->price->getTaxRate();
295
		$list['order.base.service.taxrates'] = $this->price->getTaxRates();
296
297
		return $list;
298
	}
299
300
301
	/**
302
	 * Checks if the given address type is valid
303
	 *
304
	 * @param string $value Address type defined in \Aimeos\MShop\Order\Item\Base\Address\Base
305
	 * @throws \Aimeos\MShop\Order\Exception If type is invalid
306
	 */
307
	protected function checkType( string $value )
308
	{
309
		switch( $value )
310
		{
311
			case \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_DELIVERY:
312
			case \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT:
313
				return;
314
			default:
315
				throw new \Aimeos\MShop\Order\Exception( sprintf( 'Service of type "%1$s" not available', $value ) );
316
		}
317
	}
318
319
320
	/**
321
	 * Returns the attribute map for the service.
322
	 *
323
	 * @return array Associative list of type and code as key and an \Aimeos\MShop\Order\Item\Base\Service\Attribute\Iface as value
324
	 */
325
	protected function getAttributeMap() : array
326
	{
327
		if( !isset( $this->attributesMap ) )
328
		{
329
			$this->attributesMap = [];
330
331
			foreach( $this->attributes as $item ) {
332
				$this->attributesMap[$item->getType()][$item->getCode()][$item->getAttributeId()] = $item;
333
			}
334
		}
335
336
		return $this->attributesMap;
337
	}
338
}
339