useless-stuff
2/10/2016 - 4:11 PM

PHP - Closure

PHP - Closure

<?php
/**
 * Class Basket
 */
class Basket
{

    protected $productsQuantityCollection;
    protected $productsCollection;
    protected $tax                  = 1.2;
    protected $currency             = '&#128;';

    /**
     * Basket constructor.
     */
    public function __construct()
    {
        $this->initializeCollections();
    }

    /**
     *
     */
    protected function initializeCollections(){
        $this->productsCollection = new \ArrayIterator();
        $this->productsQuantityCollection = new \ArrayIterator();
    }

    /**
     * @param Product $product
     * @param $quantity
     */
    public function add(Product $product, $quantity = 1)
    {
        $productSlug = $product->getSlug();
        if(!$this->productsQuantityCollection->offsetExists($productSlug)){
            $this->productsQuantityCollection->offsetSet($productSlug,$quantity);
        }else{
            $this->productsQuantityCollection->offsetSet($productSlug,$quantity + $this->productsQuantityCollection->offsetGet($productSlug));
        }
        $this->productsCollection->offsetSet($productSlug,$product);
    }

    /**
     * @return float
     */
    public function getTotal()
    {
        $total = 0.0;
        $tax = $this->getTax();
        $productsQuantity =  $this->productsQuantityCollection;
        // CLOUSURE
        $callback = function (Product $product) use ($productsQuantity, $tax, &$total) {
            $total += ($product->getPrice() * $productsQuantity->offsetGet($product->getSlug())) * $tax;

            return $total;
        };
        array_walk($this->productsCollection, $callback);

        return round($total, 2);
    }

    /**
     * @return float
     */
    public function getTax()
    {

        return $this->tax;
    }

    /**
     * @return float
     */
    public function getCurrency()
    {

        return $this->currency;
    }

    /**
     * @return integer
     */
    public function getProductsSum(){

       return array_sum($this->productsQuantityCollection->getArrayCopy());
    }

    /**
     *
     */
    public function clear(){
        $this->initializeCollections();
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return "Basket contains ".$this->getProductsSum().' products, Total amount is '.number_format($this->getTotal(),2).' '.$this->getCurrency();
    }

}

/**
 * Class Product
 */
class Product
{

    use Slugify {
        Slugify::getSlug as getSlugTrait;
    }

    protected $name;
    protected $price;
    protected $slug = false;

    /**
     * Product constructor.
     * @param $name
     * @param $price
     */
    public function __construct($name, $price)
    {

        $this->setName($name);
        $this->setPrice($price);
    }

    /**
     * @return string;
     */
    public function getSlug()
    {
        if(!$this->slug){
            return $this->getSlugTrait($this->getName());
        }
        return $this->slug;
    }

    /**
     * @return string
     */
    public function getName()
    {

        return $this->name;
    }

    /**
     * @param string $name
     */
    public function setName($name)
    {

        $this->name = $name;
    }

    /**
     * @return float
     */
    public function getPrice()
    {

        return $this->price;
    }

    /**
     * @param float $price
     */
    public function setPrice($price)
    {

        $this->price = $price;
    }

    /**
     * @return string
     */
    public function __toString()
    {

        return $this->name;
    }
}

/**
 * Class Slugify
 */
trait Slugify
{

    function getSlug($text)
    {

        $text = preg_replace('~[^\\pL\d]+~u', '-', $text);
        $text = trim($text, '-');
        $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
        $text = strtolower($text);
        $text = preg_replace('~[^-\w]+~', '', $text);
        if (empty($text)) {
            throw new \RuntimeException("The value given does not convertible to string .".__METHOD__);
        }

        return $text;
    }
}

$basket = new Basket();
echo $basket;
//output: Basket contains 0 products, Total amount is 0 €

$apple = new Product('apple',1.0);
$basket->add($apple,2);
echo $basket;
$basket->clear();
//output: Basket contains 2 products, Total amount is 2.4 €

$banana = new Product('banana',1.5);
$basket->add($banana);
$basket->add($apple);
echo $basket;
$basket->clear();
//output: Basket contains 2 products, Total amount is 3.00 €