<?php
/**
 * A class for filtering values using a sequence of filters.
 *
 * This class provides a way to create a sequence of filters and filter
 * a value against that sequence.
 */
class filter_macro implements filter
{
    /**
     * @var array The sequence of filters.
     */
    protected $macro;

    ////////////////////////////////////////////////////////////////////////////
    // Construct and destruct functions.

    /**
     * @param array $macro The sequence of filters.
     */
    public function __construct(array $macro)
    {
        $this->clear();
        
        foreach ($macro as $k => $v)
        {
            $this->set($v, $k);
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    // Overload functions.

    ////////////////////////////////////////////////////////////////////////////
    // Interface functions.

    /**
     * Filters a value.
     * 
     * @param mixed $value Description.
     * @return mixed Description.
     */
    public function filter($value)
    {
        foreach ($this->macro as $f)
        {
            $value = $f->filter($value);
        }
        
        return $value;
    }
    
    /**
     * Sets a filter.
     * 
     * @param filter $filter The filter.
     * @param string (optional) $name The filter name.
     * @return filter_macro A fluent interface.
     */
    public function set(filter $filter, $name = null)
    {
        if ($name === null)
        {
            $this->macro[] = $filter;
        }
        else
        {
            $this->macro[$name] = $filter;
        }
        
        return $this;
    }

    /**
     * Clears one or all filters.
     * 
     * @param string (optional) $name The filter name.
     * @return filter_macro A fluent interface.
     */
    public function clear($name = null)
    {
        if ($name === null)
        {
            $this->macro = array();
        }
        else
        {
            unset($this->macro[$name]);
        }
        
        return $this;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Internal functions.
}
