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.
		
		
		
		
			
				
					243 lines
				
				6.7 KiB
			
		
		
			
		
	
	
					243 lines
				
				6.7 KiB
			| 
								 
											7 years ago
										 
									 | 
							
								<?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 '';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |