Passed
Push — master ( 5788d1...3b28d2 )
by Aimeos
04:17
created

Standard   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 448
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 43
eloc 107
c 0
b 0
f 0
dl 0
loc 448
rs 8.96

28 Methods

Rating   Name   Duplication   Size   Complexity  
A __clone() 0 6 1
A __construct() 0 9 1
A setComment() 0 3 1
A getComment() 0 3 1
A setCustomerId() 0 10 2
A getSiteId() 0 3 1
A setCustomerReference() 0 3 1
A locale() 0 3 1
A jsonSerialize() 0 7 1
B fromArray() 0 26 7
A getCustomerId() 0 3 1
A getCustomerReference() 0 3 1
A getSiteCode() 0 3 1
A isAvailable() 0 3 1
A getTimeModified() 0 3 1
A editor() 0 3 1
A setAvailable() 0 4 1
A finish() 0 4 1
A checkPrice() 0 4 1
A getId() 0 3 1
A getPrice() 0 22 5
A setModified() 0 4 1
A check() 0 11 3
A setLocale() 0 10 1
A getCustomerItem() 0 3 1
A setId() 0 10 2
A toArray() 0 29 2
A getTimeCreated() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Standard 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.

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 Standard, and based on these observations, apply Extract Interface, too.

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;
13
14
15
/**
16
 * Default implementation of the shopping basket.
17
 *
18
 * @package MShop
19
 * @subpackage Order
20
 */
21
class Standard extends \Aimeos\MShop\Order\Item\Base\Base
22
{
23
	// protected is a workaround for serialize problem
24
	protected $price;
25
	protected $locale;
26
	protected $customer;
27
	protected $recalc = false;
28
	protected $available = true;
29
30
31
	/**
32
	 * Initializes the shopping cart.
33
	 *
34
	 * @param \Aimeos\MShop\Price\Item\Iface $price Default price of the basket (usually 0.00)
35
	 * @param \Aimeos\MShop\Locale\Item\Iface $locale Locale item containing the site, language and currency
36
	 * @param array $values Associative list of key/value pairs containing, e.g. the order or user ID
37
	 * @param \Aimeos\MShop\Order\Item\Base\Product\Iface[] $products List of ordered product items
38
	 * @param \Aimeos\MShop\Order\Item\Base\Address\Iface[] $addresses List of order address items
39
	 * @param \Aimeos\MShop\Order\Item\Base\Service\Iface[] $services List of order service items
40
	 * @param \Aimeos\MShop\Order\Item\Base\Product\Iface[] $coupons Associative list of coupon codes as keys and order product items as values
41
	 * @param \Aimeos\MShop\Customer\Item\Iface|null $custItem Customer item object
42
	 */
43
	public function __construct( \Aimeos\MShop\Price\Item\Iface $price, \Aimeos\MShop\Locale\Item\Iface $locale,
44
		array $values = [], array $products = [], array $addresses = [], array $services = [], array $coupons = [],
45
		?\Aimeos\MShop\Customer\Item\Iface $custItem = null )
46
	{
47
		parent::__construct( $price, $locale, $values, $products, $addresses, $services, $coupons );
48
49
		$this->price = $price;
50
		$this->locale = $locale;
51
		$this->customer = $custItem;
52
	}
53
54
55
	/**
56
	 * Clones internal objects of the order base item.
57
	 */
58
	public function __clone()
59
	{
60
		parent::__clone();
61
62
		$this->price = clone $this->price;
63
		$this->locale = clone $this->locale;
64
	}
65
66
67
	/**
68
	 * Specifies the data which should be serialized to JSON by json_encode().
69
	 *
70
	 * @return array<string,mixed> Data to serialize to JSON
71
	 */
72
	#[\ReturnTypeWillChange]
73
	public function jsonSerialize()
74
	{
75
		return parent::jsonSerialize() + [
76
			'price' => $this->price,
77
			'locale' => $this->locale,
78
			'customer' => $this->customer,
79
		];
80
	}
81
82
83
	/**
84
	 * Tests if all necessary items are available to create the order.
85
	 *
86
	 * @param array $what Type of data
87
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for method chaining
88
	 * @throws \Aimeos\MShop\Order\Exception if there are no products in the basket
89
	 */
90
	public function check( array $what = ['order/base/address', 'order/base/coupon', 'order/base/product', 'order/base/service'] ) : \Aimeos\MShop\Order\Item\Base\Iface
91
	{
92
		$this->notify( 'check.before', $what );
93
94
		if( in_array( 'order/base/product', $what ) && ( count( $this->getProducts() ) < 1 ) ) {
95
			throw new \Aimeos\MShop\Order\Exception( sprintf( 'Basket empty' ) );
96
		}
97
98
		$this->notify( 'check.after', $what );
99
100
		return $this;
101
	}
102
103
104
	/**
105
	 * Returns the associated customer item
106
	 *
107
	 * @return \Aimeos\MShop\Customer\Item\Iface|null Customer item
108
	 */
109
	public function getCustomerItem() : ?\Aimeos\MShop\Customer\Item\Iface
110
	{
111
		return $this->customer;
112
	}
113
114
115
	/**
116
	 * Returns the ID of the order if already available.
117
	 *
118
	 * @return string|null ID of the order item
119
	 */
120
	public function getId() : ?string
121
	{
122
		return $this->get( 'order.base.id' );
123
	}
124
125
126
	/**
127
	 * Sets the id of the order base object.
128
	 *
129
	 * @param string|null $id Unique ID of the order base object
130
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for chaining method calls
131
	 */
132
	public function setId( ?string $id ) : \Aimeos\MShop\Common\Item\Iface
133
	{
134
		$id = \Aimeos\MShop\Common\Item\Base::checkId( $this->getId(), $id );
135
		$this->set( 'order.base.id', $id );
136
137
		if( $id !== null ) {
138
			$this->modified = false;
139
		}
140
141
		return $this;
142
	}
143
144
145
	/**
146
	 * Returns the ID of the site the item is stored.
147
	 *
148
	 * @return string Site ID (or null if not available)
149
	 */
150
	public function getSiteId() : string
151
	{
152
		return $this->get( 'order.base.siteid', '' );
153
	}
154
155
156
	/**
157
	 * Returns the code of the site the item is stored.
158
	 *
159
	 * @return string Site code (or empty string if not available)
160
	 */
161
	public function getSiteCode() : string
162
	{
163
		return $this->get( 'order.base.sitecode', '' );
164
	}
165
166
167
	/**
168
	 * Returns the comment field of the order item.
169
	 *
170
	 * @return string Comment for the order
171
	 */
172
	public function getComment() : string
173
	{
174
		return $this->get( 'order.base.comment', '' );
175
	}
176
177
178
	/**
179
	 * Sets the comment field of the order item
180
	 *
181
	 * @param string $comment Comment for the order
182
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for chaining method calls
183
	 */
184
	public function setComment( ?string $comment ) : \Aimeos\MShop\Order\Item\Base\Iface
185
	{
186
		return $this->set( 'order.base.comment', (string) $comment );
187
	}
188
189
190
	/**
191
	 * Returns modify date/time of the order item base product.
192
	 *
193
	 * @return string|null Returns modify date/time of the order base item
194
	 */
195
	public function getTimeModified() : ?string
196
	{
197
		return $this->get( 'order.base.mtime' );
198
	}
199
200
201
	/**
202
	 * Returns the create date of the item.
203
	 *
204
	 * @return string|null ISO date in YYYY-MM-DD hh:mm:ss format
205
	 */
206
	public function getTimeCreated() : ?string
207
	{
208
		return $this->get( 'order.base.ctime' );
209
	}
210
211
212
	/**
213
	 * Returns the editor code of editor who created/modified the item at last.
214
	 *
215
	 * @return string Editorcode of editor who created/modified the item at last
216
	 */
217
	public function editor() : string
218
	{
219
		return $this->get( 'order.base.editor', '' );
220
	}
221
222
223
	/**
224
	 * Returns the customer ID of the customer who has ordered.
225
	 *
226
	 * @return string Unique ID of the customer
227
	 */
228
	public function getCustomerId() : string
229
	{
230
		return $this->get( 'order.base.customerid', '' );
231
	}
232
233
234
	/**
235
	 * Sets the customer ID of the customer who has ordered.
236
	 *
237
	 * @param string $customerid Unique ID of the customer
238
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for chaining method calls
239
	 */
240
	public function setCustomerId( ?string $customerid ) : \Aimeos\MShop\Order\Item\Base\Iface
241
	{
242
		if( (string) $customerid !== $this->getCustomerId() )
243
		{
244
			$this->notify( 'setCustomerId.before', (string) $customerid );
245
			$this->set( 'order.base.customerid', (string) $customerid );
246
			$this->notify( 'setCustomerId.after', (string) $customerid );
247
		}
248
249
		return $this;
250
	}
251
252
253
	/**
254
	 * Returns the customer reference field of the order item
255
	 *
256
	 * @return string Customer reference for the order
257
	 */
258
	public function getCustomerReference() : string
259
	{
260
		return $this->get( 'order.base.customerref', '' );
261
	}
262
263
264
	/**
265
	 * Sets the customer reference field of the order item
266
	 *
267
	 * @param string $value Customer reference for the order
268
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for chaining method calls
269
	 */
270
	public function setCustomerReference( ?string $value ) : \Aimeos\MShop\Order\Item\Base\Iface
271
	{
272
		return $this->set( 'order.base.customerref', (string) $value );
273
	}
274
275
276
	/**
277
	 * Returns the locales for the basic order item.
278
	 *
279
	 * @return \Aimeos\MShop\Locale\Item\Iface Object containing information
280
	 *  about site, language, country and currency
281
	 */
282
	public function locale() : \Aimeos\MShop\Locale\Item\Iface
283
	{
284
		return $this->locale;
285
	}
286
287
288
	/**
289
	 * Sets the locales for the basic order item.
290
	 *
291
	 * @param \Aimeos\MShop\Locale\Item\Iface $locale Object containing information
292
	 *  about site, language, country and currency
293
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for chaining method calls
294
	 */
295
	public function setLocale( \Aimeos\MShop\Locale\Item\Iface $locale ) : \Aimeos\MShop\Order\Item\Base\Iface
296
	{
297
		$this->notify( 'setLocale.before', $locale );
298
299
		$this->locale = clone $locale;
300
		$this->modified = true;
301
302
		$this->notify( 'setLocale.after', $locale );
303
304
		return $this;
305
	}
306
307
308
	/**
309
	 * Returns a price item with amounts calculated for the products, costs, etc.
310
	 *
311
	 * @return \Aimeos\MShop\Price\Item\Iface Price item with price, costs and rebate the customer has to pay
312
	 */
313
	public function getPrice() : \Aimeos\MShop\Price\Item\Iface
314
	{
315
		if( $this->recalc )
316
		{
317
			$price = $this->price->clear();
318
319
			foreach( $this->getServices() as $list )
320
			{
321
				foreach( $list as $service ) {
322
					$price = $price->addItem( $service->getPrice() );
323
				}
324
			}
325
326
			foreach( $this->getProducts() as $product ) {
327
				$price = $price->addItem( $product->getPrice(), $product->getQuantity() );
328
			}
329
330
			$this->price = $price;
331
			$this->recalc = false;
332
		}
333
334
		return $this->price;
335
	}
336
337
338
	/**
339
	 * Tests if the item is available based on status, time, language and currency
340
	 *
341
	 * @return bool True if available, false if not
342
	 */
343
	public function isAvailable() : bool
344
	{
345
		return $this->available;
346
	}
347
348
349
	/**
350
	 * Sets the general availability of the item
351
	 *
352
	 * @param bool $value True if available, false if not
353
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for method chaining
354
	 */
355
	public function setAvailable( bool $value ) : \Aimeos\MShop\Common\Item\Iface
356
	{
357
		$this->available = $value;
358
		return $this;
359
	}
360
361
362
	/**
363
	 * Sets the modified flag of the object.
364
	 *
365
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for method chaining
366
	 */
367
	public function setModified() : \Aimeos\MShop\Order\Item\Base\Iface
368
	{
369
		$this->recalc = true;
370
		return parent::setModified();
371
	}
372
373
374
	/*
375
	 * Sets the item values from the given array and removes that entries from the list
376
	 *
377
	 * @param array &$list Associative list of item keys and their values
378
	 * @param bool True to set private properties too, false for public only
379
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for chaining method calls
380
	 */
381
	public function fromArray( array &$list, bool $private = false ) : \Aimeos\MShop\Common\Item\Iface
382
	{
383
		$item = $this;
384
		$locale = $item->locale();
385
386
		unset( $list['order.base.siteid'] );
387
		unset( $list['order.base.ctime'] );
388
		unset( $list['order.base.mtime'] );
389
		unset( $list['order.base.editor'] );
390
391
		foreach( $list as $key => $value )
392
		{
393
			switch( $key )
394
			{
395
				case 'order.base.id': $item = $item->setId( $value ); break;
396
				case 'order.base.customerid': $item = $item->setCustomerId( $value ); break;
397
				case 'order.base.languageid': $locale = $locale->setLanguageId( $value ); break;
398
				case 'order.base.customerref': $item = $item->setCustomerReference( $value ); break;
399
				case 'order.base.comment': $item = $item->setComment( $value ); break;
400
				default: continue 2;
401
			}
402
403
			unset( $list[$key] );
404
		}
405
406
		return $item->setLocale( $locale );
407
	}
408
409
410
	/**
411
	 * Returns the item values as array.
412
	 *
413
	 * @param bool True to return private properties, false for public only
414
	 * @return array Associative list of item properties and their values
415
	 */
416
	public function toArray( bool $private = false ) : array
417
	{
418
		$price = $this->getPrice();
419
		$locale = $this->locale();
420
421
		$list = array(
422
			'order.base.id' => $this->getId(),
423
			'order.base.sitecode' => $this->getSiteCode(),
424
			'order.base.customerid' => $this->getCustomerId(),
425
			'order.base.languageid' => $locale->getLanguageId(),
426
			'order.base.currencyid' => $price->getCurrencyId(),
427
			'order.base.price' => $price->getValue(),
428
			'order.base.costs' => $price->getCosts(),
429
			'order.base.rebate' => $price->getRebate(),
430
			'order.base.taxvalue' => $price->getTaxValue(),
431
			'order.base.taxflag' => $price->getTaxFlag(),
432
			'order.base.customerref' => $this->getCustomerReference(),
433
			'order.base.comment' => $this->getComment(),
434
		);
435
436
		if( $private === true )
437
		{
438
			$list['order.base.siteid'] = $this->getSiteId();
439
			$list['order.base.mtime'] = $this->getTimeModified();
440
			$list['order.base.ctime'] = $this->getTimeCreated();
441
			$list['order.base.editor'] = $this->editor();
442
		}
443
444
		return $list;
445
	}
446
447
448
	/**
449
	 * Notifies listeners before the basket becomes an order.
450
	 *
451
	 * @return \Aimeos\MShop\Order\Item\Base\Iface Order base item for chaining method calls
452
	 */
453
	public function finish() : \Aimeos\MShop\Order\Item\Base\Iface
454
	{
455
		$this->notify( 'setOrder.before' );
456
		return $this;
457
	}
458
459
460
	/**
461
	 * Checks if the price uses the same currency as the price in the basket.
462
	 *
463
	 * @param \Aimeos\MShop\Price\Item\Iface $item Price item
464
	 */
465
	protected function checkPrice( \Aimeos\MShop\Price\Item\Iface $item )
466
	{
467
		$price = clone $this->price;
468
		$price->addItem( $item );
469
	}
470
}
471