<?php
/**
 * A class for rendering sets of composite templates.
 *
 * This class provides a way to render a set of composite templates using a
 * decorator strategy.
 */
class view_renderer_composite implements view_renderer
{
    ////////////////////////////////////////////////////////////////////////////
    // Construct and destruct functions.

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

    ////////////////////////////////////////////////////////////////////////////
    // Interface functions.
    
    /**
     * Renders a set of composite templates.
     * 
     * @param string/array $template The composite template(s).
     * @param array (optional) $data The template variables.
     * @throws logicexception If a 'content' or 'template' variable is supplied.
     * @return string The rendered templates.
     */
    public function render($template, array $data = array())
    {
        if (array_key_exists('content', $data) || array_key_exists('template', $data))
        {
            throw new logicexception('Template variable \'content\' and \'template\' are reserved variables.');
        }
        
        if (!is_array($template))
        {
            $template = array($template);
        }
        
        foreach (array_reverse($template) as $t)
        {
            $data['content'] = $this->render_composite($t, $data);
        }
        
        return $data['content'];
    }
    
    ////////////////////////////////////////////////////////////////////////////
    // Internal functions.
    
    /**
     * Renders a composite template.
     *
     * @param string $template The composite template.
     * @param array $data The template variables.
     * @throws logicexception If the composite template file is missing.
     * @throws unexpectedvalueexception If the output buffer could not be
     * started or retrieved.
     * @return string The rendered template.
     */
    protected function render_composite($template, array $data)
    {
        if (!is_file($template))
        {
            throw new logicexception('Composite template file ' . var_export($template, true) . ' is missing.');
        }
        
        if (!ob_start())
        {
            throw new unexpectedvalueexception('Output buffer could not be started.');
        }
        
        extract($data);
        include $template;
        $content = ob_get_clean();
        
        if ($content === false)
        {
            throw new unexpectedvalueexception('Output buffer could not be retrieved.');
        }
        
        return $content;
    }
}
