Passed
Push — master ( 2a5595...992182 )
by Aimeos
04:19
created

Standard::setTaxRates()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 2
nop 1
dl 0
loc 15
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2018
7
 * @package MShop
8
 * @subpackage Price
9
 */
10
11
12
namespace Aimeos\MShop\Price\Item;
13
14
15
/**
16
 * Default implementation of a price object.
17
 *
18
 * @package MShop
19
 * @subpackage Price
20
 */
21
class Standard extends Base
22
{
23
	private $values;
24
	private $precision;
25
26
27
	/**
28
	 * Initalizes the object with the given values
29
	 *
30
	 * @param array $values Associative array of key/value pairs for price, costs, rebate and currencyid
31
	 * @param \Aimeos\MShop\Common\Item\Lists\Iface[] $listItems List of list items
32
	 * @param \Aimeos\MShop\Common\Item\Iface[] $refItems List of referenced items
33
	 * @param \Aimeos\MShop\Common\Item\Property\Iface[] $propItems List of property items
34
	 */
35
	public function __construct( array $values = [], array $listItems = [], array $refItems = [], array $propItems = [] )
36
	{
37
		parent::__construct( 'price.', $values, $listItems, $refItems, $propItems );
38
39
		$this->precision = ( isset( $values['precision'] ) ? $values['precision'] : 2 );
40
		$this->values = $values;
41
	}
42
43
44
	/**
45
	 * Returns the type of the price.
46
	 *
47
	 * @return string|null Type of the price
48
	 */
49
	public function getType()
50
	{
51
		if( isset( $this->values['price.type'] ) ) {
52
			return (string) $this->values['price.type'];
53
		}
54
	}
55
56
57
	/**
58
	 * Sets the new type of the price.
59
	 *
60
	 * @param string $type Type of the price
61
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
62
	 */
63
	public function setType( $type )
64
	{
65
		if( (string) $type !== $this->getType() )
66
		{
67
			$this->values['price.type'] = (string) $type;
68
			$this->setModified();
69
		}
70
71
		return $this;
72
	}
73
74
75
	/**
76
	 * Returns the currency ID.
77
	 *
78
	 * @return string|null Three letter ISO currency code (e.g. EUR)
79
	 */
80
	public function getCurrencyId()
81
	{
82
		if( isset( $this->values['price.currencyid'] ) ) {
83
			return (string) $this->values['price.currencyid'];
84
		}
85
	}
86
87
88
	/**
89
	 * Sets the used currency ID.
90
	 *
91
	 * @param string $currencyid Three letter currency code
92
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
93
	 * @throws \Aimeos\MShop\Exception If the language ID is invalid
94
	 */
95
	public function setCurrencyId( $currencyid )
96
	{
97
		if( (string) $currencyid !== $this->getCurrencyId() )
98
		{
99
			$this->values['price.currencyid'] = (string) $this->checkCurrencyId( $currencyid, false );
100
			$this->setModified();
101
		}
102
103
		return $this;
104
	}
105
106
107
	/**
108
	 * Returns the domain the price is valid for.
109
	 *
110
	 * @return string Domain name
111
	 */
112
	public function getDomain()
113
	{
114
		if( isset( $this->values['price.domain'] ) ) {
115
			return (string) $this->values['price.domain'];
116
		}
117
118
		return '';
119
	}
120
121
122
	/**
123
	 * Sets the new domain the price is valid for.
124
	 *
125
	 * @param string $domain Domain name
126
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
127
	 */
128
	public function setDomain( $domain )
129
	{
130
		if( (string) $domain !== $this->getDomain() )
131
		{
132
			$this->values['price.domain'] = (string) $domain;
133
			$this->setModified();
134
		}
135
136
		return $this;
137
	}
138
139
140
	/**
141
	 * Returns the label of the item
142
	 *
143
	 * @return string Label of the item
144
	 */
145
	public function getLabel()
146
	{
147
		if( isset( $this->values['price.label'] ) ) {
148
			return (string) $this->values['price.label'];
149
		}
150
151
		return '';
152
	}
153
154
155
	/**
156
	 * Sets the label of the item
157
	 *
158
	 * @param string $label Label of the item
159
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
160
	 */
161
	public function setLabel( $label )
162
	{
163
		if( (string) $label !== $this->getLabel() )
164
		{
165
			$this->values['price.label'] = (string) $label;
166
			$this->setModified();
167
		}
168
169
		return $this;
170
	}
171
172
173
	/**
174
	 * Returns the quantity the price is valid for.
175
	 *
176
	 * @return integer Quantity
177
	 */
178
	public function getQuantity()
179
	{
180
		if( isset( $this->values['price.quantity'] ) ) {
181
			return (int) $this->values['price.quantity'];
182
		}
183
184
		return 1;
185
	}
186
187
188
	/**
189
	 * Sets the quantity the price is valid for.
190
	 *
191
	 * @param integer $quantity Quantity
192
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
193
	 */
194
	public function setQuantity( $quantity )
195
	{
196
		if( (int) $quantity !== $this->getQuantity() )
197
		{
198
			$this->values['price.quantity'] = (int) $quantity;
199
			$this->setModified();
200
		}
201
202
		return $this;
203
	}
204
205
206
	/**
207
	 * Returns the amount of money.
208
	 *
209
	 * @return string Price value
210
	 */
211
	public function getValue()
212
	{
213
		if( isset( $this->values['price.value'] ) ) {
214
			return (string) $this->values['price.value'];
215
		}
216
217
		return '0.00';
218
	}
219
220
221
	/**
222
	 * Sets the new amount of money.
223
	 *
224
	 * @param string|integer|double $price Amount with two digits precision
225
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
226
	 */
227
	public function setValue( $price )
228
	{
229
		if( (string) $price !== $this->getValue() )
230
		{
231
			$this->values['price.value'] = (string) $this->checkPrice( $price );
232
			$this->setModified();
233
		}
234
235
		return $this;
236
	}
237
238
239
	/**
240
	 * Returns costs.
241
	 *
242
	 * @return string Costs
243
	 */
244
	public function getCosts()
245
	{
246
		if( isset( $this->values['price.costs'] ) ) {
247
			return (string) $this->values['price.costs'];
248
		}
249
250
		return '0.00';
251
	}
252
253
254
	/**
255
	 * Sets the new costs.
256
	 *
257
	 * @param string|integer|double $price Amount with two digits precision
258
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
259
	 */
260
	public function setCosts( $price )
261
	{
262
		if( (string) $price !== $this->getCosts() )
263
		{
264
			$this->values['price.costs'] = (string) $this->checkPrice( $price );
265
			$this->setModified();
266
		}
267
268
		return $this;
269
	}
270
271
272
	/**
273
	 * Returns the rebate amount.
274
	 *
275
	 * @return string Rebate amount
276
	 */
277
	public function getRebate()
278
	{
279
		if( isset( $this->values['price.rebate'] ) ) {
280
			return (string) $this->values['price.rebate'];
281
		}
282
283
		return '0.00';
284
	}
285
286
287
	/**
288
	 * Sets the new rebate amount.
289
	 *
290
	 * @param string|integer|double $price Rebate amount with two digits precision
291
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
292
	 */
293
	public function setRebate( $price )
294
	{
295
		if( (string) $price !== $this->getRebate() )
296
		{
297
			$this->values['price.rebate'] = (string) $this->checkPrice( $price );
298
			$this->setModified();
299
		}
300
301
		return $this;
302
	}
303
304
305
	/**
306
	 * Returns the tax rate
307
	 *
308
	 * @return string Tax rate
309
	 */
310
	public function getTaxRate()
311
	{
312
		if( isset( $this->values['price.taxrates'][''] ) ) {
313
			return (string) $this->values['price.taxrates'][''];
314
		}
315
316
		return '0.00';
317
	}
318
319
320
	/**
321
	 * Returns all tax rates in percent.
322
	 *
323
	 * @return string[] Tax rates for the price
324
	 */
325
	 public function getTaxRates()
326
	 {
327
		if( isset( $this->values['price.taxrates'] ) ) {
328
			return (array) $this->values['price.taxrates'];
329
		}
330
331
		 return [];
332
	 }
333
334
335
	/**
336
	 * Sets the new tax rate.
337
	 *
338
	 * @param string|integer|double $taxrate Tax rate with two digits precision
339
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
340
	 */
341
	public function setTaxRate( $taxrate )
342
	{
343
		if( (string) $taxrate !== $this->getTaxRate() )
344
		{
345
			if( !isset( $this->values['price.taxrates'] ) ) {
346
				$this->values['price.taxrates'] = [];
347
			}
348
349
			if( !is_array( $this->values['price.taxrates'] ) ) {
350
				$this->values['price.taxrates'] = ['' => $this->values['price.taxrates']];
351
			}
352
353
			$this->values['price.taxrates'][''] = (string) $this->checkPrice( $taxrate );
354
			$this->setModified();
355
		}
356
357
		return $this;
358
	}
359
360
361
	/**
362
	 * Sets the new tax rates in percent
363
	 *
364
	 * @param array $taxrates Tax rates with name as key and values with two digits precision
365
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
366
	 */
367
	public function setTaxRates( array $taxrates )
368
	{
369
		if( $taxrates !== $this->getTaxRates() )
370
		{
371
			foreach( $taxrates as $name => $taxrate )
372
			{
373
				unset( $taxrates[$name] ); // change index 0 to ''
374
				$taxrates[$name ?: ''] = (string) $this->checkPrice( $taxrate );
375
			}
376
377
			$this->values['price.taxrates'] = $taxrates;
378
			$this->setModified();
379
		}
380
381
		return $this;
382
	}
383
384
385
	/**
386
	 * Returns the tax rate flag.
387
	 *
388
	 * True if tax is included in the price value, costs and rebate, false if not
389
	 *
390
	 * @return boolean Tax rate flag for the price
391
	 */
392
	public function getTaxFlag()
393
	{
394
		if( isset( $this->values['price.taxflag'] ) ) {
395
			return (bool) $this->values['price.taxflag'];
396
		}
397
398
		return true;
399
	}
400
401
402
	/**
403
	 * Sets the new tax flag.
404
	 *
405
	 * @param boolean $flag True if tax is included in the price value, costs and rebate, false if not
406
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
407
	*/
408
	public function setTaxFlag( $flag )
409
	{
410
		if( (bool) $flag !== $this->getTaxFlag() )
411
		{
412
			$this->values['price.taxflag'] = (bool) $flag;
413
			$this->setModified();
414
		}
415
416
		return $this;
417
	}
418
419
420
	/**
421
	 * Returns the tax for the price item
422
	 *
423
	 * @return string Tax value with four digits precision
424
	 * @see mshop/price/taxflag
425
	 */
426
	public function getTaxValue()
427
	{
428
		if( !isset( $this->values['price.tax'] ) )
429
		{
430
			$taxrate = array_sum( $this->getTaxRates() );
431
432
			if( $this->getTaxFlag() !== false ) {
433
				$tax = ( $this->getValue() + $this->getCosts() ) / ( 100 + $taxrate ) * $taxrate;
434
			} else {
435
				$tax = ( $this->getValue() + $this->getCosts() ) * $taxrate / 100;
436
			}
437
438
			$this->values['price.tax'] = $this->formatNumber( $tax, $this->precision + 2 );
439
		}
440
441
		return (string) $this->values['price.tax'];
442
	}
443
444
445
	/**
446
	 * Sets the tax amount
447
	 *
448
	 * @param string|integer|double $value Tax value with up to four digits precision
449
	 */
450
	public function setTaxValue( $value )
451
	{
452
		if( (string) $value !== $this->getTaxValue() )
453
		{
454
			$this->values['price.tax'] = (string) $this->checkPrice( $value, $this->precision + 2 );
455
			parent::setModified(); // don't unset tax immediately again
456
		}
457
458
		return $this;
459
	}
460
461
462
	/**
463
	 * Returns the status of the item
464
	 *
465
	 * @return integer Status of the item
466
	 */
467
	public function getStatus()
468
	{
469
		if( isset( $this->values['price.status'] ) ) {
470
			return (int) $this->values['price.status'];
471
		}
472
473
		return 1;
474
	}
475
476
477
	/**
478
	 * Sets the status of the item
479
	 *
480
	 * @param integer $status Status of the item
481
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
482
	 */
483
	public function setStatus( $status )
484
	{
485
		if( (int) $status !== $this->getStatus() )
486
		{
487
			$this->values['price.status'] = (int) $status;
488
			$this->setModified();
489
		}
490
491
		return $this;
492
	}
493
494
495
	/**
496
	 * Sets the modified flag of the object.
497
	 */
498
	public function setModified()
499
	{
500
		parent::setModified();
501
		unset( $this->values['price.tax'] );
502
	}
503
504
505
	/**
506
	 * Tests if the item is available based on status, time, language and currency
507
	 *
508
	 * @return boolean True if available, false if not
509
	 */
510
	public function isAvailable()
511
	{
512
		return parent::isAvailable() && $this->getStatus() > 0
513
			&& ( $this->values['currencyid'] === null || $this->getCurrencyId() === $this->values['currencyid'] );
514
	}
515
516
517
	/**
518
	 * Add the given price to the current one.
519
	 *
520
	 * @param \Aimeos\MShop\Price\Item\Iface $item Price item which should be added
521
	 * @param integer $quantity Number of times the Price should be added
522
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
523
	 */
524
	public function addItem( \Aimeos\MShop\Price\Item\Iface $item, $quantity = 1 )
525
	{
526
		if( $item->getCurrencyId() != $this->getCurrencyId() )
527
		{
528
			$msg = 'Price can not be added. Currency ID "%1$s" of price item and currently used currency ID "%2$s" does not match.';
529
			throw new \Aimeos\MShop\Price\Exception( sprintf( $msg, $item->getCurrencyId(), $this->getCurrencyId() ) );
530
		}
531
532
		if( $this === $item ) { $item = clone $item; }
533
		$taxValue = $this->getTaxValue();
534
535
		$this->setQuantity( 1 );
536
		$this->setValue( $this->getValue() + $item->getValue() * $quantity );
537
		$this->setCosts( $this->getCosts() + $item->getCosts() * $quantity );
538
		$this->setRebate( $this->getRebate() + $item->getRebate() * $quantity );
539
		$this->setTaxValue( $taxValue + $item->getTaxValue() * $quantity );
540
541
		return $this;
542
	}
543
544
545
	/**
546
	 * Resets the values of the price item.
547
	 * The currency ID, domain, type and status stays the same.
548
	 *
549
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
550
	 */
551
	public function clear()
552
	{
553
		$this->setQuantity( 1 );
554
		$this->setValue( '0.00' );
555
		$this->setCosts( '0.00' );
556
		$this->setRebate( '0.00' );
557
		$this->setTaxRate( '0.00' );
558
		unset( $this->values['price.tax'] );
559
560
		return $this;
561
	}
562
563
564
	/*
565
	 * Sets the item values from the given array and removes that entries from the list
566
	 *
567
	 * @param array &$list Associative list of item keys and their values
568
	 * @param boolean True to set private properties too, false for public only
569
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
570
	 */
571
	public function fromArray( array &$list, $private = false )
572
	{
573
		$item = parent::fromArray( $list, $private );
574
575
		foreach( $list as $key => $value )
576
		{
577
			switch( $key )
578
			{
579
				case 'price.type': $item = $item->setType( $value ); break;
580
				case 'price.currencyid': $item = $item->setCurrencyId( $value ); break;
581
				case 'price.domain': $item = $item->setDomain( $value ); break;
582
				case 'price.quantity': $item = $item->setQuantity( $value ); break;
583
				case 'price.value': $item = $item->setValue( $value ); break;
584
				case 'price.costs': $item = $item->setCosts( $value ); break;
585
				case 'price.rebate': $item = $item->setRebate( $value ); break;
586
				case 'price.taxvalue': $item = $item->setTaxValue( $value ); break;
587
				case 'price.taxrates': $item = $item->setTaxRates( (array) $value ); break;
588
				case 'price.taxrate': $item = $item->setTaxRate( $value ); break;
589
				case 'price.taxflag': $item = $item->setTaxFlag( $value ); break;
590
				case 'price.status': $item = $item->setStatus( $value ); break;
591
				case 'price.label': $item = $item->setLabel( $value ); break;
592
				default: continue 2;
593
			}
594
595
			unset( $list[$key] );
596
		}
597
598
		return $item;
599
	}
600
601
602
	/**
603
	 * Returns the item values as array.
604
	 *
605
	 * @param boolean True to return private properties, false for public only
606
	 * @return array Associative list of item properties and their values
607
	 */
608
	public function toArray( $private = false )
609
	{
610
		$list = parent::toArray( $private );
611
612
		$list['price.type'] = $this->getType();
613
		$list['price.currencyid'] = $this->getCurrencyId();
614
		$list['price.domain'] = $this->getDomain();
615
		$list['price.quantity'] = $this->getQuantity();
616
		$list['price.value'] = $this->getValue();
617
		$list['price.costs'] = $this->getCosts();
618
		$list['price.rebate'] = $this->getRebate();
619
		$list['price.taxvalue'] = $this->getTaxValue();
620
		$list['price.taxrates'] = $this->getTaxRates();
621
		$list['price.taxrate'] = $this->getTaxRate();
622
		$list['price.taxflag'] = $this->getTaxFlag();
623
		$list['price.status'] = $this->getStatus();
624
		$list['price.label'] = $this->getLabel();
625
626
		return $list;
627
	}
628
}
629