A super easy PHP Framework for web development!
				https://github.com/exacti/phacil-framework
			
			
		
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							242 lines
						
					
					
						
							6.7 KiB
						
					
					
				
			
		
		
	
	
							242 lines
						
					
					
						
							6.7 KiB
						
					
					
				<?php
 | 
						|
 | 
						|
/*
 | 
						|
 * This file is part of Mustache.php.
 | 
						|
 *
 | 
						|
 * (c) 2010-2017 Justin Hileman
 | 
						|
 *
 | 
						|
 * For the full copyright and license information, please view the LICENSE
 | 
						|
 * file that was distributed with this source code.
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * Mustache Template rendering Context.
 | 
						|
 */
 | 
						|
class Mustache_Context
 | 
						|
{
 | 
						|
    private $stack      = array();
 | 
						|
    private $blockStack = array();
 | 
						|
 | 
						|
    /**
 | 
						|
     * Mustache rendering Context constructor.
 | 
						|
     *
 | 
						|
     * @param mixed $context Default rendering context (default: null)
 | 
						|
     */
 | 
						|
    public function __construct($context = null)
 | 
						|
    {
 | 
						|
        if ($context !== null) {
 | 
						|
            $this->stack = array($context);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Push a new Context frame onto the stack.
 | 
						|
     *
 | 
						|
     * @param mixed $value Object or array to use for context
 | 
						|
     */
 | 
						|
    public function push($value)
 | 
						|
    {
 | 
						|
        array_push($this->stack, $value);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Push a new Context frame onto the block context stack.
 | 
						|
     *
 | 
						|
     * @param mixed $value Object or array to use for block context
 | 
						|
     */
 | 
						|
    public function pushBlockContext($value)
 | 
						|
    {
 | 
						|
        array_push($this->blockStack, $value);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Pop the last Context frame from the stack.
 | 
						|
     *
 | 
						|
     * @return mixed Last Context frame (object or array)
 | 
						|
     */
 | 
						|
    public function pop()
 | 
						|
    {
 | 
						|
        return array_pop($this->stack);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Pop the last block Context frame from the stack.
 | 
						|
     *
 | 
						|
     * @return mixed Last block Context frame (object or array)
 | 
						|
     */
 | 
						|
    public function popBlockContext()
 | 
						|
    {
 | 
						|
        return array_pop($this->blockStack);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the last Context frame.
 | 
						|
     *
 | 
						|
     * @return mixed Last Context frame (object or array)
 | 
						|
     */
 | 
						|
    public function last()
 | 
						|
    {
 | 
						|
        return end($this->stack);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Find a variable in the Context stack.
 | 
						|
     *
 | 
						|
     * Starting with the last Context frame (the context of the innermost section), and working back to the top-level
 | 
						|
     * rendering context, look for a variable with the given name:
 | 
						|
     *
 | 
						|
     *  * If the Context frame is an associative array which contains the key $id, returns the value of that element.
 | 
						|
     *  * If the Context frame is an object, this will check first for a public method, then a public property named
 | 
						|
     *    $id. Failing both of these, it will try `__isset` and `__get` magic methods.
 | 
						|
     *  * If a value named $id is not found in any Context frame, returns an empty string.
 | 
						|
     *
 | 
						|
     * @param string $id Variable name
 | 
						|
     *
 | 
						|
     * @return mixed Variable value, or '' if not found
 | 
						|
     */
 | 
						|
    public function find($id)
 | 
						|
    {
 | 
						|
        return $this->findVariableInStack($id, $this->stack);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Find a 'dot notation' variable in the Context stack.
 | 
						|
     *
 | 
						|
     * Note that dot notation traversal bubbles through scope differently than the regular find method. After finding
 | 
						|
     * the initial chunk of the dotted name, each subsequent chunk is searched for only within the value of the previous
 | 
						|
     * result. For example, given the following context stack:
 | 
						|
     *
 | 
						|
     *     $data = array(
 | 
						|
     *         'name' => 'Fred',
 | 
						|
     *         'child' => array(
 | 
						|
     *             'name' => 'Bob'
 | 
						|
     *         ),
 | 
						|
     *     );
 | 
						|
     *
 | 
						|
     * ... and the Mustache following template:
 | 
						|
     *
 | 
						|
     *     {{ child.name }}
 | 
						|
     *
 | 
						|
     * ... the `name` value is only searched for within the `child` value of the global Context, not within parent
 | 
						|
     * Context frames.
 | 
						|
     *
 | 
						|
     * @param string $id Dotted variable selector
 | 
						|
     *
 | 
						|
     * @return mixed Variable value, or '' if not found
 | 
						|
     */
 | 
						|
    public function findDot($id)
 | 
						|
    {
 | 
						|
        $chunks = explode('.', $id);
 | 
						|
        $first  = array_shift($chunks);
 | 
						|
        $value  = $this->findVariableInStack($first, $this->stack);
 | 
						|
 | 
						|
        foreach ($chunks as $chunk) {
 | 
						|
            if ($value === '') {
 | 
						|
                return $value;
 | 
						|
            }
 | 
						|
 | 
						|
            $value = $this->findVariableInStack($chunk, array($value));
 | 
						|
        }
 | 
						|
 | 
						|
        return $value;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Find an 'anchored dot notation' variable in the Context stack.
 | 
						|
     *
 | 
						|
     * This is the same as findDot(), except it looks in the top of the context
 | 
						|
     * stack for the first value, rather than searching the whole context stack
 | 
						|
     * and starting from there.
 | 
						|
     *
 | 
						|
     * @see Mustache_Context::findDot
 | 
						|
     *
 | 
						|
     * @throws Mustache_Exception_InvalidArgumentException if given an invalid anchored dot $id
 | 
						|
     *
 | 
						|
     * @param string $id Dotted variable selector
 | 
						|
     *
 | 
						|
     * @return mixed Variable value, or '' if not found
 | 
						|
     */
 | 
						|
    public function findAnchoredDot($id)
 | 
						|
    {
 | 
						|
        $chunks = explode('.', $id);
 | 
						|
        $first  = array_shift($chunks);
 | 
						|
        if ($first !== '') {
 | 
						|
            throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected id for findAnchoredDot: %s', $id));
 | 
						|
        }
 | 
						|
 | 
						|
        $value  = $this->last();
 | 
						|
 | 
						|
        foreach ($chunks as $chunk) {
 | 
						|
            if ($value === '') {
 | 
						|
                return $value;
 | 
						|
            }
 | 
						|
 | 
						|
            $value = $this->findVariableInStack($chunk, array($value));
 | 
						|
        }
 | 
						|
 | 
						|
        return $value;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Find an argument in the block context stack.
 | 
						|
     *
 | 
						|
     * @param string $id
 | 
						|
     *
 | 
						|
     * @return mixed Variable value, or '' if not found
 | 
						|
     */
 | 
						|
    public function findInBlock($id)
 | 
						|
    {
 | 
						|
        foreach ($this->blockStack as $context) {
 | 
						|
            if (array_key_exists($id, $context)) {
 | 
						|
                return $context[$id];
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return '';
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Helper function to find a variable in the Context stack.
 | 
						|
     *
 | 
						|
     * @see Mustache_Context::find
 | 
						|
     *
 | 
						|
     * @param string $id    Variable name
 | 
						|
     * @param array  $stack Context stack
 | 
						|
     *
 | 
						|
     * @return mixed Variable value, or '' if not found
 | 
						|
     */
 | 
						|
    private function findVariableInStack($id, array $stack)
 | 
						|
    {
 | 
						|
        for ($i = count($stack) - 1; $i >= 0; $i--) {
 | 
						|
            $frame = &$stack[$i];
 | 
						|
 | 
						|
            switch (gettype($frame)) {
 | 
						|
                case 'object':
 | 
						|
                    if (!($frame instanceof Closure)) {
 | 
						|
                        // Note that is_callable() *will not work here*
 | 
						|
                        // See https://github.com/bobthecow/mustache.php/wiki/Magic-Methods
 | 
						|
                        if (method_exists($frame, $id)) {
 | 
						|
                            return $frame->$id();
 | 
						|
                        }
 | 
						|
 | 
						|
                        if (isset($frame->$id)) {
 | 
						|
                            return $frame->$id;
 | 
						|
                        }
 | 
						|
 | 
						|
                        if ($frame instanceof ArrayAccess && isset($frame[$id])) {
 | 
						|
                            return $frame[$id];
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 'array':
 | 
						|
                    if (array_key_exists($id, $frame)) {
 | 
						|
                        return $frame[$id];
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return '';
 | 
						|
    }
 | 
						|
}
 | 
						|
 |