diff options
Diffstat (limited to 'vendors/simpletest/reflection_php5.php')
| -rwxr-xr-x | vendors/simpletest/reflection_php5.php | 380 | 
1 files changed, 380 insertions, 0 deletions
| diff --git a/vendors/simpletest/reflection_php5.php b/vendors/simpletest/reflection_php5.php new file mode 100755 index 000000000..8383bccd3 --- /dev/null +++ b/vendors/simpletest/reflection_php5.php @@ -0,0 +1,380 @@ +<?php +/** + *  base include file for SimpleTest + *  @package    SimpleTest + *  @subpackage UnitTester + *  @version    $Id: reflection_php5.php 1683 2008-03-05 21:57:08Z lastcraft $ + */ + +/** + *    Version specific reflection API. + *    @package SimpleTest + *    @subpackage UnitTester + */ +class SimpleReflection { +    var $_interface; + +    /** +     *    Stashes the class/interface. +     *    @param string $interface    Class or interface +     *                                to inspect. +     */ +    function SimpleReflection($interface) { +        $this->_interface = $interface; +    } + +    /** +     *    Checks that a class has been declared. Versions +     *    before PHP5.0.2 need a check that it's not really +     *    an interface. +     *    @return boolean            True if defined. +     *    @access public +     */ +    function classExists() { +        if (! class_exists($this->_interface)) { +            return false; +        } +        $reflection = new ReflectionClass($this->_interface); +        return ! $reflection->isInterface(); +    } + +    /** +     *    Needed to kill the autoload feature in PHP5 +     *    for classes created dynamically. +     *    @return boolean        True if defined. +     *    @access public +     */ +    function classExistsSansAutoload() { +        return class_exists($this->_interface, false); +    } + +    /** +     *    Checks that a class or interface has been +     *    declared. +     *    @return boolean            True if defined. +     *    @access public +     */ +    function classOrInterfaceExists() { +        return $this->_classOrInterfaceExistsWithAutoload($this->_interface, true); +    } + +    /** +     *    Needed to kill the autoload feature in PHP5 +     *    for classes created dynamically. +     *    @return boolean        True if defined. +     *    @access public +     */ +    function classOrInterfaceExistsSansAutoload() { +        return $this->_classOrInterfaceExistsWithAutoload($this->_interface, false); +    } + +    /** +     *    Needed to select the autoload feature in PHP5 +     *    for classes created dynamically. +     *    @param string $interface       Class or interface name. +     *    @param boolean $autoload       True totriggerautoload. +     *    @return boolean                True if interface defined. +     *    @access private +     */ +    function _classOrInterfaceExistsWithAutoload($interface, $autoload) { +        if (function_exists('interface_exists')) { +            if (interface_exists($this->_interface, $autoload)) { +                return true; +            } +        } +        return class_exists($this->_interface, $autoload); +    } + +    /** +     *    Gets the list of methods on a class or +     *    interface. +     *    @returns array              List of method names. +     *    @access public +     */ +    function getMethods() { +        return array_unique(get_class_methods($this->_interface)); +    } + +    /** +     *    Gets the list of interfaces from a class. If the +     *    class name is actually an interface then just that +     *    interface is returned. +     *    @returns array          List of interfaces. +     *    @access public +     */ +    function getInterfaces() { +        $reflection = new ReflectionClass($this->_interface); +        if ($reflection->isInterface()) { +            return array($this->_interface); +        } +        return $this->_onlyParents($reflection->getInterfaces()); +    } + +    /** +     *    Gets the list of methods for the implemented +     *    interfaces only. +     *    @returns array      List of enforced method signatures. +     *    @access public +     */ +    function getInterfaceMethods() { +        $methods = array(); +        foreach ($this->getInterfaces() as $interface) { +            $methods = array_merge($methods, get_class_methods($interface)); +        } +        return array_unique($methods); +    } + +    /** +     *    Checks to see if the method signature has to be tightly +     *    specified. +     *    @param string $method        Method name. +     *    @returns boolean             True if enforced. +     *    @access private +     */ +    function _isInterfaceMethod($method) { +        return in_array($method, $this->getInterfaceMethods()); +    } + +    /** +     *    Finds the parent class name. +     *    @returns string      Parent class name. +     *    @access public +     */ +    function getParent() { +        $reflection = new ReflectionClass($this->_interface); +        $parent = $reflection->getParentClass(); +        if ($parent) { +            return $parent->getName(); +        } +        return false; +    } + +    /** +     *    Trivially determines if the class is abstract. +     *    @returns boolean      True if abstract. +     *    @access public +     */ +    function isAbstract() { +        $reflection = new ReflectionClass($this->_interface); +        return $reflection->isAbstract(); +    } + +    /** +     *    Trivially determines if the class is an interface. +     *    @returns boolean      True if interface. +     *    @access public +     */ +    function isInterface() { +        $reflection = new ReflectionClass($this->_interface); +        return $reflection->isInterface(); +    } + +    /** +     *    Scans for final methods, as they screw up inherited +     *    mocks by not allowing you to override them. +     *    @returns boolean   True if the class has a final method. +     *    @access public +     */ +    function hasFinal() { +        $reflection = new ReflectionClass($this->_interface); +        foreach ($reflection->getMethods() as $method) { +            if ($method->isFinal()) { +                return true; +            } +        } +        return false; +    } + +    /** +     *    Whittles a list of interfaces down to only the +     *    necessary top level parents. +     *    @param array $interfaces     Reflection API interfaces +     *                                 to reduce. +     *    @returns array               List of parent interface names. +     *    @access private +     */ +    function _onlyParents($interfaces) { +        $parents = array(); +        $blacklist = array(); +        foreach ($interfaces as $interface) { +            foreach($interfaces as $possible_parent) { +                if ($interface->getName() == $possible_parent->getName()) { +                    continue; +                } +                if ($interface->isSubClassOf($possible_parent)) { +                    $blacklist[$possible_parent->getName()] = true; +                } +            } +            if (!isset($blacklist[$interface->getName()])) { +                $parents[] = $interface->getName(); +            } +        } +        return $parents; +    } + +    /** +     * Checks whether a method is abstract or not. +     * @param   string   $name  Method name. +     * @return  bool            true if method is abstract, else false +     * @access  private +     */ +    function _isAbstractMethod($name) { +        $interface = new ReflectionClass($this->_interface); +        if (! $interface->hasMethod($name)) { +            return false; +        } +        return $interface->getMethod($name)->isAbstract(); +    } + +    /** +     * Checks whether a method is the constructor. +     * @param   string   $name  Method name. +     * @return  bool            true if method is the constructor +     * @access  private +     */ +    function _isConstructor($name) { +        return ($name == '__construct') || ($name == $this->_interface); +    } + +    /** +     * Checks whether a method is abstract in all parents or not. +     * @param   string   $name  Method name. +     * @return  bool            true if method is abstract in parent, else false +     * @access  private +     */ +    function _isAbstractMethodInParents($name) { +        $interface = new ReflectionClass($this->_interface); +        $parent = $interface->getParentClass(); +        while($parent) { +            if (! $parent->hasMethod($name)) { +                return false; +            } +            if ($parent->getMethod($name)->isAbstract()) { +                return true; +            } +            $parent = $parent->getParentClass(); +        } +        return false; +    } + +    /** +     * Checks whether a method is static or not. +     * @param   string  $name   Method name +     * @return  bool            true if method is static, else false +     * @access  private +     */ +    function _isStaticMethod($name) { +        $interface = new ReflectionClass($this->_interface); +        if (! $interface->hasMethod($name)) { +            return false; +        } +        return $interface->getMethod($name)->isStatic(); +    } + +    /** +     *    Writes the source code matching the declaration +     *    of a method. +     *    @param string $name    Method name. +     *    @return string         Method signature up to last +     *                           bracket. +     *    @access public +     */ +    function getSignature($name) { +        if ($name == '__set') { +            return 'function __set($key, $value)'; +        } +        if ($name == '__call') { +            return 'function __call($method, $arguments)'; +        } +        if (version_compare(phpversion(), '5.1.0', '>=')) { +            if (in_array($name, array('__get', '__isset', $name == '__unset'))) { +                return "function {$name}(\$key)"; +            } +        } +        if ($name == '__toString') { +            return "function $name()"; +        } +        if ($this->_isInterfaceMethod($name) || +                $this->_isAbstractMethod($name) || +                $this->_isAbstractMethodInParents($name) || +                $this->_isStaticMethod($name)) { +            return $this->_getFullSignature($name); +        } +        return "function $name()"; +    } + +    /** +     *    For a signature specified in an interface, full +     *    details must be replicated to be a valid implementation. +     *    @param string $name    Method name. +     *    @return string         Method signature up to last +     *                           bracket. +     *    @access private +     */ +    function _getFullSignature($name) { +        $interface = new ReflectionClass($this->_interface); +        $method = $interface->getMethod($name); +        $reference = $method->returnsReference() ? '&' : ''; +        $static = $method->isStatic() ? 'static ' : ''; +        return "{$static}function $reference$name(" . +                implode(', ', $this->_getParameterSignatures($method)) . +                ")"; +    } + +    /** +     *    Gets the source code for each parameter. +     *    @param ReflectionMethod $method   Method object from +     *                                      reflection API +     *    @return array                     List of strings, each +     *                                      a snippet of code. +     *    @access private +     */ +    function _getParameterSignatures($method) { +        $signatures = array(); +        foreach ($method->getParameters() as $parameter) { +            $signature = ''; +            $type = $parameter->getClass(); +            if (is_null($type) && version_compare(phpversion(), '5.1.0', '>=') && $parameter->isArray()) { +                $signature .= 'array '; +            } elseif (!is_null($type)) { +                $signature .= $type->getName() . ' '; +            } +            if ($parameter->isPassedByReference()) { +                $signature .= '&'; +            } +            $signature .= '$' . $this->_suppressSpurious($parameter->getName()); +            if ($this->_isOptional($parameter)) { +                $signature .= ' = null'; +            } +            $signatures[] = $signature; +        } +        return $signatures; +    } + +    /** +     *    The SPL library has problems with the +     *    Reflection library. In particular, you can +     *    get extra characters in parameter names :(. +     *    @param string $name    Parameter name. +     *    @return string         Cleaner name. +     *    @access private +     */ +    function _suppressSpurious($name) { +        return str_replace(array('[', ']', ' '), '', $name); +    } + +    /** +     *    Test of a reflection parameter being optional +     *    that works with early versions of PHP5. +     *    @param reflectionParameter $parameter    Is this optional. +     *    @return boolean                          True if optional. +     *    @access private +     */ +    function _isOptional($parameter) { +        if (method_exists($parameter, 'isOptional')) { +            return $parameter->isOptional(); +        } +        return false; +    } +} +?> | 
