Passed
Push — master ( 59a418...224b02 )
by Aimeos
04:23
created

Standard::getTaxRates()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 0
dl 0
loc 12
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.taxrate'] ) ) {
313
			return (string) $this->values['price.taxrate'];
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
		 $list = ['taxrate' => $this->getTaxRate()];
328
329
		 foreach( $this->getPropertyItems() as $propItem )
330
		 {
331
			if( !strncmp( 'taxrate', $propItem->getType(), 7 ) ) {
332
				$list[$propItem->getType()] = $propItem->getValue();
333
			}
334
		 }
335
336
		 return $list;
337
	 }
338
339
340
	/**
341
	 * Sets the new tax rate.
342
	 *
343
	 * @param string|integer|double $taxrate Tax rate with two digits precision
344
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
345
	 */
346
	public function setTaxRate( $taxrate )
347
	{
348
		if( (string) $taxrate !== $this->getTaxRate() )
349
		{
350
			$this->values['price.taxrate'] = (string) $this->checkPrice( $taxrate );
351
			$this->setModified();
352
		}
353
354
		return $this;
355
	}
356
357
358
	/**
359
	 * Returns the tax rate flag.
360
	 *
361
	 * True if tax is included in the price value, costs and rebate, false if not
362
	 *
363
	 * @return boolean Tax rate flag for the price
364
	 */
365
	public function getTaxFlag()
366
	{
367
		if( isset( $this->values['price.taxflag'] ) ) {
368
			return (bool) $this->values['price.taxflag'];
369
		}
370
371
		return true;
372
	}
373
374
375
	/**
376
	 * Sets the new tax flag.
377
	 *
378
	 * @param boolean $flag True if tax is included in the price value, costs and rebate, false if not
379
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
380
	*/
381
	public function setTaxFlag( $flag )
382
	{
383
		if( (bool) $flag !== $this->getTaxFlag() )
384
		{
385
			$this->values['price.taxflag'] = (bool) $flag;
386
			$this->setModified();
387
		}
388
389
		return $this;
390
	}
391
392
393
	/**
394
	 * Returns the tax for the price item
395
	 *
396
	 * @return string Tax value with four digits precision
397
	 * @see mshop/price/taxflag
398
	 */
399
	public function getTaxValue()
400
	{
401
		if( !isset( $this->values['price.tax'] ) )
402
		{
403
			$taxrate = $this->getTaxRate();
404
405
			if( $this->getTaxFlag() !== false ) {
406
				$tax = ( $this->getValue() + $this->getCosts() ) / ( 100 + $taxrate ) * $taxrate;
407
			} else {
408
				$tax = ( $this->getValue() + $this->getCosts() ) * $taxrate / 100;
409
			}
410
411
			$this->values['price.tax'] = $this->formatNumber( $tax, $this->precision + 2 );
412
		}
413
414
		return (string) $this->values['price.tax'];
415
	}
416
417
418
	/**
419
	 * Sets the tax amount
420
	 *
421
	 * @param string|integer|double $value Tax value with up to four digits precision
422
	 */
423
	public function setTaxValue( $value )
424
	{
425
		if( (string) $value !== $this->getTaxValue() )
426
		{
427
			$this->values['price.tax'] = (string) $this->checkPrice( $value, $this->precision + 2 );
428
			parent::setModified(); // don't unset tax immediately again
429
		}
430
431
		return $this;
432
	}
433
434
435
	/**
436
	 * Returns the status of the item
437
	 *
438
	 * @return integer Status of the item
439
	 */
440
	public function getStatus()
441
	{
442
		if( isset( $this->values['price.status'] ) ) {
443
			return (int) $this->values['price.status'];
444
		}
445
446
		return 1;
447
	}
448
449
450
	/**
451
	 * Sets the status of the item
452
	 *
453
	 * @param integer $status Status of the item
454
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
455
	 */
456
	public function setStatus( $status )
457
	{
458
		if( (int) $status !== $this->getStatus() )
459
		{
460
			$this->values['price.status'] = (int) $status;
461
			$this->setModified();
462
		}
463
464
		return $this;
465
	}
466
467
468
	/**
469
	 * Sets the modified flag of the object.
470
	 */
471
	public function setModified()
472
	{
473
		parent::setModified();
474
		unset( $this->values['price.tax'] );
475
	}
476
477
478
	/**
479
	 * Tests if the item is available based on status, time, language and currency
480
	 *
481
	 * @return boolean True if available, false if not
482
	 */
483
	public function isAvailable()
484
	{
485
		return parent::isAvailable() && $this->getStatus() > 0
486
			&& ( $this->values['currencyid'] === null || $this->getCurrencyId() === $this->values['currencyid'] );
487
	}
488
489
490
	/**
491
	 * Add the given price to the current one.
492
	 *
493
	 * @param \Aimeos\MShop\Price\Item\Iface $item Price item which should be added
494
	 * @param integer $quantity Number of times the Price should be added
495
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
496
	 */
497
	public function addItem( \Aimeos\MShop\Price\Item\Iface $item, $quantity = 1 )
498
	{
499
		if( $item->getCurrencyId() != $this->getCurrencyId() )
500
		{
501
			$msg = 'Price can not be added. Currency ID "%1$s" of price item and currently used currency ID "%2$s" does not match.';
502
			throw new \Aimeos\MShop\Price\Exception( sprintf( $msg, $item->getCurrencyId(), $this->getCurrencyId() ) );
503
		}
504
505
		if( $this === $item ) { $item = clone $item; }
506
		$taxValue = $this->getTaxValue();
507
508
		$this->setQuantity( 1 );
509
		$this->setValue( $this->getValue() + $item->getValue() * $quantity );
510
		$this->setCosts( $this->getCosts() + $item->getCosts() * $quantity );
511
		$this->setRebate( $this->getRebate() + $item->getRebate() * $quantity );
512
		$this->setTaxValue( $taxValue + $item->getTaxValue() * $quantity );
513
514
		return $this;
515
	}
516
517
518
	/**
519
	 * Resets the values of the price item.
520
	 * The currency ID, domain, type and status stays the same.
521
	 *
522
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
523
	 */
524
	public function clear()
525
	{
526
		$this->setQuantity( 1 );
527
		$this->setValue( '0.00' );
528
		$this->setCosts( '0.00' );
529
		$this->setRebate( '0.00' );
530
		$this->setTaxRate( '0.00' );
531
		unset( $this->values['price.tax'] );
532
533
		return $this;
534
	}
535
536
537
	/*
538
	 * Sets the item values from the given array and removes that entries from the list
539
	 *
540
	 * @param array &$list Associative list of item keys and their values
541
	 * @param boolean True to set private properties too, false for public only
542
	 * @return \Aimeos\MShop\Price\Item\Iface Price item for chaining method calls
543
	 */
544
	public function fromArray( array &$list, $private = false )
545
	{
546
		$item = parent::fromArray( $list, $private );
547
548
		foreach( $list as $key => $value )
549
		{
550
			switch( $key )
551
			{
552
				case 'price.type': $item = $item->setType( $value ); break;
553
				case 'price.currencyid': $item = $item->setCurrencyId( $value ); break;
554
				case 'price.domain': $item = $item->setDomain( $value ); break;
555
				case 'price.quantity': $item = $item->setQuantity( $value ); break;
556
				case 'price.value': $item = $item->setValue( $value ); break;
557
				case 'price.costs': $item = $item->setCosts( $value ); break;
558
				case 'price.rebate': $item = $item->setRebate( $value ); break;
559
				case 'price.taxvalue': $item = $item->setTaxValue( $value ); break;
560
				case 'price.taxrate': $item = $item->setTaxRate( $value ); break;
561
				case 'price.taxflag': $item = $item->setTaxFlag( $value ); break;
562
				case 'price.status': $item = $item->setStatus( $value ); break;
563
				case 'price.label': $item = $item->setLabel( $value ); break;
564
				default: continue 2;
565
			}
566
567
			unset( $list[$key] );
568
		}
569
570
		return $item;
571
	}
572
573
574
	/**
575
	 * Returns the item values as array.
576
	 *
577
	 * @param boolean True to return private properties, false for public only
578
	 * @return array Associative list of item properties and their values
579
	 */
580
	public function toArray( $private = false )
581
	{
582
		$list = parent::toArray( $private );
583
584
		$list['price.type'] = $this->getType();
585
		$list['price.currencyid'] = $this->getCurrencyId();
586
		$list['price.domain'] = $this->getDomain();
587
		$list['price.quantity'] = $this->getQuantity();
588
		$list['price.value'] = $this->getValue();
589
		$list['price.costs'] = $this->getCosts();
590
		$list['price.rebate'] = $this->getRebate();
591
		$list['price.taxvalue'] = $this->getTaxValue();
592
		$list['price.taxrate'] = $this->getTaxRate();
593
		$list['price.taxflag'] = $this->getTaxFlag();
594
		$list['price.status'] = $this->getStatus();
595
		$list['price.label'] = $this->getLabel();
596
597
		return $list;
598
	}
599
}
600