| <?php |
| /** |
| * File containing the ezcReflectionFunction class. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package Reflection |
| * @version //autogen// |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| */ |
| |
| /** |
| * Extends the ReflectionFunction class to provide type information |
| * using PHPDoc annotations. |
| * |
| * @package Reflection |
| * @version //autogen// |
| * @author Stefan Marr <mail@stefan-marr.de> |
| * @author Falko Menge <mail@falko-menge.de> |
| */ |
| class ezcReflectionFunction extends ReflectionFunction |
| { |
| /** |
| * @var ezcReflectionDocCommentParser Parser for source code annotations |
| */ |
| protected $docParser; |
| |
| /** |
| * @var string|ReflectionFunction |
| * ReflectionFunction object or function name used to initialize this |
| * object |
| */ |
| protected $reflectionSource; |
| |
| /** |
| * Constructs a new ezcReflectionFunction object |
| * |
| * Throws an Exception in case the given function does not exist |
| * @param string|ReflectionFunction $function |
| * Name or ReflectionFunction object of the function to be reflected |
| */ |
| public function __construct( $function ) { |
| if ( !$function instanceof ReflectionFunction ) { |
| parent::__construct( $function ); |
| } |
| $this->reflectionSource = $function; |
| |
| $this->docParser = ezcReflection::getDocCommentParser(); |
| $this->docParser->parse( $this->getDocComment() ); |
| } |
| |
| /** |
| * Use overloading to call additional methods |
| * of the ReflectionFunction instance given to the constructor. |
| * |
| * @param string $method Method to be called |
| * @param array $arguments Arguments that were passed |
| * @return mixed |
| */ |
| public function __call( $method, $arguments ) |
| { |
| $callback = array( $this->reflectionSource, $method ); |
| if ( $this->reflectionSource instanceof parent |
| and is_callable( $callback ) ) |
| { |
| // query external reflection object |
| return call_user_func_array( $callback, $arguments ); |
| } |
| else |
| { |
| throw new ezcReflectionCallToUndefinedMethodException( __CLASS__, $method ); |
| } |
| } |
| |
| /** |
| * Forwards a method invocation to either the reflection source passed to |
| * the constructor of this class when creating an instance or to the parent |
| * class. |
| * |
| * This method is part of the dependency injection mechanism and serves as |
| * a helper for implementing wrapper methods without code duplication. |
| * @param string $method Name of the method to be invoked |
| * @param mixed[] $arguments Arguments to be passed to the method |
| * @return mixed Return value of the invoked method |
| */ |
| protected function forwardCallToReflectionSource( $method, $arguments = array() ) { |
| if ( $this->reflectionSource instanceof parent ) { |
| return call_user_func_array( array( $this->reflectionSource, $method ), $arguments ); |
| } else { |
| //* |
| return call_user_func_array( array( $this, 'parent::' . $method ), $arguments ); |
| /*/ |
| $argumentStrings = array(); |
| foreach ( array_keys( $arguments ) as $key ) { |
| $argumentStrings[] = '$arguments[' . var_export( $key, true ) . ']'; |
| } |
| $cmd = 'return parent::$method( ' . implode( ', ', $argumentStrings ) . ' );'; |
| return eval( $cmd ); |
| //*/ |
| } |
| } |
| |
| /** |
| * Returns the parameters of the function as ezcReflectionParameter objects |
| * |
| * @return ezcReflectionParameter[] Parameters of the Function |
| * @since PHP 5.1.0 |
| */ |
| function getParameters() { |
| $params = $this->docParser->getParamAnnotations(); |
| $extParams = array(); |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| $apiParams = $this->reflectionSource->getParameters(); |
| } else { |
| $apiParams = parent::getParameters(); |
| } |
| foreach ($apiParams as $param) { |
| $type = null; |
| foreach ($params as $annotation) { |
| if ( |
| $annotation instanceof ezcReflectionAnnotationParam |
| and $annotation->getParamName() == $param->getName() |
| ) { |
| $type = $annotation->getTypeName(); |
| break; |
| } |
| } |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| $extParams[] = new ezcReflectionParameter( |
| null, |
| $param, |
| $type |
| ); |
| } else { |
| // slightly increase performance and save some memory |
| $extParams[] = new ezcReflectionParameter( |
| $this->getName(), |
| $param->getPosition(), |
| $type |
| ); |
| } |
| } |
| return $extParams; |
| } |
| |
| /** |
| * Returns the type of the return value |
| * |
| * @return ezcReflectionType |
| * @since PHP 5.1.0 |
| */ |
| function getReturnType() { |
| $re = $this->docParser->getReturnAnnotations(); |
| if (count($re) == 1 and isset($re[0]) and $re[0] instanceof ezcReflectionAnnotationReturn) { |
| return ezcReflection::getTypeByName($re[0]->getTypeName()); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the description of the return value |
| * |
| * @return string |
| * @since PHP 5.1.0 |
| */ |
| function getReturnDescription() { |
| $re = $this->docParser->getReturnAnnotations(); |
| if (count($re) == 1 and isset($re[0])) { |
| return $re[0]->getDescription(); |
| } |
| return ''; |
| } |
| |
| /** |
| * Returns the short description from the function's documentation |
| * |
| * @return string Short description |
| * @since PHP 5.1.0 |
| */ |
| public function getShortDescription() { |
| return $this->docParser->getShortDescription(); |
| } |
| |
| /** |
| * Returns the long description from the function's documentation |
| * |
| * @return string Long descrition |
| * @since PHP 5.1.0 |
| */ |
| public function getLongDescription() { |
| return $this->docParser->getLongDescription(); |
| } |
| |
| /** |
| * Checks whether the function is annotated with the annotation $annotation |
| * |
| * @param string $annotation Name of the annotation |
| * @return boolean True if the annotation exists for this function |
| * @since PHP 5.1.0 |
| */ |
| public function hasAnnotation($annotation) { |
| return $this->docParser->hasAnnotation($annotation); |
| } |
| |
| /** |
| * Returns an array of annotations (optinally only annotations of a given name) |
| * |
| * @param string $name Name of the annotations |
| * @return ezcReflectionAnnotation[] Annotations |
| * @since PHP 5.1.0 |
| */ |
| public function getAnnotations($name = '') { |
| if ($name == '') { |
| return $this->docParser->getAnnotations(); |
| } |
| else { |
| return $this->docParser->getAnnotationsByName($name); |
| } |
| } |
| |
| /** |
| * Returns the source code of the function |
| * |
| * @return string Source code |
| */ |
| public function getCode() |
| { |
| if ( $this->isInternal() ) { |
| $code = '/* ' . $this->getName() . ' is an internal function.' |
| . ' Therefore the source code is not available. */'; |
| } else { |
| $filename = $this->getFileName(); |
| |
| $start = $this->getStartLine(); |
| $end = $this->getEndLine(); |
| |
| $offset = $start - 1; |
| $length = $end - $start + 1; |
| |
| $lines = array_slice( file( $filename ), $offset, $length ); |
| |
| if ( strpos( trim( $lines[0] ), 'function' ) !== 0 ) { |
| $lines[0] = substr( $lines[0], strpos( $lines[0], 'function' ) ); |
| } |
| |
| $code = implode( '', $lines ); |
| } |
| return $code; |
| } |
| |
| |
| // the following methods do not contain additional features |
| // they just call the parent method or the reflection source |
| |
| /** |
| * Returns a string representation |
| * |
| * @return string String representation |
| */ |
| public function __toString() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->__toString(); |
| } else { |
| return parent::__toString(); |
| } |
| } |
| |
| /** |
| * Returns this function's name |
| * |
| * @return string This function's name |
| */ |
| public function getName() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->getName(); |
| } else { |
| return parent::getName(); |
| } |
| } |
| |
| /** |
| * Returns whether this is an internal function |
| * |
| * @return boolean True if this is an internal function |
| */ |
| public function isInternal() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->isInternal(); |
| } else { |
| return parent::isInternal(); |
| } |
| } |
| |
| /** |
| * Returns whether this is a user-defined function |
| * |
| * @return boolean True if this is a user-defined function |
| */ |
| public function isUserDefined() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->isUserDefined(); |
| } else { |
| return parent::isUserDefined(); |
| } |
| } |
| |
| /** |
| * Returns whether this function has been disabled or not |
| * |
| * @return boolean True if this function has been disabled |
| */ |
| public function isDisabled() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->isDisabled(); |
| } else { |
| return parent::isDisabled(); |
| } |
| } |
| |
| /** |
| * Returns the filename of the file this function was declared in |
| * |
| * @return string Filename of the file this function was declared in |
| */ |
| public function getFileName() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->getFileName(); |
| } else { |
| return parent::getFileName(); |
| } |
| } |
| |
| /** |
| * Returns the line this function's declaration starts at |
| * |
| * @return integer Line this function's declaration starts at |
| */ |
| public function getStartLine() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->getStartLine(); |
| } else { |
| return parent::getStartLine(); |
| } |
| } |
| |
| /** |
| * Returns the line this function's declaration ends at |
| * |
| * @return integer Line this function's declaration ends at |
| */ |
| public function getEndLine() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->getEndLine(); |
| } else { |
| return parent::getEndLine(); |
| } |
| } |
| |
| /** |
| * Returns the doc comment for this function |
| * |
| * @return string Doc comment for this function |
| * @since PHP 5.1.0 |
| */ |
| public function getDocComment() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->getDocComment(); |
| } else { |
| return parent::getDocComment(); |
| } |
| } |
| |
| /** |
| * Returns an associative array containing this function's static variables |
| * and their values |
| * |
| * @return array<sting,mixed> This function's static variables |
| */ |
| public function getStaticVariables() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->getStaticVariables(); |
| } else { |
| return parent::getStaticVariables(); |
| } |
| } |
| |
| /** |
| * Invokes the function |
| * |
| * @param mixed $argument,... Arguments |
| * @return mixed Return value of the function invocation |
| */ |
| public function invoke( $arguments = array() ) { |
| $arguments = func_get_args(); |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| // doesn't work: return call_user_func_array( array( $this->reflectionSource, 'invoke' ), $arguments ); |
| // but hopefully the methods invoke and invokeArgs of |
| // the external ReflectionFunction implementation are semantically the same |
| return $this->reflectionSource->invokeArgs( $arguments ); |
| } else { |
| // doesn't work: return call_user_func_array( array( parent, 'invoke' ), $arguments ); |
| // but hopefully the methods invoke and invokeArgs of |
| // PHP's ReflectionFunction are semantically the same |
| return parent::invokeArgs( $arguments ); |
| } |
| } |
| |
| /** |
| * Invokes the function and allows to pass its arguments as an array |
| * |
| * @param array<integer,mixed> $arguments |
| * Arguments |
| * @return mixed |
| * Return value of the function invocation |
| * @since PHP 5.1.0 |
| */ |
| public function invokeArgs( Array $arguments ) { |
| /* |
| return $this->forwardCallToReflectionSource( __FUNCTION__, array( $arguments ) ); |
| /*/ |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->invokeArgs( $arguments ); |
| } else { |
| return parent::invokeArgs( $arguments ); |
| } |
| //*/ |
| } |
| |
| /** |
| * Returns whether this function returns a reference |
| * |
| * @return boolean True if this function returns a reference |
| */ |
| public function returnsReference() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->returnsReference(); |
| } else { |
| return parent::returnsReference(); |
| } |
| } |
| |
| /** |
| * Returns the number of parameters |
| * |
| * @return integer The number of parameters |
| * @since PHP 5.0.3 |
| */ |
| public function getNumberOfParameters() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->getNumberOfParameters(); |
| } else { |
| return parent::getNumberOfParameters(); |
| } |
| } |
| |
| /** |
| * Returns the number of required parameters |
| * |
| * @return integer The number of required parameters |
| * @since PHP 5.0.3 |
| */ |
| public function getNumberOfRequiredParameters() { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->getNumberOfRequiredParameters(); |
| } else { |
| return parent::getNumberOfRequiredParameters(); |
| } |
| } |
| |
| /** |
| * Returns NULL or the extension the function belongs to |
| * |
| * @return ezcReflectionExtension Extension the function belongs to |
| */ |
| public function getExtension() { |
| if ( $this->getExtensionName() === false ) { |
| return null; |
| } else { |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return new ezcReflectionExtension( |
| $this->reflectionSource->getExtension() |
| ); |
| } else { |
| // using the name, since otherwhise the object would be treated like an |
| // external reflection implementation and that would decrease performance |
| return new ezcReflectionExtension( parent::getExtensionName() ); |
| } |
| } |
| } |
| |
| /** |
| * Returns false or the name of the extension the function belongs to |
| * |
| * @return string|boolean False or the name of the extension |
| */ |
| public function getExtensionName() { |
| return $this->forwardCallToReflectionSource( __FUNCTION__ ); |
| } |
| |
| /** |
| * Returns whether this function is deprecated |
| * |
| * This is purely a wrapper method, which calls the corresponding method of |
| * the parent class. |
| * @return boolean |
| */ |
| public function isDeprecated() { |
| // TODO: also check @deprecated annotation |
| if ( $this->reflectionSource instanceof ReflectionFunction ) { |
| return $this->reflectionSource->isDeprecated(); |
| } else { |
| return parent::isDeprecated(); |
| } |
| } |
| |
| /** |
| * Returns the name of namespace where this function is defined |
| * |
| * This is purely a wrapper method, which either calls the corresponding |
| * method of the parent class or forwards the call to the ReflectionClass |
| * instance passed to the constructor. |
| * @return string The name of namespace where this function is defined |
| * @since PHP 5.3.0 |
| */ |
| public function getNamespaceName() { |
| return $this->forwardCallToReflectionSource( __FUNCTION__ ); |
| } |
| |
| /** |
| * Returns whether this function is defined in a namespace |
| * |
| * This is purely a wrapper method, which either calls the corresponding |
| * method of the parent class or forwards the call to the ReflectionClass |
| * instance passed to the constructor. |
| * @return boolean Whether this function is defined in a namespace |
| * @since PHP 5.3.0 |
| */ |
| public function inNamespace() { |
| return $this->forwardCallToReflectionSource( __FUNCTION__ ); |
| } |
| |
| /** |
| * Returns the short name of the function (without namespace part) |
| * |
| * This is purely a wrapper method, which either calls the corresponding |
| * method of the parent class or forwards the call to the ReflectionClass |
| * instance passed to the constructor. |
| * @return string |
| * Returns the short name of the function (without namespace part) |
| * @since PHP 5.3.0 |
| */ |
| public function getShortName() { |
| return $this->forwardCallToReflectionSource( __FUNCTION__ ); |
| } |
| |
| /** |
| * Returns whether this is a closure |
| * |
| * This is purely a wrapper method, which either calls the corresponding |
| * method of the parent class or forwards the call to the ReflectionClass |
| * instance passed to the constructor. |
| * @return boolean Whether this is a closure |
| * @since PHP 5.3.0 |
| */ |
| public function isClosure() { |
| return $this->forwardCallToReflectionSource( __FUNCTION__ ); |
| } |
| |
| /** |
| * Exports a ReflectionFunction object. |
| * |
| * Returns the output if TRUE is specified for $return, printing it otherwise. |
| * This is purely a wrapper method, which calls the corresponding method of |
| * the parent class (ReflectionFunction::export()). |
| * @param string $function Name of the function |
| * @param boolean $return |
| * Whether to return (TRUE) or print (FALSE) the output |
| * @return mixed |
| */ |
| public static function export($function, $return = false) { |
| return parent::export($function, $return); |
| } |
| |
| } |
| ?> |