| 
<?php
 /**
 * Engine.php - Template engine
 *
 * Generate templates with template vars.
 *
 * @package jaxon-core
 * @author Thierry Feuzeu <[email protected]>
 * @copyright 2016 Thierry Feuzeu <[email protected]>
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
 * @link https://github.com/jaxon-php/jaxon-core
 */
 
 namespace Jaxon\Utils\Template;
 
 class Engine
 {
 /**
 * The namespaces
 *
 * @var array   $aNamespaces
 */
 protected $aNamespaces;
 
 /**
 * The constructor
 *
 * @param   string      $sTemplateDir       The template directory
 */
 public function __construct($sTemplateDir)
 {
 $sTemplateDir = rtrim(trim($sTemplateDir), '/\\');
 $this->aNamespaces = [
 'jaxon' => [
 'directory' => $sTemplateDir . DIRECTORY_SEPARATOR,
 'extension' => '.php',
 ],
 'pagination' => [
 'directory' => $sTemplateDir . DIRECTORY_SEPARATOR . 'pagination' . DIRECTORY_SEPARATOR,
 'extension' => '.php',
 ],
 ];
 }
 
 /**
 * Add a namespace to the template system
 *
 * @param string        $sNamespace         The namespace name
 * @param string        $sDirectory         The namespace directory
 * @param string        $sExtension         The extension to append to template names
 *
 * @return void
 */
 public function addNamespace($sNamespace, $sDirectory, $sExtension = '')
 {
 // The 'jaxon' key cannot be overriden
 if($sNamespace == 'jaxon' || $sNamespace == 'pagination')
 {
 return;
 }
 // Save the namespace
 $this->aNamespaces[$sNamespace] = [
 'directory' => rtrim(trim($sDirectory), "/\\") . DIRECTORY_SEPARATOR,
 'extension' => $sExtension,
 ];
 }
 
 /**
 * Set a new directory for pagination templates
 *
 * @param string        $sDirectory             The directory path
 *
 * @return void
 */
 public function pagination($sDirectory)
 {
 $this->aNamespaces['pagination']['directory'] = $sDirectory;
 }
 
 /**
 * Render a template
 *
 * @param string        $sPath                The path to the template
 * @param array         $aVars                The template vars
 *
 * @return string
 */
 private function _render($sPath, array $aVars)
 {
 // Make the template vars available, throught a Context object.
 $xContext = new Context($this);
 foreach($aVars as $sName => $xValue)
 {
 $sName = (string)$sName;
 $xContext->$sName = $xValue;
 }
 // Render the template
 $cRenderer = function($_sPath) {
 ob_start();
 include($_sPath);
 return ob_get_clean();
 };
 // Call the closure in the context of the $xContext object.
 // So the keyword '$this' in the template will refer to the $xContext object.
 return \call_user_func($cRenderer->bindTo($xContext), $sPath);
 }
 
 /**
 * Render a template
 *
 * @param string        $sTemplate            The name of template to be rendered
 * @param array         $aVars                The template vars
 *
 * @return string
 */
 public function render($sTemplate, array $aVars = [])
 {
 $sTemplate = trim($sTemplate);
 // Get the namespace name
 $sNamespace = '';
 $iSeparatorPosition = strrpos($sTemplate, '::');
 if($iSeparatorPosition !== false)
 {
 $sNamespace = substr($sTemplate, 0, $iSeparatorPosition);
 $sTemplate = substr($sTemplate, $iSeparatorPosition + 2);
 }
 // The default namespace is 'jaxon'
 if(!($sNamespace = trim($sNamespace)))
 {
 $sNamespace = 'jaxon';
 }
 // Check if the namespace is defined
 if(!key_exists($sNamespace, $this->aNamespaces))
 {
 return '';
 }
 $aNamespace = $this->aNamespaces[$sNamespace];
 // Get the template path
 $sTemplatePath = $aNamespace['directory'] . $sTemplate . $aNamespace['extension'];
 // Render the template
 return $this->_render($sTemplatePath, $aVars);
 }
 }
 
 |