Price.php in Price 2.x
Same filename in this branch
Same filename and directory in other branches
Namespace
Drupal\priceFile
src/Price.phpView source
<?php
namespace Drupal\price;
use Drupal\price\Exception\CurrencyMismatchException;
/**
* Provides a value object for monetary values.
*
* Use the price.currency_formatter service to format prices.
*/
final class Price {
/**
* The number.
*
* @var string
*/
protected $number;
/**
* The currency code.
*
* @var string
*/
protected $currencyCode;
/**
* Constructs a new Price object.
*
* @param string $number
* The number.
* @param string $currency_code
* The currency code.
*/
public function __construct(string $number, string $currency_code) {
Calculator::assertNumberFormat($number);
$this
->assertCurrencyCodeFormat($currency_code);
$this->number = (string) $number;
$this->currencyCode = strtoupper($currency_code);
}
/**
* Creates a new price from the given array.
*
* @param array $price
* The price array, with the "number" and "currency_code" keys.
*
* @return static
*/
public static function fromArray(array $price) : Price {
if (!isset($price['number'], $price['currency_code'])) {
throw new \InvalidArgumentException('Price::fromArray() called with a malformed array.');
}
return new static($price['number'], $price['currency_code']);
}
/**
* Gets the number.
*
* @return string
* The number.
*/
public function getNumber() : string {
return $this->number;
}
/**
* Gets the currency code.
*
* @return string
* The currency code.
*/
public function getCurrencyCode() : string {
return $this->currencyCode;
}
/**
* Gets the string representation of the price.
*
* @return string
* The string representation of the price.
*/
public function __toString() : string {
return Calculator::trim($this->number) . ' ' . $this->currencyCode;
}
/**
* Gets the array representation of the price.
*
* @return array
* The array representation of the price.
*/
public function toArray() : array {
return [
'number' => $this->number,
'currency_code' => $this->currencyCode,
];
}
/**
* Converts the current price to the given currency.
*
* @param string $currency_code
* The currency code.
* @param string $rate
* A currency rate corresponding to the currency code.
*
* @return static
* The resulting price.
*/
public function convert($currency_code, $rate = '1') : Price {
$new_number = Calculator::multiply($this->number, $rate);
return new static($new_number, $currency_code);
}
/**
* Adds the given price to the current price.
*
* @param \Drupal\price\Price $price
* The price.
*
* @return static
* The resulting price.
*/
public function add(Price $price) : Price {
$this
->assertSameCurrency($this, $price);
$new_number = Calculator::add($this->number, $price
->getNumber());
return new static($new_number, $this->currencyCode);
}
/**
* Subtracts the given price from the current price.
*
* @param \Drupal\price\Price $price
* The price.
*
* @return static
* The resulting price.
*/
public function subtract(Price $price) : Price {
$this
->assertSameCurrency($this, $price);
$new_number = Calculator::subtract($this->number, $price
->getNumber());
return new static($new_number, $this->currencyCode);
}
/**
* Multiplies the current price by the given number.
*
* @param string $number
* The number.
*
* @return static
* The resulting price.
*/
public function multiply(string $number) : Price {
$new_number = Calculator::multiply($this->number, $number);
return new static($new_number, $this->currencyCode);
}
/**
* Divides the current price by the given number.
*
* @param string $number
* The number.
*
* @return static
* The resulting price.
*/
public function divide(string $number) : Price {
$new_number = Calculator::divide($this->number, $number);
return new static($new_number, $this->currencyCode);
}
/**
* Compares the current price with the given price.
*
* @param \Drupal\price\Price $price
* The price.
*
* @return int
* 0 if both prices are equal, 1 if the first one is greater, -1 otherwise.
*/
public function compareTo(Price $price) : int {
$this
->assertSameCurrency($this, $price);
return Calculator::compare($this->number, $price
->getNumber());
}
/**
* Gets whether the current price is positive.
*
* @return bool
* TRUE if the price is positive, FALSE otherwise.
*/
public function isPositive() : bool {
return Calculator::compare($this->number, '0') == 1;
}
/**
* Gets whether the current price is negative.
*
* @return bool
* TRUE if the price is negative, FALSE otherwise.
*/
public function isNegative() : bool {
return Calculator::compare($this->number, '0') == -1;
}
/**
* Gets whether the current price is zero.
*
* @return bool
* TRUE if the price is zero, FALSE otherwise.
*/
public function isZero() : bool {
return Calculator::compare($this->number, '0') == 0;
}
/**
* Gets whether the current price is equivalent to the given price.
*
* @param \Drupal\price\Price $price
* The price.
*
* @return bool
* TRUE if the prices are equal, FALSE otherwise.
*/
public function equals(Price $price) : bool {
return $this
->compareTo($price) == 0;
}
/**
* Gets whether the current price is greater than the given price.
*
* @param \Drupal\price\Price $price
* The price.
*
* @return bool
* TRUE if the current price is greater than the given price,
* FALSE otherwise.
*/
public function greaterThan(Price $price) : bool {
return $this
->compareTo($price) == 1;
}
/**
* Gets whether the current price is greater than or equal to the given price.
*
* @param \Drupal\price\Price $price
* The price.
*
* @return bool
* TRUE if the current price is greater than or equal to the given price,
* FALSE otherwise.
*/
public function greaterThanOrEqual(Price $price) : bool {
return $this
->greaterThan($price) || $this
->equals($price);
}
/**
* Gets whether the current price is lesser than the given price.
*
* @param \Drupal\price\Price $price
* The price.
*
* @return bool
* TRUE if the current price is lesser than the given price,
* FALSE otherwise.
*/
public function lessThan(Price $price) : bool {
return $this
->compareTo($price) == -1;
}
/**
* Gets whether the current price is lesser than or equal to the given price.
*
* @param \Drupal\price\Price $price
* The price.
*
* @return bool
* TRUE if the current price is lesser than or equal to the given price,
* FALSE otherwise.
*/
public function lessThanOrEqual(Price $price) : bool {
return $this
->lessThan($price) || $this
->equals($price);
}
/**
* Asserts that the currency code is in the right format.
*
* Serves only as a basic sanity check.
*
* @param string $currency_code
* The currency code.
*
* @throws \InvalidArgumentException
* Thrown when the currency code is not in the right format.
*/
protected function assertCurrencyCodeFormat($currency_code) {
if (strlen($currency_code) != '3') {
throw new \InvalidArgumentException(sprintf('Invalid currency code "%s".', $currency_code));
}
}
/**
* Asserts that the two prices have the same currency.
*
* @param \Drupal\price\Price $first_price
* The first price.
* @param \Drupal\price\Price $second_price
* The second price.
*
* @throws \Drupal\price\Exception\CurrencyMismatchException
* Thrown when the prices do not have the same currency.
*/
protected function assertSameCurrency(Price $first_price, Price $second_price) {
if ($first_price
->getCurrencyCode() != $second_price
->getCurrencyCode()) {
throw new CurrencyMismatchException(sprintf('The provided prices have mismatched currencies: %s, %s.', $first_price
->__toString(), $second_price
->__toString()));
}
}
}