Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- declare(strict_types=1);
- final class Currency
- {
- private $value;
- public function __construct(string $currency)
- {
- $this->value = $currency;
- }
- public function equals(Currency $currency): bool
- {
- return $this->value === $currency->value;
- }
- public function __toString(): string
- {
- return $this->value;
- }
- }
- final class Money
- {
- private $amount;
- private $currency;
- public function __construct(int $amount, Currency $currency)
- {
- $this->amount = $amount;
- $this->currency = $currency;
- }
- public function getAmount(): int
- {
- return $this->amount;
- }
- public function getCurrency(): Currency
- {
- return $this->currency;
- }
- }
- interface RoundingPolicyInterface
- {
- public function round(float $value): float;
- }
- final class RoundingHalfUpPolicy implements RoundingPolicyInterface
- {
- public $precision;
- public function __construct(int $precision)
- {
- $this->precision = $precision;
- }
- public function round(float $value): float
- {
- return round($value, $this->precision, PHP_ROUND_HALF_UP);
- }
- }
- interface MoneyCalculatorInterface
- {
- public function multiply(Money $base, float $amount): Money;
- }
- final class StandardMoneyCalculator implements MoneyCalculatorInterface
- {
- private $roundingPolicy;
- public function __construct(RoundingPolicyInterface $roundingPolicy)
- {
- $this->roundingPolicy = $roundingPolicy;
- }
- public function multiply(Money $base, float $amount): Money
- {
- $value = $base->getAmount() * $amount;
- $value = $this->roundingPolicy->round($value);
- $value = intval($value); // atomic
- return new Money($value, clone $base->getCurrency());
- }
- }
- interface TaxInterface
- {
- public function getMultiplier(): float;
- }
- final class PercentageTax implements TaxInterface
- {
- private $multiplier;
- public function __construct(float $multiplier)
- {
- if ($multiplier < 0) {
- throw new Exception();
- }
- $this->multiplier = $multiplier;
- }
- public function getMultiplier(): float
- {
- return $this->multiplier;
- }
- }
- final class ReleasedTax implements TaxInterface
- {
- public function getMultiplier(): float
- {
- return 1.0;
- }
- }
- interface PriceCreator
- {
- public function create(Money $money): Price;
- }
- final class BruttoPriceCreator implements PriceCreator
- {
- private $moneyCalculator;
- private $tax;
- public function __construct(MoneyCalculatorInterface $moneyCalculator, TaxInterface $tax)
- {
- $this->moneyCalculator = $moneyCalculator;
- $this->tax = $tax;
- }
- public function create(Money $bruttoMoney): Price
- {
- $multiplier = 1 / $this->tax->getMultiplier();
- $nettoMoney = $this->moneyCalculator->multiply($bruttoMoney, $multiplier);
- return new Price(clone $bruttoMoney, $nettoMoney, clone $this->tax);
- }
- }
- final class Price
- {
- private $brutto;
- private $netto;
- private $tax;
- public function __construct(Money $brutto, Money $netto, TaxInterface $tax)
- {
- $this->brutto = $brutto;
- $this->netto = $netto;
- $this->tax = $tax;
- }
- public function getBruttoMoney(): Money
- {
- return $this->brutto;
- }
- public function getNettoMoney(): Money
- {
- return $this->netto;
- }
- }
- interface MoneyFormaterInterface
- {
- public function format(Money $money): string;
- }
- final class WithoutCurrencyMoneyFormater implements MoneyFormaterInterface
- {
- private $precision;
- private $decimalSeparator;
- private $thousandsSeparator;
- public function __construct(int $precision, string $decimalSeparator, string $thousandsSeparator)
- {
- if ($precision < 0) {
- throw new Exception();
- }
- $this->precision = $precision;
- $this->decimalSeparator = $decimalSeparator;
- $this->thousandsSeparator = $thousandsSeparator;
- }
- public function format(Money $money): string
- {
- $amount = $money->getAmount();
- if ($this->precision > 0) {
- $amount = $amount / pow(10, $this->precision);
- }
- return number_format($amount, $this->precision, $this->decimalSeparator, $this->thousandsSeparator);
- }
- }
- interface XMLPriceSerializer
- {
- public function serialize(XMLWriter $writer, Price $price);
- }
- class StandardXMLNettoPriceSerializer implements XMLPriceSerializer
- {
- private $moneyFormater;
- public function __construct(MoneyFormaterInterface $moneyFormater)
- {
- $this->moneyFormater = $moneyFormater;
- }
- public function serialize(XMLWriter $writer, Price $price)
- {
- $money = $price->getNettoMoney();
- $expression = $this->moneyFormater->format($money);
- $writer->startElement('price');
- {
- $writer->startAttribute('currency');
- $writer->text((string)$money->getCurrency());
- $writer->endAttribute();
- $writer->text($expression);
- }
- $writer->endElement();
- }
- }
- $brutto = new Money(1200, new Currency('PLN'));
- $tax = new PercentageTax(1.23);
- $roundingPolicy = new RoundingHalfUpPolicy(0);
- $moneyCalculator = new StandardMoneyCalculator($roundingPolicy);
- $bruttoPriceCreator = new BruttoPriceCreator($moneyCalculator, $tax);
- $price = $bruttoPriceCreator->create($brutto);
- $moneyFormater = new WithoutCurrencyMoneyFormater(2, '.', '');
- $serializer = new StandardXMLNettoPriceSerializer($moneyFormater);
- $writer = new XMLWriter();
- $writer->openUri('php://output');
- $writer->setIndent(true);
- $writer->startDocument('1.0','UTF-8');
- $writer->startElement('product');
- $serializer->serialize($writer, $price);
- $writer->endElement();
- $writer->endDocument();
- $writer->flush();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement