Passed
Push — master ( 8659e3...021966 )
by Aimeos
14:38
created

Standard::setTaxFlag()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2024
6
 * @package MShop
7
 * @subpackage Price
8
 */
9
10
11
namespace Aimeos\MShop\Price\Item;
12
13
use \Aimeos\MShop\Common\Item\ListsRef;
0 ignored issues
show
Bug introduced by
The type \Aimeos\MShop\Common\Item\ListsRef was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use \Aimeos\MShop\Common\Item\PropertyRef;
0 ignored issues
show
Bug introduced by
The type \Aimeos\MShop\Common\Item\PropertyRef was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use \Aimeos\MShop\Common\Item\TypeRef;
0 ignored issues
show
Bug introduced by
The type \Aimeos\MShop\Common\Item\TypeRef was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
17
18
/**
19
 * Default implementation of a price object.
20
 *
21
 * @package MShop
22
 * @subpackage Price
23
 */
24
class Standard extends Base
25
{
26
	use ListsRef\Traits, PropertyRef\Traits, TypeRef\Traits {
0 ignored issues
show
Bug introduced by
The type \Aimeos\MShop\Common\Item\ListsRef\Traits was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type \Aimeos\MShop\Common\Item\PropertyRef\Traits was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type \Aimeos\MShop\Common\Item\TypeRef\Traits was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
		ListsRef\Traits::__clone insteadof PropertyRef\Traits;
28
		ListsRef\Traits::__clone as __cloneList;
29
		PropertyRef\Traits::__clone as __cloneProperty;
30
	}
31
32
33
	private int $precision;
34
	private ?string $tax;
35
36
37
	/**
38
	 * Initalizes the object with the given values
39
	 *
40
	 * @param string $prefix Prefix for the keys returned by toArray()
41
	 * @param array $values Associative array of key/value pairs for price, costs, rebate and currencyid
42
	 */
43
	public function __construct( string $prefix, array $values = [] )
44
	{
45
		parent::__construct( 'price.', $values );
46
47
		$this->tax = $values['price.taxvalue'] ?? null;
48
		$this->precision = (int) ( $values['.precision'] ?? 2 );
49
50
		$this->initPropertyItems( $values['.propitems'] ?? [] );
51
		$this->initListItems( $values['.listitems'] ?? [] );
52
	}
53
54
55
	/**
56
	 * Creates a deep clone of all objects
57
	 */
58
	public function __clone()
59
	{
60
		parent::__clone();
61
		$this->__cloneList();
62
		$this->__cloneProperty();
63
	}
64
65
66
	/**
67
	 * Returns costs per item.
68
	 *
69
	 * @return string Costs per item
70
	 */
71
	public function getCosts() : string
72
	{
73
		return $this->formatNumber( (float) $this->get( 'price.costs', '0.00' ) );
74
	}
75
76
77
	/**
78
	 * Sets the new costsper item.
79
	 *
80
	 * @param string|integer|double $price Amount with two digits precision
81
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
82
	 */
83
	public function setCosts( $price ) : \Aimeos\MShop\Price\Item\Iface
84
	{
85
		return $this->set( 'price.costs', $this->checkPrice( (string) $price ) );
86
	}
87
88
89
	/**
90
	 * Returns the currency ID.
91
	 *
92
	 * @return string|null Three letter ISO currency code (e.g. EUR)
93
	 */
94
	public function getCurrencyId() : ?string
95
	{
96
		return $this->get( 'price.currencyid' );
97
	}
98
99
100
	/**
101
	 * Sets the used currency ID.
102
	 *
103
	 * @param string $currencyid Three letter currency code
104
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
105
	 * @throws \Aimeos\MShop\Exception If the language ID is invalid
106
	 */
107
	public function setCurrencyId( string $currencyid ) : \Aimeos\MShop\Price\Item\Iface
108
	{
109
		return $this->set( 'price.currencyid', $this->checkCurrencyId( $currencyid, false ) );
110
	}
111
112
113
	/**
114
	 * Returns the domain the price is valid for.
115
	 *
116
	 * @return string Domain name
117
	 */
118
	public function getDomain() : string
119
	{
120
		return $this->get( 'price.domain', '' );
121
	}
122
123
124
	/**
125
	 * Sets the new domain the price is valid for.
126
	 *
127
	 * @param string $domain Domain name
128
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
129
	 */
130
	public function setDomain( string $domain ) : \Aimeos\MShop\Common\Item\Iface
131
	{
132
		return $this->set( 'price.domain', $domain );
133
	}
134
135
136
	/**
137
	 * Returns the label of the item
138
	 *
139
	 * @return string Label of the item
140
	 */
141
	public function getLabel() : string
142
	{
143
		return $this->get( 'price.label', '' );
144
	}
145
146
147
	/**
148
	 * Sets the label of the item
149
	 *
150
	 * @param string $label Label of the item
151
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
152
	 */
153
	public function setLabel( ?string $label ) : \Aimeos\MShop\Price\Item\Iface
154
	{
155
		return $this->set( 'price.label', (string) $label );
156
	}
157
158
159
	/**
160
	 * Returns the decimal precision of the price
161
	 *
162
	 * @return int Number of decimal digits
163
	 */
164
	public function getPrecision() : int
165
	{
166
		return $this->precision;
167
	}
168
169
170
	/**
171
	 * Returns the quantity the price is valid for.
172
	 *
173
	 * @return float Quantity
174
	 */
175
	public function getQuantity() : float
176
	{
177
		return (float) $this->get( 'price.quantity', 1 );
178
	}
179
180
181
	/**
182
	 * Sets the quantity the price is valid for.
183
	 *
184
	 * @param float $quantity Quantity
185
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
186
	 */
187
	public function setQuantity( float $quantity ) : \Aimeos\MShop\Price\Item\Iface
188
	{
189
		return $this->set( 'price.quantity', $quantity );
190
	}
191
192
193
	/**
194
	 * Returns the rebate amount.
195
	 *
196
	 * @return string Rebate amount
197
	 */
198
	public function getRebate() : string
199
	{
200
		return $this->formatNumber( (float) $this->get( 'price.rebate', '0.00' ) );
201
	}
202
203
204
	/**
205
	 * Sets the new rebate amount.
206
	 *
207
	 * @param string|integer|double $price Rebate amount with two digits precision
208
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
209
	 */
210
	public function setRebate( $price ) : \Aimeos\MShop\Price\Item\Iface
211
	{
212
		return $this->set( 'price.rebate', $this->checkPrice( (string) $price ) );
213
	}
214
215
216
	/**
217
	 * Returns the status of the item
218
	 *
219
	 * @return int Status of the item
220
	 */
221
	public function getStatus() : int
222
	{
223
		return $this->get( 'price.status', 1 );
224
	}
225
226
227
	/**
228
	 * Sets the status of the item
229
	 *
230
	 * @param int $status Status of the item
231
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
232
	 */
233
	public function setStatus( int $status ) : \Aimeos\MShop\Common\Item\Iface
234
	{
235
		return $this->set( 'price.status', $status );
236
	}
237
238
239
	/**
240
	 * Returns the tax rate
241
	 *
242
	 * @return string Tax rate
243
	 */
244
	public function getTaxRate() : string
245
	{
246
		$list = (array) $this->get( 'price.taxrates', [] );
247
		return $this->formatNumber( $list['tax'] ?? '0.00' );
248
	}
249
250
251
	/**
252
	 * Returns all tax rates in percent.
253
	 *
254
	 * @return string[] Tax rates for the price
255
	 */
256
	 public function getTaxRates() : array
257
	 {
258
		return $this->get( 'price.taxrates', [] );
259
	 }
260
261
262
	/**
263
	 * Sets the new tax rate.
264
	 *
265
	 * @param string|integer|double $taxrate Tax rate with two digits precision
266
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
267
	 */
268
	public function setTaxRate( $taxrate ) : \Aimeos\MShop\Price\Item\Iface
269
	{
270
		return $this->setTaxRates( ['tax' => $taxrate] );
271
	}
272
273
274
	/**
275
	 * Sets the new tax rates in percent
276
	 *
277
	 * @param array $taxrates Tax rates with name as key and values with two digits precision
278
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
279
	 */
280
	public function setTaxRates( array $taxrates ) : \Aimeos\MShop\Price\Item\Iface
281
	{
282
		foreach( $taxrates as $name => $taxrate )
283
		{
284
			unset( $taxrates[$name] ); // change index 0 to ''
285
			$taxrates[$name ?: 'tax'] = $this->checkPrice( $taxrate );
286
		}
287
288
		return $this->set( 'price.taxrates', $taxrates );
289
	}
290
291
292
	/**
293
	 * Returns the tax rate flag.
294
	 *
295
	 * True if tax is included in the price value, costs and rebate, false if not
296
	 *
297
	 * @return bool Tax rate flag for the price
298
	 */
299
	public function getTaxFlag() : bool
300
	{
301
		return $this->get( 'price.taxflag', true );
302
	}
303
304
305
	/**
306
	 * Sets the new tax flag.
307
	 *
308
	 * @param bool $flag True if tax is included in the price value, costs and rebate, false if not
309
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
310
	 */
311
	public function setTaxFlag( bool $flag ) : \Aimeos\MShop\Price\Item\Iface
312
	{
313
		return $this->set( 'price.taxflag', $flag );
314
	}
315
316
317
	/**
318
	 * Returns the tax for the price item
319
	 *
320
	 * @return string Tax value with four digits precision
321
	 * @see mshop/price/taxflag
322
	 */
323
	public function getTaxValue() : string
324
	{
325
		if( $this->tax === null )
326
		{
327
			$taxrate = array_sum( $this->getTaxRates() );
328
329
			if( $this->getTaxFlag() !== false ) {
330
				$this->tax = ( $this->getValue() + $this->getCosts() ) / ( 100 + $taxrate ) * $taxrate;
331
			} else {
332
				$this->tax = ( $this->getValue() + $this->getCosts() ) * $taxrate / 100;
333
			}
334
335
			parent::setModified();
336
		}
337
338
		return $this->formatNumber( (float) $this->tax, $this->getPrecision() + 2 );
339
	}
340
341
342
	/**
343
	 * Sets the tax amount
344
	 *
345
	 * @param string|integer|double $value Tax value with up to four digits precision
346
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
347
	 */
348
	public function setTaxValue( $value ) : \Aimeos\MShop\Price\Item\Iface
349
	{
350
		$this->tax = $this->checkPrice( (string) $value, $this->getPrecision() + 2 );
351
		parent::setModified();
352
		return $this;
353
	}
354
355
356
	/**
357
	 * Returns the type of the price item.
358
	 * Overwritten for different default value.
359
	 *
360
	 * @return string Type of the price item
361
	 */
362
	public function getType() : string
363
	{
364
		return $this->get( 'price.type', 'default' );
365
	}
366
367
368
	/**
369
	 * Returns the amount of money.
370
	 *
371
	 * @return string|null Price value or NULL for on request
372
	 */
373
	public function getValue() : ?string
374
	{
375
		return $this->formatNumber( $this->get( 'price.value' ) );
376
	}
377
378
379
	/**
380
	 * Sets the new amount of money.
381
	 *
382
	 * @param string|integer|double|null $price Amount with configured precision or NULL for on request
383
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
384
	 */
385
	public function setValue( $price ) : \Aimeos\MShop\Price\Item\Iface
386
	{
387
		return $this->set( 'price.value', $this->checkPrice( $price ) );
388
	}
389
390
391
	/**
392
	 * Sets the modified flag of the object.
393
	 *
394
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
395
	 */
396
	public function setModified() : \Aimeos\MShop\Common\Item\Iface
397
	{
398
		$this->tax = null;
399
		return parent::setModified();
400
	}
401
402
403
	/**
404
	 * Tests if the item is available based on status, time, language and currency
405
	 *
406
	 * @return bool True if available, false if not
407
	 */
408
	public function isAvailable() : bool
409
	{
410
		$cid = $this->get( '.currencyid' );
411
		return parent::isAvailable() && $this->getStatus() > 0 && ( $cid === null || $this->getCurrencyId() === $cid );
412
	}
413
414
415
	/**
416
	 * Add the given price to the current one.
417
	 *
418
	 * @param \Aimeos\MShop\Price\Item\Iface $item Price item which should be added
419
	 * @param float $quantity Number of times the Price should be added
420
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
421
	 */
422
	public function addItem( \Aimeos\MShop\Price\Item\Iface $item, float $quantity = 1 ) : \Aimeos\MShop\Price\Item\Iface
423
	{
424
		if( $item->getCurrencyId() != $this->getCurrencyId() )
425
		{
426
			$msg = 'Price can not be added. Currency ID "%1$s" of price item and currently used currency ID "%2$s" does not match.';
427
			throw new \Aimeos\MShop\Price\Exception( sprintf( $msg, $item->getCurrencyId(), $this->getCurrencyId() ) );
428
		}
429
430
		if( $this === $item ) { $item = clone $item; }
431
		$taxValue = $this->getTaxValue(); // use initial value before it gets reset
432
433
		$this->setQuantity( 1 );
434
		$this->setValue( $this->getValue() + $item->getValue() * $quantity );
435
		$this->setCosts( $this->getCosts() + $item->getCosts() * $quantity );
436
		$this->setRebate( $this->getRebate() + $item->getRebate() * $quantity );
437
		$this->setTaxValue( $taxValue + $item->getTaxValue() * $quantity );
438
439
		return $this;
440
	}
441
442
443
	/**
444
	 * Resets the values of the price item.
445
	 * The currency ID, domain, type and status stays the same.
446
	 *
447
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
448
	 */
449
	public function clear()
450
	{
451
		$this->setQuantity( 1 );
452
		$this->setValue( '0.00' );
453
		$this->setCosts( '0.00' );
454
		$this->setRebate( '0.00' );
455
		$this->setTaxRate( '0.00' );
456
		$this->tax = null;
457
458
		return $this;
459
	}
460
461
462
	/*
463
	 * Sets the item values from the given array and removes that entries from the list
464
	 *
465
	 * @param array &$list Associative list of item keys and their values
466
	 * @param bool True to set private properties too, false for public only
467
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
468
	 */
469
	public function fromArray( array &$list, bool $private = false ) : \Aimeos\MShop\Common\Item\Iface
470
	{
471
		$item = parent::fromArray( $list, $private );
472
473
		foreach( $list as $key => $value )
474
		{
475
			switch( $key )
476
			{
477
				case 'price.type': $item->setType( $value ); break;
478
				case 'price.currencyid': $item->setCurrencyId( $value ); break;
479
				case 'price.quantity': $item->setQuantity( (float) $value ); break;
480
				case 'price.domain': $item->setDomain( $value ); break;
481
				case 'price.value': $item->setValue( $value ); break;
482
				case 'price.costs': $item->setCosts( $value ); break;
483
				case 'price.rebate': $item->setRebate( $value ); break;
484
				case 'price.taxvalue': $item->setTaxValue( $value ); break;
485
				case 'price.taxrate': $item->setTaxRate( $value ); break;
486
				case 'price.taxrates': $item->setTaxRates( (array) $value ); break;
487
				case 'price.taxflag': $item->setTaxFlag( (bool) $value ); break;
488
				case 'price.status': $item->setStatus( (int) $value ); break;
489
				case 'price.label': $item->setLabel( $value ); break;
490
				default: continue 2;
491
			}
492
493
			unset( $list[$key] );
494
		}
495
496
		return $item;
497
	}
498
499
500
	/**
501
	 * Returns the item values as array.
502
	 *
503
	 * @param bool True to return private properties, false for public only
504
	 * @return array Associative list of item properties and their values
505
	 */
506
	public function toArray( bool $private = false ) : array
507
	{
508
		$list = parent::toArray( $private );
509
510
		$list['price.type'] = $this->getType();
511
		$list['price.currencyid'] = $this->getCurrencyId();
512
		$list['price.domain'] = $this->getDomain();
513
		$list['price.quantity'] = $this->getQuantity();
514
		$list['price.value'] = $this->getValue();
515
		$list['price.costs'] = $this->getCosts();
516
		$list['price.rebate'] = $this->getRebate();
517
		$list['price.taxvalue'] = $this->getTaxValue();
518
		$list['price.taxrates'] = $this->getTaxRates();
519
		$list['price.taxrate'] = $this->getTaxRate();
520
		$list['price.taxflag'] = $this->getTaxFlag();
521
		$list['price.status'] = $this->getStatus();
522
		$list['price.label'] = $this->getLabel();
523
524
		return $list;
525
	}
526
}
527