Source for file reflection_php5.php

Documentation is available at reflection_php5.php

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

Documentation generated on Sun, 04 May 2008 09:21:59 -0500 by phpDocumentor 1.3.0