* @author Kornel Lesiński * @author Iván Montes * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License * @version SVN: $Id$ * @link http://phptal.org/ */ /** * Keeps track of variable contents when using grouping in a path (first/ and last/) * * @package PHPTAL * @subpackage Php */ class PHPTAL_RepeatControllerGroups { protected $dict = array(); protected $cache = array(); protected $data = null; protected $vars = array(); protected $branch; public function __construct() { $this->dict = array(); $this->reset(); } /** * Resets the result caches. Use it to signal an iteration in the loop * */ public function reset() { $this->cache = array(); } /** * Checks if the data passed is the first one in a group * * @param mixed $data The data to evaluate * * @return Mixed True if the first item in the group, false if not and * this same object if the path is not finished */ public function first($data) { if ( !is_array($data) && !is_object($data) && !is_null($data) ) { if ( !isset($this->cache['F']) ) { $hash = md5($data); if ( !isset($this->dict['F']) || $this->dict['F'] !== $hash ) { $this->dict['F'] = $hash; $res = true; } else { $res = false; } $this->cache['F'] = $res; } return $this->cache['F']; } $this->data = $data; $this->branch = 'F'; $this->vars = array(); return $this; } /** * Checks if the data passed is the last one in a group * * @param mixed $data The data to evaluate * * @return Mixed True if the last item in the group, false if not and * this same object if the path is not finished */ public function last($data) { if ( !is_array($data) && !is_object($data) && !is_null($data) ) { if ( !isset($this->cache['L']) ) { $hash = md5($data); if (empty($this->dict['L'])) { $this->dict['L'] = $hash; $res = false; } elseif ($this->dict['L'] !== $hash) { $this->dict['L'] = $hash; $res = true; } else { $res = false; } $this->cache['L'] = $res; } return $this->cache['L']; } $this->data = $data; $this->branch = 'L'; $this->vars = array(); return $this; } /** * Handles variable accesses for the tal path resolver * * @param string $var The variable name to check * * @return Mixed An object/array if the path is not over or a boolean * * @todo replace the PHPTAL_Context::path() with custom code */ public function __get($var) { // When the iterator item is empty we just let the tal // expression consume by continuously returning this // same object which should evaluate to true for 'last' if ( is_null($this->data) ) { return $this; } // Find the requested variable $value = PHPTAL_Context::path($this->data, $var, true); // Check if it's an object or an array if ( is_array($value) || is_object($value) ) { // Move the context to the requested variable and return $this->data = $value; $this->addVarName($var); return $this; } // get a hash of the variable contents $hash = md5($value); // compute a path for the variable to use as dictionary key $path = $this->branch . $this->getVarPath() . $var; // If we don't know about this var store in the dictionary if ( !isset($this->cache[$path]) ) { if ( !isset($this->dict[$path]) ) { $this->dict[$path] = $hash; $res = $this->branch === 'F'; } else { // Check if the value has changed if ($this->dict[$path] !== $hash) { $this->dict[$path] = $hash; $res = true; } else { $res = false; } } $this->cache[$path] = $res; } return $this->cache[$path]; } /** * Adds a variable name to the current path of variables * * @param string $varname The variable name to store as a path part * @access protected */ protected function addVarName($varname) { $this->vars[] = $varname; } /** * Returns the current variable path separated by a slash * * @return String The current variable path * @access protected */ protected function getVarPath() { return implode('/', $this->vars) . '/'; } }