chippyash/Builder-Pattern

View on GitHub
src/Chippyash/BuilderPattern/AbstractDirector.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
/*
 * Builder Pattern Library
 *
 * @author Ashley Kitson <akitson@zf4.biz>
 * @copyright Ashley Kitson, UK, 2014
 * @licence GPL V3 or later : http://www.gnu.org/licenses/gpl.html
 * @link http://en.wikipedia.org/wiki/Builder_pattern
 */
namespace Chippyash\BuilderPattern;

use Chippyash\BuilderPattern\BuilderInterface;
use Chippyash\BuilderPattern\RendererInterface;
use Chippyash\BuilderPattern\DirectorInterface;
use Chippyash\BuilderPattern\ModifiableInterface;
use Chippyash\BuilderPattern\Exceptions\BuilderPatternException;
use Zend\EventManager\ResponseCollection;
use Zend\EventManager\EventManagerAwareInterface;

/**
 * Abstract builder director pattern
 * 
 * Supports building, rendering and modification of the build process
 */
abstract class AbstractDirector implements DirectorInterface, ModifiableInterface
{
    /**
     *
     * @var Chippyash\BuilderPattern\BuilderInterface
     */
    protected $builder;
    
    /**
     *
     * @var Chippyash\BuilderPattern\RendererInterface
     */
    protected $renderer;

    /**
     *
     * @var Chippyash\BuilderPattern\AbstractModifier
     */
    protected $modifier;
    
    /**
     * Modifications to be made
     * 
     * @var array
     */
    protected $modifications = [
        ModifiableInterface::PHASE_PRE_BUILD => [],
        ModifiableInterface::PHASE_POST_BUILD => []
    ];
    
    /**
     * Constructor
     *
     * @param \Chippyash\BuilderPattern\BuilderInterface $builder
     * @param \Chippyash\BuilderPattern\RendererInterface $renderer
     */
    public function __construct(BuilderInterface $builder, RendererInterface $renderer)
    {
        $this->builder = $builder;
        $this->renderer = $renderer;
    }

    /**
     * Build and render
     *
     * @return mixed Depends on rendering
     * @throws \Chippyash\BuilderPattern\Exceptions\BuilderPatternException
     */
    public function build()
    {
        $this->modifyPreBuild();
        if (!$this->builder->build()) {
            throw new BuilderPatternException('Unable to build');
        }
        $this->modifyPostBuild();

        return $this->renderer->render($this->builder);
    }
    
    /**
     * Set the builder modifier if required
     * 
     * @param EventManagerAwareInterface $modifier
     * 
     * @return Chippyash\BuilderPattern\AbstractDirector Fluent Interface
     */
    public function setModifier(EventManagerAwareInterface $modifier)
    {
        $this->modifier = $modifier;
        $this->builder->setModifier($modifier);
        
        return $this;
    }
    
    /**
     * Run a modification on the builder being controlled
     * by this director
     *
     * @param array $params - parameters to pass to modication responder
     * @param int $phase - phase we are running
     *
     * @return Zend\EventManager\ResponseCollection Response from trigger
     */
    public function modify(array $params = [], $phase = ModifiableInterface::PHASE_POST_BUILD)
    {
        if (!empty($this->modifier)) {
            return $this->modifier->getEventManager()
                    ->trigger($phase, $this, $params);
        }
        
        //return empty collection
        return new ResponseCollection();
    }
    
    /**
     * Add a modification to be triggered pre or post build
     * It is expected that concrete Directors will call this and/or have
     * methods that the user can call to set modifications via this method.
     * 
     * @param array|mixed $mod  ['name'=>modName,...] or simply the modName
     * @param string $phase Phase name, usually one of ModifiableInterface::PHASE_...
     * 
     * @return \Chippyash\BuilderPattern\AbstractDirector Fluent Interface
     */
    protected function addModification($mod, $phase = ModifiableInterface::PHASE_POST_BUILD)
    {
        if (!is_array($mod)) {
            $mod = ['name' => $mod];
        }
        $this->modifications[$phase][] = $mod;
        
        return $this;
    }
    
    /**
     * Fire event triggers for pre build modifications
     */
    protected function modifyPreBuild()
    {
        foreach ($this->modifications[ModifiableInterface::PHASE_PRE_BUILD] as $mod) {
            $this->modify($mod, ModifiableInterface::PHASE_PRE_BUILD);
        }
    }
    
    /**
     * Fire event triggers for post build modifications
     */
    protected function modifyPostBuild()
    {
        foreach ($this->modifications[ModifiableInterface::PHASE_POST_BUILD] as $mod) {
            $this->modify($mod);
        }
    }
}