Advertisement
lignite0

Idealny sklep - PriceSerializer

Jan 23rd, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 5.95 KB | None | 0 0
  1. <?php
  2.  
  3. declare(strict_types=1);
  4.  
  5. final class Currency
  6. {
  7.     private $value;
  8.  
  9.     public function __construct(string $currency)
  10.     {
  11.         $this->value = $currency;
  12.     }
  13.  
  14.     public function equals(Currency $currency): bool
  15.     {
  16.         return $this->value === $currency->value;
  17.     }
  18.  
  19.     public function __toString(): string
  20.     {
  21.         return $this->value;
  22.     }
  23. }
  24.  
  25. final class Money
  26. {
  27.     private $amount;
  28.     private $currency;
  29.  
  30.     public function __construct(int $amount, Currency $currency)
  31.     {
  32.         $this->amount = $amount;
  33.         $this->currency = $currency;
  34.     }
  35.  
  36.     public function getAmount(): int
  37.     {
  38.         return $this->amount;
  39.     }
  40.  
  41.     public function getCurrency(): Currency
  42.     {
  43.         return $this->currency;
  44.     }
  45. }
  46.  
  47. interface RoundingPolicyInterface
  48. {
  49.     public function round(float $value): float;
  50. }
  51.  
  52. final class RoundingHalfUpPolicy implements RoundingPolicyInterface
  53. {
  54.     public $precision;
  55.  
  56.     public function __construct(int $precision)
  57.     {
  58.         $this->precision = $precision;
  59.     }
  60.  
  61.     public function round(float $value): float
  62.     {
  63.         return round($value, $this->precision, PHP_ROUND_HALF_UP);
  64.     }
  65. }
  66.  
  67. interface MoneyCalculatorInterface
  68. {
  69.     public function multiply(Money $base, float $amount): Money;
  70. }
  71.  
  72. final class StandardMoneyCalculator implements MoneyCalculatorInterface
  73. {
  74.     private $roundingPolicy;
  75.  
  76.     public function __construct(RoundingPolicyInterface $roundingPolicy)
  77.     {
  78.         $this->roundingPolicy = $roundingPolicy;
  79.     }
  80.  
  81.     public function multiply(Money $base, float $amount): Money
  82.     {
  83.         $value = $base->getAmount() * $amount;
  84.         $value = $this->roundingPolicy->round($value);
  85.         $value = intval($value); // atomic
  86.  
  87.         return new Money($value, clone $base->getCurrency());
  88.     }
  89. }
  90.  
  91. interface TaxInterface
  92. {
  93.     public function getMultiplier(): float;
  94. }
  95.  
  96. final class PercentageTax implements TaxInterface
  97. {
  98.     private $multiplier;
  99.  
  100.     public function __construct(float $multiplier)
  101.     {
  102.         if ($multiplier < 0) {
  103.             throw new Exception();
  104.         }
  105.  
  106.         $this->multiplier = $multiplier;
  107.     }
  108.  
  109.     public function getMultiplier(): float
  110.     {
  111.         return $this->multiplier;
  112.     }
  113. }
  114.  
  115. final class ReleasedTax implements TaxInterface
  116. {
  117.     public function getMultiplier(): float
  118.     {
  119.         return 1.0;
  120.     }
  121. }
  122.  
  123. interface PriceCreator
  124. {
  125.     public function create(Money $money): Price;
  126. }
  127.  
  128. final class BruttoPriceCreator implements PriceCreator
  129. {
  130.     private $moneyCalculator;
  131.     private $tax;
  132.  
  133.     public function __construct(MoneyCalculatorInterface $moneyCalculator, TaxInterface $tax)
  134.     {
  135.         $this->moneyCalculator = $moneyCalculator;
  136.         $this->tax = $tax;
  137.     }
  138.  
  139.     public function create(Money $bruttoMoney): Price
  140.     {
  141.         $multiplier = 1 / $this->tax->getMultiplier();
  142.         $nettoMoney = $this->moneyCalculator->multiply($bruttoMoney, $multiplier);
  143.  
  144.         return new Price(clone $bruttoMoney, $nettoMoney, clone $this->tax);
  145.     }
  146. }
  147.  
  148. final class Price
  149. {
  150.     private $brutto;
  151.     private $netto;
  152.     private $tax;
  153.  
  154.     public function __construct(Money $brutto, Money $netto, TaxInterface $tax)
  155.     {
  156.         $this->brutto = $brutto;
  157.         $this->netto = $netto;
  158.         $this->tax = $tax;
  159.     }
  160.  
  161.     public function getBruttoMoney(): Money
  162.     {
  163.         return $this->brutto;
  164.     }
  165.  
  166.     public function getNettoMoney(): Money
  167.     {
  168.         return $this->netto;
  169.     }
  170. }
  171.  
  172. interface MoneyFormaterInterface
  173. {
  174.     public function format(Money $money): string;
  175. }
  176.  
  177. final class WithoutCurrencyMoneyFormater implements MoneyFormaterInterface
  178. {
  179.     private $precision;
  180.     private $decimalSeparator;
  181.     private $thousandsSeparator;
  182.  
  183.     public function __construct(int $precision, string $decimalSeparator, string $thousandsSeparator)
  184.     {
  185.         if ($precision < 0) {
  186.             throw new Exception();
  187.         }
  188.  
  189.         $this->precision = $precision;
  190.         $this->decimalSeparator = $decimalSeparator;
  191.         $this->thousandsSeparator = $thousandsSeparator;
  192.     }
  193.  
  194.     public function format(Money $money): string
  195.     {
  196.         $amount = $money->getAmount();
  197.         if ($this->precision > 0) {
  198.             $amount = $amount / pow(10, $this->precision);
  199.         }
  200.  
  201.         return number_format($amount, $this->precision, $this->decimalSeparator, $this->thousandsSeparator);
  202.     }
  203. }
  204.  
  205. interface XMLPriceSerializer
  206. {
  207.     public function serialize(XMLWriter $writer, Price $price);
  208. }
  209.  
  210. class StandardXMLNettoPriceSerializer implements XMLPriceSerializer
  211. {
  212.     private $moneyFormater;
  213.  
  214.     public function __construct(MoneyFormaterInterface $moneyFormater)
  215.     {
  216.         $this->moneyFormater = $moneyFormater;
  217.     }
  218.  
  219.     public function serialize(XMLWriter $writer, Price $price)
  220.     {
  221.         $money = $price->getNettoMoney();
  222.         $expression = $this->moneyFormater->format($money);
  223.  
  224.         $writer->startElement('price');
  225.         {
  226.             $writer->startAttribute('currency');
  227.             $writer->text((string)$money->getCurrency());
  228.             $writer->endAttribute();
  229.  
  230.             $writer->text($expression);
  231.         }
  232.         $writer->endElement();
  233.     }
  234. }
  235.  
  236. $brutto = new Money(1200, new Currency('PLN'));
  237. $tax = new PercentageTax(1.23);
  238. $roundingPolicy = new RoundingHalfUpPolicy(0);
  239. $moneyCalculator = new StandardMoneyCalculator($roundingPolicy);
  240. $bruttoPriceCreator = new BruttoPriceCreator($moneyCalculator, $tax);
  241. $price = $bruttoPriceCreator->create($brutto);
  242. $moneyFormater = new WithoutCurrencyMoneyFormater(2, '.', '');
  243. $serializer = new StandardXMLNettoPriceSerializer($moneyFormater);
  244.  
  245. $writer = new XMLWriter();
  246. $writer->openUri('php://output');
  247. $writer->setIndent(true);
  248. $writer->startDocument('1.0','UTF-8');
  249. $writer->startElement('product');
  250. $serializer->serialize($writer, $price);
  251. $writer->endElement();
  252. $writer->endDocument();
  253. $writer->flush();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement