Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

Context.php

Go to the documentation of this file.
00001 <?php 00002 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 00003 // 00004 // Copyright (c) 2003 Laurent Bedubourg 00005 // 00006 // This library is free software; you can redistribute it and/or 00007 // modify it under the terms of the GNU Lesser General Public 00008 // License as published by the Free Software Foundation; either 00009 // version 2.1 of the License, or (at your option) any later version. 00010 // 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 // Lesser General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public 00017 // License along with this library; if not, write to the Free Software 00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 // 00020 // Authors: Laurent Bedubourg <laurent.bedubourg@free.fr> 00021 // 00022 00023 00024 // What are Context and Resolvers 00025 // ============================== 00026 // 00027 // In phptal, variables and methods are referenced by path without distinction, 00028 // also, arrays and hashtable elements are accessed using a path like 00029 // myarray/10 to reach the 11's element of myarray or myhash/mykey to 00030 // reach the value of mykey in myhash. 00031 // 00032 // This allow things like 'myobject/mymethod/10/othermethod' which is usefull 00033 // in templates. 00034 // 00035 // The Context is an array containing all template variables. 00036 // When asked to reach a path, it look for the variable type of the first path 00037 // element and generate a resolver matching the variable type. 00038 // Then this resolver is asked to resolve the rest of the path, etc... up to 00039 // the final path element. 00040 // 00041 // Resolver knows how to handle a given path relatively to the object they 00042 // handle. 00043 // 00044 // For instance, an array resolver can handle access to its array elements 00045 // given a key (string) or the element id (int). 00046 // 00047 // The array resolver also bring an array method : count which return the 00048 // number of elements in the array. 00049 // 00050 // Note 00051 // ---- 00052 // 00053 // If a name conflict occurs between an object's variable and one of its 00054 // methods, the variable is return in stead of the method. 00055 // 00056 00065 class PHPTAL_Context 00066 { 00067 var $_array = array(); 00068 var $_errorRaised = false; 00069 00075 function PHPTAL_Context($hash=array()) 00076 { 00077 $this->_array = $hash; 00078 } 00079 00086 function setRef($path, &$value) 00087 { 00088 $this->remove($path); 00089 $this->_array[$path] =& $value; 00090 } 00091 00098 function set($path, $value) 00099 { 00100 $this->remove($path); 00101 $this->_array[$path] = $value; 00102 } 00103 00109 function remove($path) 00110 { 00111 if (array_key_exists($path, $this->_array)) { 00112 unset($this->_array[$path]); 00113 } 00114 } 00115 00124 function has($path) 00125 { 00126 if (array_key_exists($path, $this->_array)) { 00127 return true; 00128 } 00129 $resp =& PHPTAL_ArrayResolver::get($this->_array, $path); 00130 if (PEAR::isError($resp)) { 00131 return false; 00132 } else if ($resp === null) { 00133 return false; 00134 } 00135 return true; 00136 } 00137 00141 function &getHash() 00142 { 00143 return $this->_array; 00144 } 00145 00155 function &get($path) 00156 { 00157 if (array_key_exists($path, $this->_array)) { 00158 return $this->_array[$path]; 00159 } 00160 $resp =& PHPTAL_ArrayResolver::get($this->_array, $path); 00161 if (PEAR::isError($resp)) { 00162 $this->_errorRaised = $resp; 00163 } else if ($resp === null) { 00164 $this->_errorRaised = true; 00165 } 00166 return $resp; 00167 } 00168 00177 function &getToString($path) 00178 { 00179 $o = $this->get($path); 00180 if (is_object($o) && method_exists($o, "toString")) { 00181 return $o->toString(); 00182 } 00183 if (is_object($o) || is_array($o)) { 00184 ob_start(); 00185 print_r($o); // var_dump($o); 00186 $res = ob_get_contents(); 00187 ob_end_clean(); 00188 return $res; 00189 } 00190 return $o; 00191 } 00192 00198 function errorRaised() 00199 { 00200 $r = $this->_errorRaised; 00201 $this->_errorRaised = false; 00202 return $r; 00203 } 00204 00208 function cleanError() 00209 { 00210 $this->_errorRaised = false; 00211 } 00212 } 00213 00222 class PHPTAL_ObjectResolver 00223 { 00224 function &get(&$obj, $subpath) 00225 { 00226 list($first, $next) = PHPTAL_path_explode($subpath); 00227 00228 if (method_exists($obj, $first)) { 00229 // reference to a variable of the handled object 00230 $value =& $obj->$first(); 00231 } elseif (array_key_exists($first, $obj)) { 00232 // reference to an object variable 00233 $value =& $obj->$first; 00234 } elseif (is_a($obj, 'OHash') && $obj->containsKey($first)) { 00235 return $obj->get($first); 00236 } elseif (is_a($obj, 'OArray') && preg_match('/^[0-9]+$/', $first)) { 00237 return $obj->get((int)$first); 00238 } else { 00239 $err = new NameError($subpath . " not found"); 00240 return $err; 00241 } 00242 // more to resolve in value 00243 if ($next) { 00244 return PHPTAL_resolve($next, $value, $obj); 00245 } 00246 return $value; 00247 } 00248 } 00249 00250 00258 class PHPTAL_ArrayResolver 00259 { 00260 function &get(&$array, $subpath) 00261 { 00262 list($first, $next) = PHPTAL_path_explode($subpath); 00263 00264 if ($first == "length" && !$next && !array_key_exists("length", $array)) { 00265 return count($array); 00266 } 00267 00268 if ($next === false) { 00269 if ($first == 'count') { return count($array); } 00270 if ($first == 'keys') { return array_keys($array); } 00271 if ($first == 'values'){ return array_values($array); } 00272 if (!array_key_exists($first, $array)) { 00273 $err = new NameError("(ArrayResolver) Context does not contains key '$first'"); 00274 return $err; 00275 } 00276 return $array[$first]; 00277 } 00278 00279 if (!array_key_exists($first, $array)) { 00280 $err = new NameError("(ArrayResolver) Context does not contains key '$first'"); 00281 return $err; 00282 } 00283 $temp =& $array[$first]; 00284 if ($temp) { 00285 return PHPTAL_resolve($next, $temp, $array); 00286 } 00287 } 00288 } 00289 00290 00296 class PHPTAL_StringResolver 00297 { 00298 function get(&$str, $subpath) 00299 { 00300 list($first, $next) = PHPTAL_path_explode($subpath); 00301 if ($next) { 00302 $err = new TypeError("string methods have no sub path (string.$subpath)"); 00303 return $err; 00304 } 00305 if ($first == "len") { 00306 return strlen($str); 00307 } 00308 $err = new NameError("string type has no method named '$first'"); 00309 return $err; 00310 } 00311 }; 00312 00316 function &PHPTAL_resolve($path, &$value, &$parent) 00317 { 00318 if (is_array($value)) return PHPTAL_ArrayResolver::get($value, $path); 00319 if (is_object($value)) return PHPTAL_ObjectResolver::get($value, $path); 00320 if (is_string($value)) return PHPTAL_StringResolver::get($value, $path); 00321 $err = new TypeError("unable to find adequate resolver for '".gettype($value)."' remaining path is '$path'"); 00322 return $err; 00323 } 00324 00331 function PHPTAL_path_explode($path) 00332 { 00333 if (preg_match('|^(.*?)\/(.*?)$|', $path, $match)) { 00334 array_shift($match); 00335 return $match; 00336 } else { 00337 return array($path, false); 00338 } 00339 00340 $pos = strpos($path,"."); 00341 if ($pos !== false) { 00342 $first = substr($path, 0, $pos); 00343 $next = substr($path, $pos+1); 00344 return array($first, $next); 00345 } 00346 return array($path, false); 00347 } 00348 00349 ?>

Generated on Tue Jun 29 23:40:03 2004 for Mediawiki by doxygen 1.3.7