- <?php
- /**
- * Zend Framework (http://framework.zend.com/)
- *
- * @link http://github.com/zendframework/zf2 for the canonical source repository
- * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
-
- namespace Zend\Server\Reflection;
-
- use ReflectionClass as PhpReflectionClass;
- use ReflectionFunction as PhpReflectionFunction;
- use ReflectionFunctionAbstract;
- use ReflectionMethod as PhpReflectionMethod;
- use Zend\Code\Reflection\DocBlockReflection;
-
- /**
- * Function/Method Reflection
- *
- * Decorates a ReflectionFunction. Allows setting and retrieving an alternate
- * 'service' name (i.e., the name to be used when calling via a service),
- * setting and retrieving the description (originally set using the docblock
- * contents), retrieving the callback and callback type, retrieving additional
- * method invocation arguments, and retrieving the
- * method {@link \Zend\Server\Reflection\Prototype prototypes}.
- */
- abstract class AbstractFunction
- {
- /**
- * @var ReflectionFunctionAbstract
- */
- protected $reflection;
-
- /**
- * Additional arguments to pass to method on invocation
- * @var array
- */
- protected $argv = array();
-
- /**
- * Used to store extra configuration for the method (typically done by the
- * server class, e.g., to indicate whether or not to instantiate a class).
- * Associative array; access is as properties via {@link __get()} and
- * {@link __set()}
- * @var array
- */
- protected $config = array();
-
- /**
- * Declaring class (needed for when serialization occurs)
- * @var string
- */
- protected $class;
-
- /**
- * Function/method description
- * @var string
- */
- protected $description = '';
-
- /**
- * Namespace with which to prefix function/method name
- * @var string
- */
- protected $namespace;
-
- /**
- * Prototypes
- * @var array
- */
- protected $prototypes = array();
-
- private $return;
- private $returnDesc;
- private $paramDesc;
- private $sigParams;
- private $sigParamsDepth;
-
- /**
- * Constructor
- *
- * @param ReflectionFunctionAbstract $r
- * @param null|string $namespace
- * @param null|array $argv
- * @throws Exception\InvalidArgumentException
- * @throws Exception\RuntimeException
- */
- public function __construct(ReflectionFunctionAbstract $r, $namespace = null, $argv = array())
- {
- $this->reflection = $r;
-
- // Determine namespace
- if (null !== $namespace) {
- $this->setNamespace($namespace);
- }
-
- // Determine arguments
- if (is_array($argv)) {
- $this->argv = $argv;
- }
-
- // If method call, need to store some info on the class
- if ($r instanceof PhpReflectionMethod) {
- $this->class = $r->getDeclaringClass()->getName();
- }
-
- // Perform some introspection
- $this->reflect();
- }
-
- /**
- * Create signature node tree
- *
- * Recursive method to build the signature node tree. Increments through
- * each array in {@link $sigParams}, adding every value of the next level
- * to the current value (unless the current value is null).
- *
- * @param \Zend\Server\Reflection\Node $parent
- * @param int $level
- * @return void
- */
- protected function addTree(Node $parent, $level = 0)
- {
- if ($level >= $this->sigParamsDepth) {
- return;
- }
-
- foreach ($this->sigParams[$level] as $value) {
- $node = new Node($value, $parent);
- if ((null !== $value) && ($this->sigParamsDepth > $level + 1)) {
- $this->addTree($node, $level + 1);
- }
- }
- }
-
- /**
- * Build the signature tree
- *
- * Builds a signature tree starting at the return values and descending
- * through each method argument. Returns an array of
- * {@link \Zend\Server\Reflection\Node}s.
- *
- * @return array
- */
- protected function buildTree()
- {
- $returnTree = array();
- foreach ($this->return as $value) {
- $node = new Node($value);
- $this->addTree($node);
- $returnTree[] = $node;
- }
-
- return $returnTree;
- }
-
- /**
- * Build method signatures
- *
- * Builds method signatures using the array of return types and the array of
- * parameters types
- *
- * @param array $return Array of return types
- * @param string $returnDesc Return value description
- * @param array $paramTypes Array of arguments (each an array of types)
- * @param array $paramDesc Array of parameter descriptions
- * @return array
- */
- protected function buildSignatures($return, $returnDesc, $paramTypes, $paramDesc)
- {
- $this->return = $return;
- $this->returnDesc = $returnDesc;
- $this->paramDesc = $paramDesc;
- $this->sigParams = $paramTypes;
- $this->sigParamsDepth = count($paramTypes);
- $signatureTrees = $this->buildTree();
- $signatures = array();
-
- $endPoints = array();
- foreach ($signatureTrees as $root) {
- $tmp = $root->getEndPoints();
- if (empty($tmp)) {
- $endPoints = array_merge($endPoints, array($root));
- } else {
- $endPoints = array_merge($endPoints, $tmp);
- }
- }
-
- foreach ($endPoints as $node) {
- if (!$node instanceof Node) {
- continue;
- }
-
- $signature = array();
- do {
- array_unshift($signature, $node->getValue());
- $node = $node->getParent();
- } while ($node instanceof Node);
-
- $signatures[] = $signature;
- }
-
- // Build prototypes
- $params = $this->reflection->getParameters();
- foreach ($signatures as $signature) {
- $return = new ReflectionReturnValue(array_shift($signature), $this->returnDesc);
- $tmp = array();
- foreach ($signature as $key => $type) {
- $param = new ReflectionParameter($params[$key], $type, (isset($this->paramDesc[$key]) ? $this->paramDesc[$key] : null));
- $param->setPosition($key);
- $tmp[] = $param;
- }
-
- $this->prototypes[] = new Prototype($return, $tmp);
- }
- }
-
- /**
- * Use code reflection to create method signatures
- *
- * Determines the method help/description text from the function DocBlock
- * comment. Determines method signatures using a combination of
- * ReflectionFunction and parsing of DocBlock @param and @return values.
- *
- * @throws Exception\RuntimeException
- * @return array
- */
- protected function reflect()
- {
- $function = $this->reflection;
- $paramCount = $function->getNumberOfParameters();
- $parameters = $function->getParameters();
- $scanner = new DocBlockReflection(($function->getDocComment()) ? : '/***/');
- $helpText = $scanner->getLongDescription();
- /* @var \Zend\Code\Reflection\DocBlock\Tag\ParamTag[] $paramTags */
- $paramTags = $scanner->getTags('param');
- /* @var \Zend\Code\Reflection\DocBlock\Tag\ReturnTag $returnTag */
- $returnTag = $scanner->getTag('return');
-
- if (empty($helpText)) {
- $helpText = $scanner->getShortDescription();
- if (empty($helpText)) {
- $helpText = $function->getName();
- }
- }
- $this->setDescription($helpText);
-
- if ($returnTag) {
- $return = array();
- $returnDesc = $returnTag->getDescription();
- foreach ($returnTag->getTypes() as $type) {
- $return[] = $type;
- }
- } else {
- $return = array('void');
- $returnDesc = '';
- }
-
- $paramTypesTmp = array();
- $paramDesc = array();
- if (empty($paramTags)) {
- foreach ($parameters as $param) {
- $paramTypesTmp[] = array(($param->isArray()) ? 'array' : 'mixed');
- $paramDesc[] = '';
- }
- } else {
- $paramDesc = array();
- foreach ($paramTags as $paramTag) {
- $paramTypesTmp[] = $paramTag->getTypes();
- $paramDesc[] = ($paramTag->getDescription()) ? : '';
- }
- }
-
- // Get all param types as arrays
- $nParamTypesTmp = count($paramTypesTmp);
- if ($nParamTypesTmp < $paramCount) {
- $start = $paramCount - $nParamTypesTmp;
- for ($i = $start; $i < $paramCount; ++$i) {
- $paramTypesTmp[$i] = array('mixed');
- $paramDesc[$i] = '';
- }
- } elseif ($nParamTypesTmp != $paramCount) {
- throw new Exception\RuntimeException(
- 'Variable number of arguments is not supported for services (except optional parameters). '
- . 'Number of function arguments must correspond to actual number of arguments described in a docblock.');
- }
-
- $paramTypes = array();
- foreach ($paramTypesTmp as $i => $param) {
- if ($parameters[$i]->isOptional()) {
- array_unshift($param, null);
- }
- $paramTypes[] = $param;
- }
-
- $this->buildSignatures($return, $returnDesc, $paramTypes, $paramDesc);
- }
-
-
- /**
- * Proxy reflection calls
- *
- * @param string $method
- * @param array $args
- * @throws Exception\BadMethodCallException
- * @return mixed
- */
- public function __call($method, $args)
- {
- if (method_exists($this->reflection, $method)) {
- return call_user_func_array(array($this->reflection, $method), $args);
- }
-
- throw new Exception\BadMethodCallException('Invalid reflection method ("' . $method . '")');
- }
-
- /**
- * Retrieve configuration parameters
- *
- * Values are retrieved by key from {@link $config}. Returns null if no
- * value found.
- *
- * @param string $key
- * @return mixed
- */
- public function __get($key)
- {
- if (isset($this->config[$key])) {
- return $this->config[$key];
- }
-
- return null;
- }
-
- /**
- * Set configuration parameters
- *
- * Values are stored by $key in {@link $config}.
- *
- * @param string $key
- * @param mixed $value
- * @return void
- */
- public function __set($key, $value)
- {
- $this->config[$key] = $value;
- }
-
- /**
- * Set method's namespace
- *
- * @param string $namespace
- * @throws Exception\InvalidArgumentException
- * @return void
- */
- public function setNamespace($namespace)
- {
- if (empty($namespace)) {
- $this->namespace = '';
- return;
- }
-
- if (!is_string($namespace) || !preg_match('/[a-z0-9_\.]+/i', $namespace)) {
- throw new Exception\InvalidArgumentException('Invalid namespace');
- }
-
- $this->namespace = $namespace;
- }
-
- /**
- * Return method's namespace
- *
- * @return string
- */
- public function getNamespace()
- {
- return $this->namespace;
- }
-
- /**
- * Set the description
- *
- * @param string $string
- * @throws Exception\InvalidArgumentException
- * @return void
- */
- public function setDescription($string)
- {
- if (!is_string($string)) {
- throw new Exception\InvalidArgumentException('Invalid description');
- }
-
- $this->description = $string;
- }
-
- /**
- * Retrieve the description
- *
- * @return string
- */
- public function getDescription()
- {
- return $this->description;
- }
-
- /**
- * Retrieve all prototypes as array of
- * {@link \Zend\Server\Reflection\Prototype}s
- *
- * @return Prototype[]
- */
- public function getPrototypes()
- {
- return $this->prototypes;
- }
-
- /**
- * Retrieve additional invocation arguments
- *
- * @return array
- */
- public function getInvokeArguments()
- {
- return $this->argv;
- }
-
- /**
- * Wakeup from serialization
- *
- * Reflection needs explicit instantiation to work correctly. Re-instantiate
- * reflection object on wakeup.
- *
- * @return void
- */
- public function __wakeup()
- {
- if ($this->reflection instanceof PhpReflectionMethod) {
- $class = new PhpReflectionClass($this->class);
- $this->reflection = new PhpReflectionMethod($class->newInstance(), $this->getName());
- } else {
- $this->reflection = new PhpReflectionFunction($this->getName());
- }
- }
- }
# |
Change |
User |
Description |
Committed |
|
#1
|
18334 |
Liz Lam |
initial add of jambox |
9 years ago
|
|