1<?php 2/** 3 * PHPTAL templating engine 4 * 5 * PHP Version 5 6 * 7 * @category HTML 8 * @package PHPTAL 9 * @author Laurent Bedubourg <lbedubourg@motion-twin.com> 10 * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> 11 * @author Iván Montes <drslump@pollinimini.net> 12 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License 13 * @version SVN: $Id$ 14 * @link http://phptal.org/ 15 */ 16 17/** 18 * Keeps track of variable contents when using grouping in a path (first/ and last/) 19 * 20 * @package PHPTAL 21 * @subpackage Php 22 */ 23class PHPTAL_RepeatControllerGroups 24{ 25 protected $dict = array(); 26 protected $cache = array(); 27 protected $data = null; 28 protected $vars = array(); 29 protected $branch; 30 31 32 public function __construct() 33 { 34 $this->dict = array(); 35 $this->reset(); 36 } 37 38 /** 39 * Resets the result caches. Use it to signal an iteration in the loop 40 * 41 */ 42 public function reset() 43 { 44 $this->cache = array(); 45 } 46 47 /** 48 * Checks if the data passed is the first one in a group 49 * 50 * @param mixed $data The data to evaluate 51 * 52 * @return Mixed True if the first item in the group, false if not and 53 * this same object if the path is not finished 54 */ 55 public function first($data) 56 { 57 if ( !is_array($data) && !is_object($data) && !is_null($data) ) { 58 59 if ( !isset($this->cache['F']) ) { 60 61 $hash = md5($data); 62 63 if ( !isset($this->dict['F']) || $this->dict['F'] !== $hash ) { 64 $this->dict['F'] = $hash; 65 $res = true; 66 } else { 67 $res = false; 68 } 69 70 $this->cache['F'] = $res; 71 } 72 73 return $this->cache['F']; 74 } 75 76 $this->data = $data; 77 $this->branch = 'F'; 78 $this->vars = array(); 79 return $this; 80 } 81 82 /** 83 * Checks if the data passed is the last one in a group 84 * 85 * @param mixed $data The data to evaluate 86 * 87 * @return Mixed True if the last item in the group, false if not and 88 * this same object if the path is not finished 89 */ 90 public function last($data) 91 { 92 if ( !is_array($data) && !is_object($data) && !is_null($data) ) { 93 94 if ( !isset($this->cache['L']) ) { 95 96 $hash = md5($data); 97 98 if (empty($this->dict['L'])) { 99 $this->dict['L'] = $hash; 100 $res = false; 101 } elseif ($this->dict['L'] !== $hash) { 102 $this->dict['L'] = $hash; 103 $res = true; 104 } else { 105 $res = false; 106 } 107 108 $this->cache['L'] = $res; 109 } 110 111 return $this->cache['L']; 112 } 113 114 $this->data = $data; 115 $this->branch = 'L'; 116 $this->vars = array(); 117 return $this; 118 } 119 120 /** 121 * Handles variable accesses for the tal path resolver 122 * 123 * @param string $var The variable name to check 124 * 125 * @return Mixed An object/array if the path is not over or a boolean 126 * 127 * @todo replace the PHPTAL_Context::path() with custom code 128 */ 129 public function __get($var) 130 { 131 // When the iterator item is empty we just let the tal 132 // expression consume by continuously returning this 133 // same object which should evaluate to true for 'last' 134 if ( is_null($this->data) ) { 135 return $this; 136 } 137 138 // Find the requested variable 139 $value = PHPTAL_Context::path($this->data, $var, true); 140 141 // Check if it's an object or an array 142 if ( is_array($value) || is_object($value) ) { 143 // Move the context to the requested variable and return 144 $this->data = $value; 145 $this->addVarName($var); 146 return $this; 147 } 148 149 // get a hash of the variable contents 150 $hash = md5($value); 151 152 // compute a path for the variable to use as dictionary key 153 $path = $this->branch . $this->getVarPath() . $var; 154 155 // If we don't know about this var store in the dictionary 156 if ( !isset($this->cache[$path]) ) { 157 158 if ( !isset($this->dict[$path]) ) { 159 $this->dict[$path] = $hash; 160 $res = $this->branch === 'F'; 161 } else { 162 // Check if the value has changed 163 if ($this->dict[$path] !== $hash) { 164 $this->dict[$path] = $hash; 165 $res = true; 166 } else { 167 $res = false; 168 } 169 } 170 171 $this->cache[$path] = $res; 172 } 173 174 return $this->cache[$path]; 175 176 } 177 178 /** 179 * Adds a variable name to the current path of variables 180 * 181 * @param string $varname The variable name to store as a path part 182 * @access protected 183 */ 184 protected function addVarName($varname) 185 { 186 $this->vars[] = $varname; 187 } 188 189 /** 190 * Returns the current variable path separated by a slash 191 * 192 * @return String The current variable path 193 * @access protected 194 */ 195 protected function getVarPath() 196 { 197 return implode('/', $this->vars) . '/'; 198 } 199} 200