| [ Index ] |
PHP Cross Reference of Limb3 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * base include file for SimpleTest 4 * @package SimpleTest 5 * @subpackage UnitTester 6 * @version $Id: reflection_php5.php 5999 2007-06-18 13:13:08Z pachanga $ 7 */ 8 9 /** 10 * Version specific reflection API. 11 * @package SimpleTest 12 * @subpackage UnitTester 13 */ 14 class SimpleReflection { 15 var $_interface; 16 17 /** 18 * Stashes the class/interface. 19 * @param string $interface Class or interface 20 * to inspect. 21 */ 22 function SimpleReflection($interface) { 23 $this->_interface = $interface; 24 } 25 26 /** 27 * Checks that a class has been declared. Versions 28 * before PHP5.0.2 need a check that it's not really 29 * an interface. 30 * @return boolean True if defined. 31 * @access public 32 */ 33 function classExists() { 34 if (! class_exists($this->_interface)) { 35 return false; 36 } 37 $reflection = new ReflectionClass($this->_interface); 38 return ! $reflection->isInterface(); 39 } 40 41 /** 42 * Needed to kill the autoload feature in PHP5 43 * for classes created dynamically. 44 * @return boolean True if defined. 45 * @access public 46 */ 47 function classExistsSansAutoload() { 48 return class_exists($this->_interface, false); 49 } 50 51 /** 52 * Checks that a class or interface has been 53 * declared. 54 * @return boolean True if defined. 55 * @access public 56 */ 57 function classOrInterfaceExists() { 58 return $this->_classOrInterfaceExistsWithAutoload($this->_interface, true); 59 } 60 61 /** 62 * Needed to kill the autoload feature in PHP5 63 * for classes created dynamically. 64 * @return boolean True if defined. 65 * @access public 66 */ 67 function classOrInterfaceExistsSansAutoload() { 68 return $this->_classOrInterfaceExistsWithAutoload($this->_interface, false); 69 } 70 71 /** 72 * Needed to select the autoload feature in PHP5 73 * for classes created dynamically. 74 * @param string $interface Class or interface name. 75 * @param boolean $autoload True totriggerautoload. 76 * @return boolean True if interface defined. 77 * @access private 78 */ 79 function _classOrInterfaceExistsWithAutoload($interface, $autoload) { 80 if (function_exists('interface_exists')) { 81 if (interface_exists($this->_interface, $autoload)) { 82 return true; 83 } 84 } 85 return class_exists($this->_interface, $autoload); 86 } 87 88 /** 89 * Gets the list of methods on a class or 90 * interface. 91 * @returns array List of method names. 92 * @access public 93 */ 94 function getMethods() { 95 return array_unique(get_class_methods($this->_interface)); 96 } 97 98 /** 99 * Gets the list of interfaces from a class. If the 100 * class name is actually an interface then just that 101 * interface is returned. 102 * @returns array List of interfaces. 103 * @access public 104 */ 105 function getInterfaces() { 106 $reflection = new ReflectionClass($this->_interface); 107 if ($reflection->isInterface()) { 108 return array($this->_interface); 109 } 110 return $this->_onlyParents($reflection->getInterfaces()); 111 } 112 113 /** 114 * Gets the list of methods for the implemented 115 * interfaces only. 116 * @returns array List of enforced method signatures. 117 * @access public 118 */ 119 function getInterfaceMethods() { 120 $methods = array(); 121 foreach ($this->getInterfaces() as $interface) { 122 $methods = array_merge($methods, get_class_methods($interface)); 123 } 124 return array_unique($methods); 125 } 126 127 /** 128 * Checks to see if the method signature has to be tightly 129 * specified. 130 * @param string $method Method name. 131 * @returns boolean True if enforced. 132 * @access private 133 */ 134 function _isInterfaceMethod($method) { 135 return in_array($method, $this->getInterfaceMethods()); 136 } 137 138 /** 139 * Finds the parent class name. 140 * @returns string Parent class name. 141 * @access public 142 */ 143 function getParent() { 144 $reflection = new ReflectionClass($this->_interface); 145 $parent = $reflection->getParentClass(); 146 if ($parent) { 147 return $parent->getName(); 148 } 149 return false; 150 } 151 152 /** 153 * Trivially determines if the class is abstract. 154 * @returns boolean True if abstract. 155 * @access public 156 */ 157 function isAbstract() { 158 $reflection = new ReflectionClass($this->_interface); 159 return $reflection->isAbstract(); 160 } 161 162 /** 163 * Trivially determines if the class is an interface. 164 * @returns boolean True if interface. 165 * @access public 166 */ 167 function isInterface() { 168 $reflection = new ReflectionClass($this->_interface); 169 return $reflection->isInterface(); 170 } 171 172 /** 173 * Scans for final methods, as they screw up inherited 174 * mocks by not allowing you to override them. 175 * @returns boolean True if the class has a final method. 176 * @access public 177 */ 178 function hasFinal() { 179 $reflection = new ReflectionClass($this->_interface); 180 foreach ($reflection->getMethods() as $method) { 181 if ($method->isFinal()) { 182 return true; 183 } 184 } 185 return false; 186 } 187 188 /** 189 * Whittles a list of interfaces down to only the 190 * necessary top level parents. 191 * @param array $interfaces Reflection API interfaces 192 * to reduce. 193 * @returns array List of parent interface names. 194 * @access private 195 */ 196 function _onlyParents($interfaces) { 197 $parents = array(); 198 $blacklist = array(); 199 foreach ($interfaces as $interface) { 200 foreach($interfaces as $possible_parent) { 201 if ($interface->getName() == $possible_parent->getName()) { 202 continue; 203 } 204 if ($interface->isSubClassOf($possible_parent)) { 205 $blacklist[$possible_parent->getName()] = true; 206 } 207 } 208 if (!isset($blacklist[$interface->getName()])) { 209 $parents[] = $interface->getName(); 210 } 211 } 212 return $parents; 213 } 214 215 /** 216 * Checks whether a method is abstract or not. 217 * 218 * @param string $name Method name. 219 * @return bool true if method is abstract, else false 220 * @access private 221 */ 222 function _isAbstractMethod($name) { 223 $interface = new ReflectionClass($this->_interface); 224 if (! $interface->hasMethod($name)) { 225 return false; 226 } 227 return $interface->getMethod($name)->isAbstract(); 228 } 229 230 /** 231 * Checks whether a method is abstract in parent or not. 232 * 233 * @param string $name Method name. 234 * @return bool true if method is abstract in parent, else false 235 * @access private 236 */ 237 function _isAbstractMethodInParent($name) { 238 $interface = new ReflectionClass($this->_interface); 239 if (! $parent = $interface->getParentClass()) { 240 return false; 241 } 242 if (! $parent->hasMethod($name)) { 243 return false; 244 } 245 return $parent->getMethod($name)->isAbstract(); 246 } 247 248 /** 249 * Checks whether a method is static or not. 250 * 251 * @param string $name Method name 252 * @return bool true if method is static, else false 253 * @access private 254 */ 255 function _isStaticMethod($name) { 256 $interface = new ReflectionClass($this->_interface); 257 if (! $interface->hasMethod($name)) { 258 return false; 259 } 260 return $interface->getMethod($name)->isStatic(); 261 } 262 263 /** 264 * Gets the source code matching the declaration 265 * of a method. 266 * @param string $name Method name. 267 * @return string Method signature up to last 268 * bracket. 269 * @access public 270 */ 271 function getSignature($name) { 272 if ($name == '__set') { 273 return 'function __set($key, $value)'; 274 } 275 if ($name == '__call') { 276 return 'function __call($method, $arguments)'; 277 } 278 if (version_compare(phpversion(), '5.1.0', '>=')) { 279 if (in_array($name, array('__get', '__isset', $name == '__unset'))) { 280 return "function {$name}(\$key)"; 281 } 282 } 283 // second check is required because methods can be protected abstract 284 // which means they are not callable, but need a complete signature 285 if (! is_callable(array($this->_interface, $name)) && ! $this->_isAbstractMethod($name)) { 286 return "function $name()"; 287 } 288 if ($this->_isInterfaceMethod($name) || 289 $this->_isAbstractMethod($name) || 290 $this->_isAbstractMethodInParent($name) || 291 $this->_isStaticMethod($name)) { 292 return $this->_getFullSignature($name); 293 } 294 return "function $name()"; 295 } 296 297 /** 298 * For a signature specified in an interface, full 299 * details must be replicated to be a valid implementation. 300 * @param string $name Method name. 301 * @return string Method signature up to last 302 * bracket. 303 * @access private 304 */ 305 function _getFullSignature($name) { 306 $interface = new ReflectionClass($this->_interface); 307 $method = $interface->getMethod($name); 308 $reference = $method->returnsReference() ? '&' : ''; 309 $static = $method->isStatic() ? 'static ' : ''; 310 return "{$static}function $reference$name(" . 311 implode(', ', $this->_getParameterSignatures($method)) . 312 ")"; 313 } 314 315 /** 316 * Gets the source code for each parameter. 317 * @param ReflectionMethod $method Method object from 318 * reflection API 319 * @return array List of strings, each 320 * a snippet of code. 321 * @access private 322 */ 323 function _getParameterSignatures($method) { 324 $signatures = array(); 325 foreach ($method->getParameters() as $parameter) { 326 $signature = ''; 327 $type = $parameter->getClass(); 328 if (is_null($type) && version_compare(phpversion(), '5.1.0', '>=') && $parameter->isArray()) { 329 $signature .= 'array '; 330 } elseif (!is_null($type)) { 331 $signature .= $type->getName() . ' '; 332 } 333 if ($parameter->isPassedByReference()) { 334 $signature .= '&'; 335 } 336 $signature .= '$' . $this->_suppressSpurious($parameter->getName()); 337 if ($this->_isOptional($parameter)) { 338 $signature .= ' = null'; 339 } 340 $signatures[] = $signature; 341 } 342 return $signatures; 343 } 344 345 /** 346 * The SPL library has problems with the 347 * Reflection library. In particular, you can 348 * get extra characters in parameter names :(. 349 * @param string $name Parameter name. 350 * @return string Cleaner name. 351 * @access private 352 */ 353 function _suppressSpurious($name) { 354 return str_replace(array('[', ']', ' '), '', $name); 355 } 356 357 /** 358 * Test of a reflection parameter being optional 359 * that works with early versions of PHP5. 360 * @param reflectionParameter $parameter Is this optional. 361 * @return boolean True if optional. 362 * @access private 363 */ 364 function _isOptional($parameter) { 365 if (method_exists($parameter, 'isOptional')) { 366 return $parameter->isOptional(); 367 } 368 return false; 369 } 370 } 371 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Sat Nov 22 03:48:54 2008 | Cross-referenced by PHPXref 0.7 |