mirror of
				https://github.com/Mibew/handlebars.php.git
				synced 2025-11-04 12:05:09 +03:00 
			
		
		
		
	Merge remote-tracking branch 'origin/develop'
This commit is contained in:
		
						commit
						86ebab9dba
					
				
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -4,4 +4,7 @@ vendor
 | 
			
		||||
composer.phar
 | 
			
		||||
composer.lock
 | 
			
		||||
*.iml
 | 
			
		||||
.idea
 | 
			
		||||
.idea
 | 
			
		||||
GPATH
 | 
			
		||||
GRTAGS
 | 
			
		||||
GTAGS
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										89
									
								
								src/Handlebars/ChildContext.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/Handlebars/ChildContext.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
			
		||||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * This file is part of Handlebars-php
 | 
			
		||||
 * Base on mustache-php https://github.com/bobthecow/mustache.php
 | 
			
		||||
 *
 | 
			
		||||
 * PHP version 5.3
 | 
			
		||||
 *
 | 
			
		||||
 * @category  Xamin
 | 
			
		||||
 * @package   Handlebars
 | 
			
		||||
 * @author    fzerorubigd <fzerorubigd@gmail.com>
 | 
			
		||||
 * @author    Behrooz Shabani <everplays@gmail.com>
 | 
			
		||||
 * @author    Chris Gray <chris.w.gray@gmail.com>
 | 
			
		||||
 * @author    Ulrik Lystbaek <ulrik@bettertaste.dk>
 | 
			
		||||
 * @author    Dmitriy Simushev <simushevds@gmail.com>
 | 
			
		||||
 * @author    Christian Blanquera <cblanquera@openovate.com>
 | 
			
		||||
 * @copyright 2010-2012 (c) Justin Hileman
 | 
			
		||||
 * @copyright 2012 (c) ParsPooyesh Co
 | 
			
		||||
 * @copyright 2013 (c) Behrooz Shabani
 | 
			
		||||
 * @copyright 2013 (c) f0ruD A
 | 
			
		||||
 * @license   MIT <http://opensource.org/licenses/MIT>
 | 
			
		||||
 * @version   GIT: $Id$
 | 
			
		||||
 * @link      http://xamin.ir
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Handlebars;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handlebars context
 | 
			
		||||
 * Context for a template
 | 
			
		||||
 *
 | 
			
		||||
 * @category  Xamin
 | 
			
		||||
 * @package   Handlebars
 | 
			
		||||
 * @author    fzerorubigd <fzerorubigd@gmail.com>
 | 
			
		||||
 * @author    Behrooz Shabani <everplays@gmail.com>
 | 
			
		||||
 * @copyright 2010-2012 (c) Justin Hileman
 | 
			
		||||
 * @copyright 2012 (c) ParsPooyesh Co
 | 
			
		||||
 * @license   MIT <http://opensource.org/licenses/MIT>
 | 
			
		||||
 * @version   Release: @package_version@
 | 
			
		||||
 * @link      http://xamin.ir
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
class ChildContext extends Context
 | 
			
		||||
{
 | 
			
		||||
    protected $parentContext = null;
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets a parent context in which
 | 
			
		||||
     * we will case for the ../ in get()
 | 
			
		||||
     *
 | 
			
		||||
     * @param Context $parent parent context
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setParent(Context $parent) 
 | 
			
		||||
    {
 | 
			
		||||
        $this->parentContext = $parent;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Get a available from current context
 | 
			
		||||
     * Supported types :
 | 
			
		||||
     * variable , ../variable , variable.variable , variable.[variable] , .
 | 
			
		||||
     *
 | 
			
		||||
     * @param string  $variableName variable name to get from current context
 | 
			
		||||
     * @param boolean $strict       strict search? if not found then throw exception
 | 
			
		||||
     *
 | 
			
		||||
     * @throws \InvalidArgumentException in strict mode and variable not found
 | 
			
		||||
     * @throws \RuntimeException if supplied argument is a malformed quoted string 
 | 
			
		||||
     * @throws \InvalidArgumentException if variable name is invalid
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
    public function get($variableName, $strict = false)
 | 
			
		||||
    {
 | 
			
		||||
        //if the variable name starts with a ../
 | 
			
		||||
        //and we have a parent
 | 
			
		||||
        if (strpos($variableName, '../') === 0 
 | 
			
		||||
            && $this->parentContext instanceof Context
 | 
			
		||||
        ) {
 | 
			
		||||
            //just remove the first ../
 | 
			
		||||
            $variableName = substr($variableName, 3);
 | 
			
		||||
            
 | 
			
		||||
            //and let the parent context handle the rest
 | 
			
		||||
            return $this->parentContext->get($variableName, $strict);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        //otherwise, it's business as usual
 | 
			
		||||
        return parent::get($variableName, $strict);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -40,7 +40,6 @@ namespace Handlebars;
 | 
			
		||||
 | 
			
		||||
class Context
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * List of charcters that cannot be used in identifiers.
 | 
			
		||||
     */
 | 
			
		||||
@ -53,22 +52,30 @@ class Context
 | 
			
		||||
    const NOT_VALID_SEGMENT_NAME_CHARS = "]";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Context stack
 | 
			
		||||
     *
 | 
			
		||||
     * @var array stack for context only top stack is available
 | 
			
		||||
     */
 | 
			
		||||
    protected $stack = array();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Section stack index
 | 
			
		||||
     *
 | 
			
		||||
     * @var array index stack for sections
 | 
			
		||||
     */
 | 
			
		||||
    protected $index = array();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Object stack keys
 | 
			
		||||
     *
 | 
			
		||||
     * @var array key stack for objects
 | 
			
		||||
     */
 | 
			
		||||
    protected $key = array();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var array Special variables stack for sections. Each stack element can
 | 
			
		||||
     * Special variables stack for sections. 
 | 
			
		||||
     *
 | 
			
		||||
     * @var array Each stack element can
 | 
			
		||||
     * contain elements with "@index", "@key", "@first" and "@last" keys.
 | 
			
		||||
     */
 | 
			
		||||
    protected $specialVariables = array();
 | 
			
		||||
@ -309,8 +316,18 @@ class Context
 | 
			
		||||
        $bad_chars = preg_quote(self::NOT_VALID_NAME_CHARS, '/');
 | 
			
		||||
        $bad_seg_chars = preg_quote(self::NOT_VALID_SEGMENT_NAME_CHARS, '/');
 | 
			
		||||
 | 
			
		||||
        $name_pattern = "(?:[^" . $bad_chars . "\s]+)|(?:\[[^" . $bad_seg_chars . "]+\])";
 | 
			
		||||
        $check_pattern = "/^((" . $name_pattern . ")\.)*(" . $name_pattern  . ")\.?$/";
 | 
			
		||||
        $name_pattern = "(?:[^" 
 | 
			
		||||
            . $bad_chars 
 | 
			
		||||
            . "\s]+)|(?:\[[^" 
 | 
			
		||||
            . $bad_seg_chars 
 | 
			
		||||
            . "]+\])";
 | 
			
		||||
        
 | 
			
		||||
        $check_pattern = "/^((" 
 | 
			
		||||
            . $name_pattern 
 | 
			
		||||
            . ")\.)*(" 
 | 
			
		||||
            . $name_pattern  
 | 
			
		||||
            . ")\.?$/";
 | 
			
		||||
        
 | 
			
		||||
        $get_pattern = "/(?:" . $name_pattern . ")/";
 | 
			
		||||
 | 
			
		||||
        if (!preg_match($check_pattern, $variableName)) {
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,7 @@ class Handlebars
 | 
			
		||||
    const VERSION = '1.1.0';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * factory method
 | 
			
		||||
     * Factory method
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $options see __construct's options parameter
 | 
			
		||||
     *
 | 
			
		||||
@ -57,31 +57,43 @@ class Handlebars
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Current tokenizer instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var Tokenizer
 | 
			
		||||
     */
 | 
			
		||||
    private $_tokenizer;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Current parser instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var Parser
 | 
			
		||||
     */
 | 
			
		||||
    private $_parser;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Current helper list
 | 
			
		||||
     *
 | 
			
		||||
     * @var Helpers
 | 
			
		||||
     */
 | 
			
		||||
    private $_helpers;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Current loader instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var Loader
 | 
			
		||||
     */
 | 
			
		||||
    private $_loader;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Current partial loader instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var Loader
 | 
			
		||||
     */
 | 
			
		||||
    private $_partialsLoader;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Current cache instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var Cache
 | 
			
		||||
     */
 | 
			
		||||
    private $_cache;
 | 
			
		||||
@ -104,6 +116,8 @@ class Handlebars
 | 
			
		||||
    private $_escape = 'htmlspecialchars';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Parameters for the escpae method above
 | 
			
		||||
     *
 | 
			
		||||
     * @var array parametes to pass to escape function
 | 
			
		||||
     */
 | 
			
		||||
    private $_escapeArgs = array(
 | 
			
		||||
@ -188,8 +202,8 @@ class Handlebars
 | 
			
		||||
     * @param mixed  $data     data to use as context
 | 
			
		||||
     *
 | 
			
		||||
     * @return string Rendered template
 | 
			
		||||
     * @see Handlebars::loadTemplate
 | 
			
		||||
     * @see Template::render
 | 
			
		||||
     * @see    Handlebars::loadTemplate
 | 
			
		||||
     * @see    Template::render
 | 
			
		||||
     */
 | 
			
		||||
    public function render($template, $data)
 | 
			
		||||
    {
 | 
			
		||||
@ -258,6 +272,110 @@ class Handlebars
 | 
			
		||||
    {
 | 
			
		||||
        return $this->getHelpers()->has($name);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
     /**
 | 
			
		||||
     * Add a new helper.
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $name   helper name
 | 
			
		||||
     * @param mixed  $helper helper callable
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function registerHelper($name, $helper)
 | 
			
		||||
    {    
 | 
			
		||||
        $callback = function ($template, $context, $arg) use ($helper) {
 | 
			
		||||
            $args = $template->parseArguments($arg);
 | 
			
		||||
            $named = $template->parseNamedArguments($arg);
 | 
			
		||||
            
 | 
			
		||||
            foreach ($args as $i => $arg) {
 | 
			
		||||
                //if it's literally string
 | 
			
		||||
                if ($arg instanceof BaseString) {
 | 
			
		||||
                    //we have no problems here
 | 
			
		||||
                    $args[$i] = (string) $arg;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                //not sure what to do if it's not a string or StringWrapper
 | 
			
		||||
                if (!is_string($arg)) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                //it's a variable and we need to figure out the value of it
 | 
			
		||||
                $args[$i] = $context->get($arg);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            //push the options    
 | 
			
		||||
            $args[] = array(
 | 
			
		||||
                //special fields
 | 
			
		||||
                'data' => array(
 | 
			
		||||
                    'index' => $context->get('@index'),
 | 
			
		||||
                    'key' => $context->get('@key'),
 | 
			
		||||
                    'first' => $context->get('@first'),
 | 
			
		||||
                    'last' => $context->get('@last')),
 | 
			
		||||
                // Named arguments
 | 
			
		||||
                'hash' => $named,
 | 
			
		||||
                // A renderer for block helper
 | 
			
		||||
                'fn' => function ($inContext = null) use ($context, $template) {
 | 
			
		||||
                    $defined = !!$inContext;
 | 
			
		||||
                    
 | 
			
		||||
                    if (!$defined) {
 | 
			
		||||
                        $inContext = $context;
 | 
			
		||||
                        $inContext->push($inContext->last());
 | 
			
		||||
                    } else if (!$inContext instanceof Context) {
 | 
			
		||||
                        $inContext = new ChildContext($inContext);
 | 
			
		||||
                        $inContext->setParent($context);
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    $template->setStopToken('else');
 | 
			
		||||
                    $buffer = $template->render($inContext);
 | 
			
		||||
                    $template->setStopToken(false);
 | 
			
		||||
                    //what if it's a loop ?
 | 
			
		||||
                    $template->rewind();
 | 
			
		||||
                    //What's the point of this again?
 | 
			
		||||
                    //I mean in this context (literally)
 | 
			
		||||
                    //$template->discard($inContext);
 | 
			
		||||
                    
 | 
			
		||||
                    if ($defined) {
 | 
			
		||||
                        $inContext->pop();
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    return $buffer;
 | 
			
		||||
                },
 | 
			
		||||
                
 | 
			
		||||
                // A render for the else block
 | 
			
		||||
                'inverse' => function ($inContext = null) use ($context, $template) {
 | 
			
		||||
                    $defined = !!$inContext;
 | 
			
		||||
                    
 | 
			
		||||
                    if (!$defined) {
 | 
			
		||||
                        $inContext = $context;
 | 
			
		||||
                        $inContext->push($inContext->last());
 | 
			
		||||
                    } else if (!$inContext instanceof Context) {
 | 
			
		||||
                        $inContext = new ChildContext($inContext);
 | 
			
		||||
                        $inContext->setParent($context);
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    $template->setStopToken('else');
 | 
			
		||||
                    $template->discard($inContext);
 | 
			
		||||
                    $template->setStopToken(false);
 | 
			
		||||
                    $buffer = $template->render($inContext);
 | 
			
		||||
                    
 | 
			
		||||
                    if ($defined) {
 | 
			
		||||
                        $inContext->pop();
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    return $buffer;
 | 
			
		||||
                },
 | 
			
		||||
                
 | 
			
		||||
                // The current context.
 | 
			
		||||
                'context' => $context,
 | 
			
		||||
                // The current template
 | 
			
		||||
                'template' => $template);
 | 
			
		||||
            
 | 
			
		||||
            return call_user_func_array($helper, $args);
 | 
			
		||||
        };
 | 
			
		||||
    
 | 
			
		||||
        $this->addHelper($name, $callback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Remove a helper by name.
 | 
			
		||||
@ -284,7 +402,7 @@ class Handlebars
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get current loader
 | 
			
		||||
     * Get current loader
 | 
			
		||||
     *
 | 
			
		||||
     * @return Loader
 | 
			
		||||
     */
 | 
			
		||||
@ -310,7 +428,7 @@ class Handlebars
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get current partials loader
 | 
			
		||||
     * Get current partials loader
 | 
			
		||||
     *
 | 
			
		||||
     * @return Loader
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -31,10 +31,10 @@ interface Helper
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the helper
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Handlebars\Template $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context  $context  The current context
 | 
			
		||||
     * @param array                $args     The arguments passed the the helper
 | 
			
		||||
     * @param string               $source   The source
 | 
			
		||||
     * @param \Handlebars\Template  $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context   $context  The current context
 | 
			
		||||
     * @param \Handlebars\Arguments $args     The arguments passed the the helper
 | 
			
		||||
     * @param string                $source   The source
 | 
			
		||||
     *
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -41,10 +41,10 @@ class BindAttrHelper implements Helper
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the helper
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Handlebars\Template $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context  $context  The current context
 | 
			
		||||
     * @param array                $args     The arguments passed the the helper
 | 
			
		||||
     * @param string               $source   The source
 | 
			
		||||
     * @param \Handlebars\Template  $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context   $context  The current context
 | 
			
		||||
     * @param \Handlebars\Arguments $args     The arguments passed the the helper
 | 
			
		||||
     * @param string                $source   The source
 | 
			
		||||
     *
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -43,16 +43,17 @@ class EachHelper implements Helper
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the helper
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Handlebars\Template $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context  $context  The current context
 | 
			
		||||
     * @param array                $args     The arguments passed the the helper
 | 
			
		||||
     * @param string               $source   The source
 | 
			
		||||
     * @param \Handlebars\Template  $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context   $context  The current context
 | 
			
		||||
     * @param \Handlebars\Arguments $args     The arguments passed the the helper
 | 
			
		||||
     * @param string                $source   The source
 | 
			
		||||
     *
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
    public function execute(Template $template, Context $context, $args, $source)
 | 
			
		||||
    {
 | 
			
		||||
        $tmp = $context->get($args);
 | 
			
		||||
        $positionalArgs = $args->getPositionalArguments();
 | 
			
		||||
        $tmp = $context->get($positionalArgs[0]);
 | 
			
		||||
        $buffer = '';
 | 
			
		||||
 | 
			
		||||
        if (!$tmp) {
 | 
			
		||||
 | 
			
		||||
@ -41,10 +41,10 @@ class IfHelper implements Helper
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the helper
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Handlebars\Template $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context  $context  The current context
 | 
			
		||||
     * @param array                $args     The arguments passed the the helper
 | 
			
		||||
     * @param string               $source   The source
 | 
			
		||||
     * @param \Handlebars\Template  $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context   $context  The current context
 | 
			
		||||
     * @param \Handlebars\Arguments $args     The arguments passed the the helper
 | 
			
		||||
     * @param string                $source   The source
 | 
			
		||||
     *
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -41,10 +41,10 @@ class UnlessHelper implements Helper
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the helper
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Handlebars\Template $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context  $context  The current context
 | 
			
		||||
     * @param array                $args     The arguments passed the the helper
 | 
			
		||||
     * @param string               $source   The source
 | 
			
		||||
     * @param \Handlebars\Template  $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context   $context  The current context
 | 
			
		||||
     * @param \Handlebars\Arguments $args     The arguments passed the the helper
 | 
			
		||||
     * @param string                $source   The source
 | 
			
		||||
     *
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -41,16 +41,17 @@ class WithHelper implements Helper
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the helper
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Handlebars\Template $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context  $context  The current context
 | 
			
		||||
     * @param array                $args     The arguments passed the the helper
 | 
			
		||||
     * @param string               $source   The source
 | 
			
		||||
     * @param \Handlebars\Template  $template The template instance
 | 
			
		||||
     * @param \Handlebars\Context   $context  The current context
 | 
			
		||||
     * @param \Handlebars\Arguments $args     The arguments passed the the helper
 | 
			
		||||
     * @param string                $source   The source
 | 
			
		||||
     *
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
    public function execute(Template $template, Context $context, $args, $source)
 | 
			
		||||
    {
 | 
			
		||||
        $context->with($args);
 | 
			
		||||
        $positionalArgs = $args->getPositionalArguments();
 | 
			
		||||
        $context->with($positionalArgs[0]);
 | 
			
		||||
        $buffer = $template->render($context);
 | 
			
		||||
        $context->pop();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ namespace Handlebars;
 | 
			
		||||
/**
 | 
			
		||||
 * Handlebars helpers
 | 
			
		||||
 *
 | 
			
		||||
 * a collection of helper function. normally a function like
 | 
			
		||||
 * A collection of helper function. normally a function like
 | 
			
		||||
 * function ($sender, $name, $arguments) $arguments is unscaped arguments and
 | 
			
		||||
 * is a string, not array
 | 
			
		||||
 *
 | 
			
		||||
@ -35,10 +35,11 @@ namespace Handlebars;
 | 
			
		||||
 * @version   Release: @package_version@
 | 
			
		||||
 * @link      http://xamin.ir
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
class Helpers
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Raw helper array
 | 
			
		||||
     *
 | 
			
		||||
     * @var array array of helpers
 | 
			
		||||
     */
 | 
			
		||||
    protected $helpers = array();
 | 
			
		||||
@ -147,13 +148,20 @@ class Helpers
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $parsedArgs = new Arguments($args);
 | 
			
		||||
        if ($this->helpers[$name] instanceof Helper) {
 | 
			
		||||
            return $this->helpers[$name]->execute(
 | 
			
		||||
                $template, $context, $args, $source
 | 
			
		||||
                $template, $context, $parsedArgs, $source
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return call_user_func($this->helpers[$name], $template, $context, $args, $source);
 | 
			
		||||
        return call_user_func(
 | 
			
		||||
            $this->helpers[$name], 
 | 
			
		||||
            $template, 
 | 
			
		||||
            $context, 
 | 
			
		||||
            $parsedArgs, 
 | 
			
		||||
            $source
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -196,7 +204,7 @@ class Helpers
 | 
			
		||||
     * @param string $name helper name
 | 
			
		||||
     *
 | 
			
		||||
     * @return boolean
 | 
			
		||||
     * @see Handlebras_Helpers::has
 | 
			
		||||
     * @see    Handlebras_Helpers::has
 | 
			
		||||
     */
 | 
			
		||||
    public function __isset($name)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -61,7 +61,6 @@ class Parser
 | 
			
		||||
     * @throws \LogicException when nesting errors or mismatched section tags
 | 
			
		||||
     * are encountered.
 | 
			
		||||
     * @return array Token parse tree
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    private function _buildTree(\ArrayIterator $tokens)
 | 
			
		||||
    {
 | 
			
		||||
@ -90,14 +89,20 @@ class Parser
 | 
			
		||||
                            && isset($result[Tokenizer::NAME])
 | 
			
		||||
                            && $result[Tokenizer::NAME] == $token[Tokenizer::NAME]
 | 
			
		||||
                        ) {
 | 
			
		||||
                            if (isset($result[Tokenizer::TRIM_RIGHT]) && $result[Tokenizer::TRIM_RIGHT]) {
 | 
			
		||||
                                // If the start node has trim right, then its equal with the first item in the loop with
 | 
			
		||||
                            if (isset($result[Tokenizer::TRIM_RIGHT]) 
 | 
			
		||||
                                && $result[Tokenizer::TRIM_RIGHT]
 | 
			
		||||
                            ) {
 | 
			
		||||
                                // If the start node has trim right, then its equal 
 | 
			
		||||
                                //with the first item in the loop with
 | 
			
		||||
                                // Trim left
 | 
			
		||||
                                $newNodes[0][Tokenizer::TRIM_LEFT] = true;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            if (isset($token[Tokenizer::TRIM_RIGHT]) && $token[Tokenizer::TRIM_RIGHT]) {
 | 
			
		||||
                                //OK, if we have trim right here, we should pass it to the upper level.
 | 
			
		||||
                            if (isset($token[Tokenizer::TRIM_RIGHT]) 
 | 
			
		||||
                                && $token[Tokenizer::TRIM_RIGHT]
 | 
			
		||||
                            ) {
 | 
			
		||||
                                //OK, if we have trim right here, we should 
 | 
			
		||||
                                //pass it to the upper level.
 | 
			
		||||
                                $result[Tokenizer::TRIM_RIGHT] = true;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
@ -120,4 +125,4 @@ class Parser
 | 
			
		||||
        return $stack;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@ -43,6 +43,8 @@ use Handlebars\Arguments;
 | 
			
		||||
class Template
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Handlebars instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var Handlebars
 | 
			
		||||
     */
 | 
			
		||||
    protected $handlebars;
 | 
			
		||||
@ -58,6 +60,8 @@ class Template
 | 
			
		||||
    protected $source = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Run stack
 | 
			
		||||
     *
 | 
			
		||||
     * @var array Run stack
 | 
			
		||||
     */
 | 
			
		||||
    private $_stack = array();
 | 
			
		||||
@ -108,13 +112,12 @@ class Template
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set stop token for render and discard method
 | 
			
		||||
     * Set stop token for render and discard method
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $token token to set as stop token or false to remove
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    public function setStopToken($token)
 | 
			
		||||
    {
 | 
			
		||||
        $topStack = array_pop($this->_stack);
 | 
			
		||||
@ -123,11 +126,10 @@ class Template
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get current stop token
 | 
			
		||||
     * Get current stop token
 | 
			
		||||
     *
 | 
			
		||||
     * @return string|bool
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    public function getStopToken()
 | 
			
		||||
    {
 | 
			
		||||
        $topStack = end($this->_stack);
 | 
			
		||||
@ -175,26 +177,35 @@ class Template
 | 
			
		||||
            ) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if (isset($current[Tokenizer::TRIM_LEFT]) && $current[Tokenizer::TRIM_LEFT]) {
 | 
			
		||||
            if (isset($current[Tokenizer::TRIM_LEFT]) 
 | 
			
		||||
                && $current[Tokenizer::TRIM_LEFT]
 | 
			
		||||
            ) {
 | 
			
		||||
                $buffer = rtrim($buffer);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $tmp = $this->_renderInternal($current, $context);
 | 
			
		||||
 | 
			
		||||
            if (isset($current[Tokenizer::TRIM_LEFT]) && $current[Tokenizer::TRIM_LEFT]) {
 | 
			
		||||
            if (isset($current[Tokenizer::TRIM_LEFT]) 
 | 
			
		||||
                && $current[Tokenizer::TRIM_LEFT]
 | 
			
		||||
            ) {
 | 
			
		||||
                $tmp = rtrim($tmp);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($rTrim  || (isset($current[Tokenizer::TRIM_RIGHT]) && $current[Tokenizer::TRIM_RIGHT])) {
 | 
			
		||||
            if ($rTrim  
 | 
			
		||||
                || (isset($current[Tokenizer::TRIM_RIGHT]) 
 | 
			
		||||
                && $current[Tokenizer::TRIM_RIGHT])
 | 
			
		||||
            ) {
 | 
			
		||||
                $tmp = ltrim($tmp);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $buffer .= $tmp;
 | 
			
		||||
            // Some time, there is more than one string token (first is empty),
 | 
			
		||||
            // Some time, there is more than 
 | 
			
		||||
            //one string token (first is empty),
 | 
			
		||||
            //so we need to trim all of them in one shot
 | 
			
		||||
 | 
			
		||||
            $rTrim = (empty($tmp) && $rTrim) ||
 | 
			
		||||
                isset($current[Tokenizer::TRIM_RIGHT]) && $current[Tokenizer::TRIM_RIGHT];
 | 
			
		||||
                isset($current[Tokenizer::TRIM_RIGHT]) 
 | 
			
		||||
                && $current[Tokenizer::TRIM_RIGHT];
 | 
			
		||||
        }
 | 
			
		||||
        if ($stop) {
 | 
			
		||||
            //Ok break here, the helper should be aware of this.
 | 
			
		||||
@ -331,7 +342,9 @@ class Template
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // subexpression parsing loop
 | 
			
		||||
        $subexprs = array(); // will contain all subexpressions inside outermost brackets
 | 
			
		||||
        // will contain all subexpressions 
 | 
			
		||||
        // inside outermost brackets
 | 
			
		||||
        $subexprs = array();
 | 
			
		||||
        $insideOf = array( 'single' => false, 'double' => false );
 | 
			
		||||
        $lvl = 0;
 | 
			
		||||
        $cur_start = 0;
 | 
			
		||||
@ -353,7 +366,11 @@ class Template
 | 
			
		||||
            if ($cur == ')' && ! $insideOf['single'] && ! $insideOf['double']) {
 | 
			
		||||
                $lvl--;
 | 
			
		||||
                if ($lvl == 0) {
 | 
			
		||||
                    $subexprs[] = substr($current[Tokenizer::ARGS], $cur_start, $i - $cur_start);
 | 
			
		||||
                    $subexprs[] = substr(
 | 
			
		||||
                        $current[Tokenizer::ARGS], 
 | 
			
		||||
                        $cur_start, 
 | 
			
		||||
                        $i - $cur_start
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
@ -372,14 +389,30 @@ class Template
 | 
			
		||||
                    Tokenizer::INDEX => $current[Tokenizer::INDEX],
 | 
			
		||||
                    Tokenizer::ARGS => implode(" ", array_slice($cmd, 1))
 | 
			
		||||
                );
 | 
			
		||||
                
 | 
			
		||||
                // resolve the node recursively
 | 
			
		||||
                $resolved = addcslashes($this->_handlebarsStyleSection($context, $section_node), '"');
 | 
			
		||||
                $resolved = $this->_handlebarsStyleSection(
 | 
			
		||||
                    $context, 
 | 
			
		||||
                    $section_node
 | 
			
		||||
                );
 | 
			
		||||
                
 | 
			
		||||
                $resolved = addcslashes($resolved, '"');
 | 
			
		||||
                // replace original subexpression with result
 | 
			
		||||
                $current[Tokenizer::ARGS] = str_replace('('.$expr.')', '"' . $resolved . '"', $current[Tokenizer::ARGS]);
 | 
			
		||||
                $current[Tokenizer::ARGS] = str_replace(
 | 
			
		||||
                    '('.$expr.')', 
 | 
			
		||||
                    '"' . $resolved . '"', 
 | 
			
		||||
                    $current[Tokenizer::ARGS]
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $return = $helpers->call($sectionName, $this, $context, $current[Tokenizer::ARGS], $source);
 | 
			
		||||
        $return = $helpers->call(
 | 
			
		||||
            $sectionName, 
 | 
			
		||||
            $this, 
 | 
			
		||||
            $context, 
 | 
			
		||||
            $current[Tokenizer::ARGS], 
 | 
			
		||||
            $source
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if ($return instanceof StringWrapper) {
 | 
			
		||||
            return $this->handlebars->loadString($return)->render($context);
 | 
			
		||||
@ -564,9 +597,9 @@ class Template
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get replacing value of a tag
 | 
			
		||||
     * Get replacing value of a tag
 | 
			
		||||
     *
 | 
			
		||||
     * will process the tag as section, if a helper with the same name could be
 | 
			
		||||
     * Will process the tag as section, if a helper with the same name could be
 | 
			
		||||
     * found, so {{helper arg}} can be used instead of {{#helper arg}}.
 | 
			
		||||
     *
 | 
			
		||||
     * @param Context $context current context
 | 
			
		||||
 | 
			
		||||
@ -453,6 +453,201 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
 | 
			
		||||
        $this->setExpectedException('InvalidArgumentException');
 | 
			
		||||
        $engine->getHelpers()->call('invalid', $engine->loadTemplate(''), new \Handlebars\Context(), '', '');
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function testRegisterHelper()
 | 
			
		||||
    {
 | 
			
		||||
        $loader = new \Handlebars\Loader\StringLoader();
 | 
			
		||||
        $engine = new \Handlebars\Handlebars(array('loader' => $loader));
 | 
			
		||||
        //date_default_timezone_set('GMT');
 | 
			
		||||
        
 | 
			
		||||
        //FIRST UP: some awesome helpers!!
 | 
			
		||||
        
 | 
			
		||||
        //translations
 | 
			
		||||
        $translations = array(
 | 
			
		||||
            'hello' => 'bonjour',
 | 
			
		||||
            'my name is %s' => 'mon nom est %s',
 | 
			
		||||
            'how are your %s kids and %s' => 'comment sont les enfants de votre %s et %s'
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        //i18n
 | 
			
		||||
        $engine->registerHelper('_', function($key) use ($translations) {
 | 
			
		||||
            $args = func_get_args();
 | 
			
		||||
            $key = array_shift($args);
 | 
			
		||||
            $options = array_pop($args);
 | 
			
		||||
            
 | 
			
		||||
            //make sure it's a string
 | 
			
		||||
            $key = (string) $key;
 | 
			
		||||
            
 | 
			
		||||
            //by default the translation is the key
 | 
			
		||||
            $translation = $key;
 | 
			
		||||
            
 | 
			
		||||
            //if there is a translation
 | 
			
		||||
            if(isset($translations[$key])) {
 | 
			
		||||
                //translate it
 | 
			
		||||
                $translation = $translations[$key];
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            //if there are more arguments
 | 
			
		||||
            if(!empty($args)) {
 | 
			
		||||
                //it means the translations was 
 | 
			
		||||
                //something like 'Hello %s'
 | 
			
		||||
                return vsprintf($translation, $args);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            //just return what we got
 | 
			
		||||
            return $translation;
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        //create a better if helper
 | 
			
		||||
        $engine->registerHelper('when', function($value1, $operator, $value2, $options) {
 | 
			
		||||
            $valid = false;
 | 
			
		||||
            //the amazing reverse switch!
 | 
			
		||||
            switch (true) {
 | 
			
		||||
                case $operator == 'eq' && $value1 == $value2:
 | 
			
		||||
                case $operator == '==' && $value1 == $value2:
 | 
			
		||||
                case $operator == 'req' && $value1 === $value2:
 | 
			
		||||
                case $operator == '===' && $value1 === $value2:
 | 
			
		||||
                case $operator == 'neq' && $value1 != $value2:
 | 
			
		||||
                case $operator == '!=' && $value1 != $value2:
 | 
			
		||||
                case $operator == 'rneq' && $value1 !== $value2:
 | 
			
		||||
                case $operator == '!==' && $value1 !== $value2:
 | 
			
		||||
                case $operator == 'lt' && $value1 < $value2:
 | 
			
		||||
                case $operator == '<' && $value1 < $value2:
 | 
			
		||||
                case $operator == 'lte' && $value1 <= $value2:
 | 
			
		||||
                case $operator == '<=' && $value1 <= $value2:
 | 
			
		||||
                case $operator == 'gt' && $value1 > $value2:
 | 
			
		||||
                case $operator == '>' && $value1 > $value2:
 | 
			
		||||
                case $operator == 'gte' && $value1 >= $value2:
 | 
			
		||||
                case $operator == '>=' && $value1 >= $value2:
 | 
			
		||||
                case $operator == 'and' && $value1 && $value2: 
 | 
			
		||||
                case $operator == '&&' && ($value1 && $value2):
 | 
			
		||||
                case $operator == 'or' && ($value1 || $value2):
 | 
			
		||||
                case $operator == '||' && ($value1 || $value2):
 | 
			
		||||
                    $valid = true;
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            if($valid) {
 | 
			
		||||
                return $options['fn']();
 | 
			
		||||
            }
 | 
			
		||||
        
 | 
			
		||||
            return $options['inverse']();
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        //a loop helper
 | 
			
		||||
        $engine->registerHelper('loop', function($object, $options) {
 | 
			
		||||
            //expected for subtemplates of this block to use
 | 
			
		||||
            //  {{value.profile_name}} vs {{profile_name}}
 | 
			
		||||
            //  {{key}} vs {{@index}}
 | 
			
		||||
            
 | 
			
		||||
            $i = 0;
 | 
			
		||||
            $buffer = array();
 | 
			
		||||
            $total = count($object);
 | 
			
		||||
            
 | 
			
		||||
            //loop through the object
 | 
			
		||||
            foreach($object as $key => $value) {
 | 
			
		||||
                //call the sub template and 
 | 
			
		||||
                //add it to the buffer
 | 
			
		||||
                $buffer[] = $options['fn'](array(
 | 
			
		||||
                    'key'    => $key,
 | 
			
		||||
                    'value'    => $value,
 | 
			
		||||
                    'last'    => ++$i === $total
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            return implode('', $buffer);
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        //array in
 | 
			
		||||
        $engine->registerHelper('in', function(array $array, $key, $options) {
 | 
			
		||||
            if(in_array($key, $array)) {
 | 
			
		||||
                return $options['fn']();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $options['inverse']();
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        //converts date formats to other formats
 | 
			
		||||
        $engine->registerHelper('date', function($time, $format, $options) {
 | 
			
		||||
            return date($format, strtotime($time));
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        //nesting helpers, these don't really help anyone :)
 | 
			
		||||
        $engine->registerHelper('nested1', function($test1, $test2, $options) {
 | 
			
		||||
            return $options['fn'](array(
 | 
			
		||||
                'test4' => $test1,
 | 
			
		||||
                'test5' => 'This is Test 5'
 | 
			
		||||
            ));
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        $engine->registerHelper('nested2', function($options) {
 | 
			
		||||
            return $options['fn'](array('test6' => 'This is Test 6'));
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        //NEXT UP: some practical case studies
 | 
			
		||||
        
 | 
			
		||||
        //case 1 - i18n
 | 
			
		||||
        $variable1 = array();
 | 
			
		||||
        $template1 = "{{_ 'hello'}}, {{_ 'my name is %s' 'Foo'}}! {{_ 'how are your %s kids and %s' 6 'dog'}}?";
 | 
			
		||||
        $expected1 = 'bonjour, mon nom est Foo! comment sont les enfants de votre 6 et dog?';
 | 
			
		||||
        
 | 
			
		||||
        //case 2 - when
 | 
			
		||||
        $variable2 = array('gender' => 'female');
 | 
			
		||||
        $template2 = "Hello {{#when gender '===' 'male'}}sir{{else}}maam{{/when}}";
 | 
			
		||||
        $expected2 = 'Hello maam';
 | 
			
		||||
        
 | 
			
		||||
        //case 3 - when else
 | 
			
		||||
        $variable3 = array('gender' => 'male');
 | 
			
		||||
        $template3 = "Hello {{#when gender '===' 'male'}}sir{{else}}maam{{/when}}";
 | 
			
		||||
        $expected3 = 'Hello sir';
 | 
			
		||||
        
 | 
			
		||||
        //case 4 - loop
 | 
			
		||||
        $variable4 = array(
 | 
			
		||||
            'rows' => array(
 | 
			
		||||
                array(
 | 
			
		||||
                    'profile_name' => 'Jane Doe',
 | 
			
		||||
                    'profile_created' => '2014-04-04 00:00:00'
 | 
			
		||||
                ),
 | 
			
		||||
                array(
 | 
			
		||||
                    'profile_name' => 'John Doe',
 | 
			
		||||
                    'profile_created' => '2015-01-21 00:00:00'
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
        $template4 = "{{#loop rows}}<li>{{value.profile_name}} - {{date value.profile_created 'M d'}}</li>{{/loop}}";
 | 
			
		||||
        $expected4 = '<li>Jane Doe - Apr 04</li><li>John Doe - Jan 21</li>';
 | 
			
		||||
        
 | 
			
		||||
        //case 5 - array in
 | 
			
		||||
        $variable5 = $variable4;
 | 
			
		||||
        $variable5['me'] = 'Jack Doe';
 | 
			
		||||
        $variable5['admins'] = array('Jane Doe', 'John Doe');
 | 
			
		||||
        $template5 = "{{#in admins me}}<ul>".$template4."</ul>{{else}}No Access{{/in}}";
 | 
			
		||||
        $expected5 = 'No Access';
 | 
			
		||||
        
 | 
			
		||||
        //case 6 - array in else
 | 
			
		||||
        $variable6 = $variable5;
 | 
			
		||||
        $variable6['me'] = 'Jane Doe';
 | 
			
		||||
        $template6 = $template5;
 | 
			
		||||
        $expected6 = '<ul><li>Jane Doe - Apr 04</li><li>John Doe - Jan 21</li></ul>';
 | 
			
		||||
        
 | 
			
		||||
        //case 7 - nested templates and parent-grand variables
 | 
			
		||||
        $variable7 = array('test' => 'Hello World');
 | 
			
		||||
        $template7 = '{{#nested1 test "test2"}}  '
 | 
			
		||||
            .'In 1: {{test4}} {{#nested1 ../test \'test3\'}} '
 | 
			
		||||
            .'In 2: {{test5}}{{#nested2}}  '
 | 
			
		||||
            .'In 3: {{test6}}  {{../../../test}}{{/nested2}}{{/nested1}}{{/nested1}}';
 | 
			
		||||
        $expected7 = '  In 1: Hello World  In 2: This is Test 5  In 3: This is Test 6  Hello World';
 | 
			
		||||
        
 | 
			
		||||
        //LAST UP: the actual testing
 | 
			
		||||
        
 | 
			
		||||
        $this->assertEquals($expected1, $engine->render($template1, $variable1));
 | 
			
		||||
        $this->assertEquals($expected2, $engine->render($template2, $variable2));
 | 
			
		||||
        $this->assertEquals($expected3, $engine->render($template3, $variable3));
 | 
			
		||||
        $this->assertEquals($expected4, $engine->render($template4, $variable4));
 | 
			
		||||
        $this->assertEquals($expected5, $engine->render($template5, $variable5));
 | 
			
		||||
        $this->assertEquals($expected6, $engine->render($template6, $variable6));
 | 
			
		||||
        $this->assertEquals($expected7, $engine->render($template7, $variable7));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testInvalidHelper()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user