[ Index ]

PHP Cross Reference of Limb3

title

Body

[close]

/tests_runner/lib/simpletest/ -> reflection_php5.php (source)

   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  ?>


Generated: Sat Nov 22 03:48:54 2008 Cross-referenced by PHPXref 0.7