Location: PHPKode > projects > PHPLayouts > PHPLayouts/libs/Template.php
<?php

/**
 * Template class
 *
 * @author rodix53 <hide@address.com>
 * @version 0.9.1-beta
 * @package php-layouts
 * @license http://creativecommons.org/licenses/by-nc/2.0/fr/ Creative Commons BY-NC 2.0
 */

/**
 * Include all the dependent librairies of PHPLayouts.
 */
require(dirname(__FILE__) . "/Cache.php");
require(dirname(__FILE__) . "/Layout.php");
require(dirname(__FILE__) . "/Helper.php");

class Template 
{
    const   VERSION                =  '0.9.2';
    const   EOL                    =  "\r\n";
    
    /**
     * Define directories where are located templates files
     * @var array
     */
    private $_template_dir         =  array();
    
    /**
     * Defines the default template extension, if he isn't provided
     * @var string
     */
    private $_default_ext          =  ".phtml";
    
    /**
     * If debugging is enabled, errors are not displayed
     * @var boolean
     */
    private static $_debugging      =  false;
        
    /**
     * If show copyright is enabled, a specific tag is
     * added in bottom of the source code of the page
     * @var boolean
     */
    private $_show_copyright       =  true;
    
    /**
     * Variables specific to the class of the template engine
     */
    private $_tpl_vars             =  array();
    private $_generation_time      =  0;
    
    /**
     * Variables referring to other child classes
     */
    private $_layout               =  null;
    private $_cache                =  null;
    
	public function __construct()
	{
        // Start timer of the generation time.
        $this->_generation_time = (int) microtime(true);
        
        // Init accessors.
        $this->_layout = new Layout($this->_template_dir);
        $this->_cache  = new Cache ($this->_template_dir);
        
        // Set default SCRIPT_NAME var.
        $this->setVar('_SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']);
	}
    
    /**
     * Trigger error
     *
     * @param string $error_msg
     * @param integer $error_type
     */
    public static function trigger_error($error_msg, $error_type = E_USER_WARNING)
    {
        // Generating random error ID xD !
        $random_error_id = rand(268435456, 4294967295);
        trigger_error('PHPLayouts Error #' . dechex($random_error_id) . ': ' . $error_msg, $error_type);
    }
    
    /**
     * Prevent E_NOTICE for nonexistent values
     *
     * If {@link strictVars()} is on, raises a notice.
     *
     * @param string $key
     * @return mixed
     */
    public function __get($key)
    {
        if (!array_key_exists($key, $this->_tpl_vars))
        {
            Template::trigger_error('key ' . $key . ' does not exist', E_USER_NOTICE);
            return false;
        }
        else if (substr($key, 0, 1) == '_')
        {
            Template::trigger_error('accessing private keys as ' . $key . ' is not allowed', E_USER_NOTICE);
            return false;
        }
        return $this->_tpl_vars[$key];
    }

    /**
     * Directly assigns a variable to the view script.
     *
     * Checks first to ensure that the caller is not attempting to set a
     * protected or private member (by checking for a prefixed underscore); if
     * not, the public member is set; otherwise, an exception is raised.
     *
     * @param string $key The variable name.
     * @param mixed $val The variable value.
     * @return false
     */
    public function __set($key, $val)
    {
        Template::trigger_error('setting vars directly isn\'t allowed, please use the setVar() function', E_USER_WARNING);
        return false;
    }
    
    /**
     * Allows testing with empty() and isset() to work inside
     * templates.
     *
     * @param  string $key
     * @return boolean
     */
    public function __isset($key)
    {
        if (substr($key, 0, 1) == '_')
        {
            Template::trigger_error('accessing private keys as ' . $key . ' is not allowed', E_USER_NOTICE);
            return false;
        }
        return array_key_exists($key, $this->_tpl_vars);
    }
    
    /**
     * Allows unset() on object properties to work
     *
     * @param string $key
     * @return void
     */
    public function __unset($key)
    {
        if (!array_key_exists($key, $this->_tpl_vars))
        {
            Template::trigger_error('key ' . $key . ' does not exist', E_USER_NOTICE);
            return false;
        }
        else if (substr($key, 0, 1) == '_')
        {
            Template::trigger_error('accessing private keys as ' . $key . ' is not allowed', E_USER_NOTICE);
            return false;
        }
        unset($this->_tpl_vars[$key]);
    }
    
    /**
     * Allow to use cache() function to access to
     * the _cache var class.
     *
     * @param string $method
     * @param string $arguments
     * @return void
     */
    public function __call($method, $arguments)
    {
        if ($method == "layout" || $method == "cache")
            return $this->{"_" . $method};
    }
    
    /**
     * Set a default template directory
     * @param string $tpl_dir Folder containing the template files
     * @return bool
     */
    public function setTemplateDir($tpl_dir)
    {
        if (!is_dir($tpl_dir))
		{
            Template::trigger_error('the template directory provided was not found in the file system of the server', E_USER_WARNING);
            return false;
        }
		/* $this->_template_dir[] = realpath(self::_cleanDir($tpl_dir));*/
		$this->_template_dir[] .= realpath($tpl_dir) . DIRECTORY_SEPARATOR;
        return true;
    }
	
	public static function _cleanDir($dir)
	{
		$dir  = preg_replace("/((^:)\/\/)/", "//", $dir);
		$dir .= DIRECTORY_SEPARATOR;
		return $dir;
	}
	
    /**
     * Add a template directory
     * @param string $tpl_dir Folder containing the template files
     * @return bool
     */
    public function addTemplateDir($tpl_dir)
    {
        if (!is_dir($tpl_dir))
		{
            Template::trigger_error('the template directory provided was not found in the file system of the server', E_USER_WARNING);
            return false;
        }
		/* $this->_template_dir[] = realpath(self::_cleanDir($tpl_dir)); */
		$this->_template_dir[] .= realpath($tpl_dir) . DIRECTORY_SEPARATOR;
        return true;
    }
    
    /**
     * Returns an array containing the template directory
     * @return array
     */
    public function getTemplateDir()
    {
        return (array) $this->_template_dir;
    }

    /**
     * Checks if the specified template file exists or not
     * @param string $template
     * @return bool
     */
    public function templateExists($template)
    {
        foreach ($this->_template_dir as $dir)
        {
            if (is_readable($dir . $template))
                return true;
        }
        return false;
    }
    
    /**
     * This function look for a template directory when a template name is provided
     * @param string $template Template name
     * @return string | bool
     */
    public function _searchTemplateDir($template)
    {
        foreach ($this->_template_dir as $dir)
        {
            if (is_readable($dir . $template))
                return $dir;
        }
        return false;
    }
    
    /**
     * Set a template variable
     * @param string $name
     * @param string $value
     */
	public function setVar($name, $value)
    {
        $this->_tpl_vars[$name] = $value;
    }
    
    /**
     * Get all assigned variables
	 * @return array
     */
    public function getVars()
    {
        return $this->_tpl_vars;
    }
    
    /**
     * Clear all templates variables
     */
    public function clearVars()
    {
        $this->_tpl_vars = array();
    }

    /**
     * Displays a template
     * @param string $file The template file
     */
	function display($file)
	{
        // If the template file doesn't exists.
        if (!$this->templateExists($file))
        {
            Template::trigger_error('the template file provided seems to do not exists', E_USER_WARNING);
            return;
        }
        
        // If layouts are activated.
        if ($this->layout()->isActivated())
        {   
            // Ajout du block réservé CONTENT.
            $this->layout()->addBlock('content', $file);
            
            // Système de cache.
            if ($this->cache()->isActivated())
            {
                $cache_file = $this->cache()->getCacheDir() . md5($file) . ".cache";
                
                if (!$this->cache()->checkCache($file))
                {
                    // Génération du contenu des blocks.
                    $blocks = $this->layout()->getBlocks();
                    foreach ($blocks as $block)
                    {
                        $this->layout()->_setContentBlock($block['name'], $this->render($block['file']));
                    }
                    $this->cache()->deleteCache($file);
                    
                    $content  = $this->render($this->layout()->getLayout(), $this->layout()->getLayoutDir());
                    $content .= $this->_generateCopyright($this->cache()->isActivated());
                    $this->cache()->createCache($file, $content);
                    echo $content;
                    return;
                }
                else
                {
                    ob_clean();
                    echo file_get_contents($cache_file);
                    return;
                }
            }

            // Génération du contenu des blocks.
            $blocks = $this->layout()->getBlocks();
            foreach ($blocks as $block)
            {
                $this->layout()->_setContentBlock($block['name'], $this->render($block['file']));
            }
            
            // Génération du layout si pas de cache.
            $content  = $this->render($this->layout()->getLayout(), $this->layout()->getLayoutDir());
            $content .= $this->_generateCopyright(false);
            echo $content;
        }
        else
        {
            // Système de cache.
            if ($this->cache()->isActivated())
            {
                $cache_file = $this->cache()->getCacheDir() . md5($file) . ".cache";
                
                if (!$this->cache()->checkCache($file))
                {
                    $this->cache()->deleteCache($file);
                    $content  = $this->render($file);
                    $content .= $this->_generateCopyright(true);
                    $this->cache()->createCache($file, $content);
                    echo $content;
                    return;
                }
                else
                {
                    ob_clean();
                    echo file_get_contents($cache_file);
                    return;
                }
            }
            
            echo $this->render($file);
            echo $this->_generateCopyright(false);
        }
        
        return;
	}
    
    /**
     * Render a template file.
     
     * @param string $file Template file to render
     * @param string $dir  Directory to force
     * @return string
     
     * @todo Default extension management
     */
    public function render($file, $dir = null)
    {
        if (!empty($dir))
        {
            // If the template file doesn't exists.
            if (!$this->templateExists($file))
            {
                Template::trigger_error('the template file provided seems to do not exists', E_USER_WARNING);
                return;
            }
        }
        // Search for a template directory.
        else
        {
            $dir = $this->_searchTemplateDir($file);
        }
        
        /**$realdir = realpath($dir) . "\\" . $file;
        $path_parts = pathinfo($realdir);
        if (empty($path_parts['extension']))
            $realdir .= $this->_default_ext;*/
       
        // Read the template file and loading debug mode if enabled.
        ob_start();
        include($dir .$file); echo $this->_debug();
        $content_file = ob_get_contents();
        ob_end_clean();

        // Return the template content.
        return $content_file;
    }
    
    /**
     * Generate a based-copyright
     * @param string $is_cached | Show a specific tag of caching
     * @return string
     */
    private function _generateCopyright($is_cached = false)
    {
        if (!$this->_show_copyright)
            return;
        
        $content  = self::EOL;
        $content .= '<!-- PHPLayouts ' . self::VERSION . ' by rodix53 ;';
        
        if ($is_cached)
        {
            $content .= ' page stored from cache on ' . date("F j, Y, H:i a");
            $content .= self::EOL;
        }
        
        $content .= ' loaded in ' . (int)((microtime(true) - $this->_generation_time) * 1000) . ' ms';
        $content .= ' -->';
        
        return $content;
    }
    
    /**
     * Show a debug template
     */ 
    private function _debug()
    {
        if (!Template::$_debugging)
            return;
        
        $this->addTemplateDir(dirname(__FILE__));
        $content  = self::EOL . "<hr />" . self::EOL;
        $content .= $this->render('phpinfo.phtml');
        $content .= $this->_generateCopyright(false);
        return $content;
    }
    
}
Return current item: PHPLayouts