[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/zend/Zend/Server/Reflection/Function/ -> Abstract.php (source)

   1  <?php
   2  /**
   3   * Zend Framework
   4   *
   5   * LICENSE
   6   *
   7   * This source file is subject to the new BSD license that is bundled
   8   * with this package in the file LICENSE.txt.
   9   * It is also available through the world-wide-web at this URL:
  10   * http://framework.zend.com/license/new-bsd
  11   * If you did not receive a copy of the license and are unable to
  12   * obtain it through the world-wide-web, please send an email
  13   * to [email protected] so we can send you a copy immediately.
  14   *
  15   * @category   Zend
  16   * @package    Zend_Server
  17   * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  18   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  19   */
  20  
  21  /**
  22   * Zend_Server_Reflection_Node
  23   */
  24  require_once 'Zend/Server/Reflection/Node.php';
  25  
  26  /**
  27   * Zend_Server_Reflection_Parameter
  28   */
  29  require_once 'Zend/Server/Reflection/Parameter.php';
  30  
  31  /**
  32   * Zend_Server_Reflection_Prototype
  33   */
  34  require_once 'Zend/Server/Reflection/Prototype.php';
  35  
  36  /**
  37   * Function/Method Reflection
  38   *
  39   * Decorates a ReflectionFunction. Allows setting and retrieving an alternate
  40   * 'service' name (i.e., the name to be used when calling via a service),
  41   * setting and retrieving the description (originally set using the docblock
  42   * contents), retrieving the callback and callback type, retrieving additional
  43   * method invocation arguments, and retrieving the
  44   * method {@link Zend_Server_Reflection_Prototype prototypes}.
  45   *
  46   * @category   Zend
  47   * @package    Zend_Server
  48   * @subpackage Reflection
  49   * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  50   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  51   * @version $Id$
  52   */
  53  abstract class Zend_Server_Reflection_Function_Abstract
  54  {
  55      /**
  56       * @var ReflectionFunction
  57       */
  58      protected $_reflection;
  59  
  60      /**
  61       * Additional arguments to pass to method on invocation
  62       * @var array
  63       */
  64      protected $_argv = array();
  65  
  66      /**
  67       * Used to store extra configuration for the method (typically done by the
  68       * server class, e.g., to indicate whether or not to instantiate a class).
  69       * Associative array; access is as properties via {@link __get()} and
  70       * {@link __set()}
  71       * @var array
  72       */
  73      protected $_config = array();
  74  
  75      /**
  76       * Declaring class (needed for when serialization occurs)
  77       * @var string
  78       */
  79      protected $_class;
  80  
  81      /**
  82       * Function/method description
  83       * @var string
  84       */
  85      protected $_description = '';
  86  
  87      /**
  88       * Namespace with which to prefix function/method name
  89       * @var string
  90       */
  91      protected $_namespace;
  92  
  93      /**
  94       * Prototypes
  95       * @var array
  96       */
  97      protected $_prototypes = array();
  98  
  99      private $_return;
 100      private $_returnDesc;
 101      private $_paramDesc;
 102      private $_sigParams;
 103      private $_sigParamsDepth;
 104  
 105      /**
 106       * Constructor
 107       *
 108       * @param ReflectionFunction $r
 109       */
 110      public function __construct(Reflector $r, $namespace = null, $argv = array())
 111      {
 112          // In PHP 5.1.x, ReflectionMethod extends ReflectionFunction. In 5.2.x,
 113          // both extend ReflectionFunctionAbstract. So, we can't do normal type
 114          // hinting in the prototype, but instead need to do some explicit
 115          // testing here.
 116          if ((!$r instanceof ReflectionFunction)
 117              && (!$r instanceof ReflectionMethod)) {
 118              require_once 'Zend/Server/Reflection/Exception.php';
 119              throw new Zend_Server_Reflection_Exception('Invalid reflection class');
 120          }
 121          $this->_reflection = $r;
 122  
 123          // Determine namespace
 124          if (null !== $namespace){
 125              $this->setNamespace($namespace);
 126          }
 127  
 128          // Determine arguments
 129          if (is_array($argv)) {
 130              $this->_argv = $argv;
 131          }
 132  
 133          // If method call, need to store some info on the class
 134          if ($r instanceof ReflectionMethod) {
 135              $this->_class = $r->getDeclaringClass()->getName();
 136          }
 137  
 138          // Perform some introspection
 139          $this->_reflect();
 140      }
 141  
 142      /**
 143       * Create signature node tree
 144       *
 145       * Recursive method to build the signature node tree. Increments through
 146       * each array in {@link $_sigParams}, adding every value of the next level
 147       * to the current value (unless the current value is null).
 148       *
 149       * @param Zend_Server_Reflection_Node $parent
 150       * @param int $level
 151       * @return void
 152       */
 153      protected function _addTree(Zend_Server_Reflection_Node $parent, $level = 0)
 154      {
 155          if ($level >= $this->_sigParamsDepth) {
 156              return;
 157          }
 158  
 159          foreach ($this->_sigParams[$level] as $value) {
 160              $node = new Zend_Server_Reflection_Node($value, $parent);
 161              if ((null !== $value) && ($this->_sigParamsDepth > $level + 1)) {
 162                  $this->_addTree($node, $level + 1);
 163              }
 164          }
 165      }
 166  
 167      /**
 168       * Build the signature tree
 169       *
 170       * Builds a signature tree starting at the return values and descending
 171       * through each method argument. Returns an array of
 172       * {@link Zend_Server_Reflection_Node}s.
 173       *
 174       * @return array
 175       */
 176      protected function _buildTree()
 177      {
 178          $returnTree = array();
 179          foreach ((array) $this->_return as $value) {
 180              $node = new Zend_Server_Reflection_Node($value);
 181              $this->_addTree($node);
 182              $returnTree[] = $node;
 183          }
 184  
 185          return $returnTree;
 186      }
 187  
 188      /**
 189       * Build method signatures
 190       *
 191       * Builds method signatures using the array of return types and the array of
 192       * parameters types
 193       *
 194       * @param array $return Array of return types
 195       * @param string $returnDesc Return value description
 196       * @param array $params Array of arguments (each an array of types)
 197       * @param array $paramDesc Array of parameter descriptions
 198       * @return array
 199       */
 200      protected function _buildSignatures($return, $returnDesc, $paramTypes, $paramDesc)
 201      {
 202          $this->_return         = $return;
 203          $this->_returnDesc     = $returnDesc;
 204          $this->_paramDesc      = $paramDesc;
 205          $this->_sigParams      = $paramTypes;
 206          $this->_sigParamsDepth = count($paramTypes);
 207          $signatureTrees        = $this->_buildTree();
 208          $signatures            = array();
 209  
 210          $endPoints = array();
 211          foreach ($signatureTrees as $root) {
 212              $tmp = $root->getEndPoints();
 213              if (empty($tmp)) {
 214                  $endPoints = array_merge($endPoints, array($root));
 215              } else {
 216                  $endPoints = array_merge($endPoints, $tmp);
 217              }
 218          }
 219  
 220          foreach ($endPoints as $node) {
 221              if (!$node instanceof Zend_Server_Reflection_Node) {
 222                  continue;
 223              }
 224  
 225              $signature = array();
 226              do {
 227                  array_unshift($signature, $node->getValue());
 228                  $node = $node->getParent();
 229              } while ($node instanceof Zend_Server_Reflection_Node);
 230  
 231              $signatures[] = $signature;
 232          }
 233  
 234          // Build prototypes
 235          $params = $this->_reflection->getParameters();
 236          foreach ($signatures as $signature) {
 237              $return = new Zend_Server_Reflection_ReturnValue(array_shift($signature), $this->_returnDesc);
 238              $tmp    = array();
 239              foreach ($signature as $key => $type) {
 240                  $param = new Zend_Server_Reflection_Parameter($params[$key], $type, (isset($this->_paramDesc[$key]) ? $this->_paramDesc[$key] : null));
 241                  $param->setPosition($key);
 242                  $tmp[] = $param;
 243              }
 244  
 245              $this->_prototypes[] = new Zend_Server_Reflection_Prototype($return, $tmp);
 246          }
 247      }
 248  
 249      /**
 250       * Use code reflection to create method signatures
 251       *
 252       * Determines the method help/description text from the function DocBlock
 253       * comment. Determines method signatures using a combination of
 254       * ReflectionFunction and parsing of DocBlock @param and @return values.
 255       *
 256       * @param ReflectionFunction $function
 257       * @return array
 258       */
 259      protected function _reflect()
 260      {
 261          $function           = $this->_reflection;
 262          $helpText           = '';
 263          $signatures         = array();
 264          $returnDesc         = '';
 265          $paramCount         = $function->getNumberOfParameters();
 266          $paramCountRequired = $function->getNumberOfRequiredParameters();
 267          $parameters         = $function->getParameters();
 268          $docBlock           = $function->getDocComment();
 269  
 270          if (!empty($docBlock)) {
 271              // Get help text
 272              if (preg_match(':/\*\*\s*\r?\n\s*\*\s(.*?)\r?\n\s*\*(\s@|/):s', $docBlock, $matches))
 273              {
 274                  $helpText = $matches[1];
 275                  $helpText = preg_replace('/(^\s*\*\s)/m', '', $helpText);
 276                  $helpText = preg_replace('/\r?\n\s*\*\s*(\r?\n)*/s', "\n", $helpText);
 277                  $helpText = trim($helpText);
 278              }
 279  
 280              // Get return type(s) and description
 281              $return     = 'void';
 282              if (preg_match('/@return\s+(\S+)/', $docBlock, $matches)) {
 283                  $return = explode('|', $matches[1]);
 284                  if (preg_match('/@return\s+\S+\s+(.*?)(@|\*\/)/s', $docBlock, $matches))
 285                  {
 286                      $value = $matches[1];
 287                      $value = preg_replace('/\s?\*\s/m', '', $value);
 288                      $value = preg_replace('/\s{2,}/', ' ', $value);
 289                      $returnDesc = trim($value);
 290                  }
 291              }
 292  
 293              // Get param types and description
 294              if (preg_match_all('/@param\s+([^\s]+)/m', $docBlock, $matches)) {
 295                  $paramTypesTmp = $matches[1];
 296                  if (preg_match_all('/@param\s+\S+\s+(\$\S+)\s+(.*?)(@|\*\/)/s', $docBlock, $matches))
 297                  {
 298                      $paramDesc = $matches[2];
 299                      foreach ($paramDesc as $key => $value) {
 300                          $value = preg_replace('/\s?\*\s/m', '', $value);
 301                          $value = preg_replace('/\s{2,}/', ' ', $value);
 302                          $paramDesc[$key] = trim($value);
 303                      }
 304                  }
 305              }
 306          } else {
 307              $helpText = $function->getName();
 308              $return   = 'void';
 309          }
 310  
 311          // Set method description
 312          $this->setDescription($helpText);
 313  
 314          // Get all param types as arrays
 315          if (!isset($paramTypesTmp) && (0 < $paramCount)) {
 316              $paramTypesTmp = array_fill(0, $paramCount, 'mixed');
 317          } elseif (!isset($paramTypesTmp)) {
 318              $paramTypesTmp = array();
 319          } elseif (count($paramTypesTmp) < $paramCount) {
 320              $start = $paramCount - count($paramTypesTmp);
 321              for ($i = $start; $i < $paramCount; ++$i) {
 322                  $paramTypesTmp[$i] = 'mixed';
 323              }
 324          }
 325  
 326          // Get all param descriptions as arrays
 327          if (!isset($paramDesc) && (0 < $paramCount)) {
 328              $paramDesc = array_fill(0, $paramCount, '');
 329          } elseif (!isset($paramDesc)) {
 330              $paramDesc = array();
 331          } elseif (count($paramDesc) < $paramCount) {
 332              $start = $paramCount - count($paramDesc);
 333              for ($i = $start; $i < $paramCount; ++$i) {
 334                  $paramDesc[$i] = '';
 335              }
 336          }
 337  
 338          if (count($paramTypesTmp) != $paramCount) {
 339              require_once 'Zend/Server/Reflection/Exception.php';
 340              throw new Zend_Server_Reflection_Exception(
 341                 'Variable number of arguments is not supported for services (except optional parameters). '
 342               . 'Number of function arguments must correspond to actual number of arguments described in a docblock '
 343               . '(function was ' . $function->getName() . ')');
 344          }
 345  
 346          $paramTypes = array();
 347          foreach ($paramTypesTmp as $i => $param) {
 348              $tmp = explode('|', $param);
 349              if ($parameters[$i]->isOptional()) {
 350                  array_unshift($tmp, null);
 351              }
 352              $paramTypes[] = $tmp;
 353          }
 354  
 355          $this->_buildSignatures($return, $returnDesc, $paramTypes, $paramDesc);
 356      }
 357  
 358  
 359      /**
 360       * Proxy reflection calls
 361       *
 362       * @param string $method
 363       * @param array $args
 364       * @return mixed
 365       */
 366      public function __call($method, $args)
 367      {
 368          if (method_exists($this->_reflection, $method)) {
 369              return call_user_func_array(array($this->_reflection, $method), $args);
 370          }
 371  
 372          require_once 'Zend/Server/Reflection/Exception.php';
 373          throw new Zend_Server_Reflection_Exception('Invalid reflection method ("' .$method. '")');
 374      }
 375  
 376      /**
 377       * Retrieve configuration parameters
 378       *
 379       * Values are retrieved by key from {@link $_config}. Returns null if no
 380       * value found.
 381       *
 382       * @param string $key
 383       * @return mixed
 384       */
 385      public function __get($key)
 386      {
 387          if (isset($this->_config[$key])) {
 388              return $this->_config[$key];
 389          }
 390  
 391          return null;
 392      }
 393  
 394      /**
 395       * Set configuration parameters
 396       *
 397       * Values are stored by $key in {@link $_config}.
 398       *
 399       * @param string $key
 400       * @param mixed $value
 401       * @return void
 402       */
 403      public function __set($key, $value)
 404      {
 405          $this->_config[$key] = $value;
 406      }
 407  
 408      /**
 409       * Set method's namespace
 410       *
 411       * @param string $namespace
 412       * @return void
 413       */
 414      public function setNamespace($namespace)
 415      {
 416          if (empty($namespace)) {
 417              $this->_namespace = '';
 418              return;
 419          }
 420  
 421          if (!is_string($namespace) || !preg_match('/[a-z0-9_\.]+/i', $namespace)) {
 422              require_once 'Zend/Server/Reflection/Exception.php';
 423              throw new Zend_Server_Reflection_Exception('Invalid namespace');
 424          }
 425  
 426          $this->_namespace = $namespace;
 427      }
 428  
 429      /**
 430       * Return method's namespace
 431       *
 432       * @return string
 433       */
 434      public function getNamespace()
 435      {
 436          return $this->_namespace;
 437      }
 438  
 439      /**
 440       * Set the description
 441       *
 442       * @param string $string
 443       * @return void
 444       */
 445      public function setDescription($string)
 446      {
 447          if (!is_string($string)) {
 448              require_once 'Zend/Server/Reflection/Exception.php';
 449              throw new Zend_Server_Reflection_Exception('Invalid description');
 450          }
 451  
 452          $this->_description = $string;
 453      }
 454  
 455      /**
 456       * Retrieve the description
 457       *
 458       * @return void
 459       */
 460      public function getDescription()
 461      {
 462          return $this->_description;
 463      }
 464  
 465      /**
 466       * Retrieve all prototypes as array of
 467       * {@link Zend_Server_Reflection_Prototype Zend_Server_Reflection_Prototypes}
 468       *
 469       * @return array
 470       */
 471      public function getPrototypes()
 472      {
 473          return $this->_prototypes;
 474      }
 475  
 476      /**
 477       * Retrieve additional invocation arguments
 478       *
 479       * @return array
 480       */
 481      public function getInvokeArguments()
 482      {
 483          return $this->_argv;
 484      }
 485  
 486      /**
 487       * Wakeup from serialization
 488       *
 489       * Reflection needs explicit instantiation to work correctly. Re-instantiate
 490       * reflection object on wakeup.
 491       *
 492       * @return void
 493       */
 494      public function __wakeup()
 495      {
 496          if ($this->_reflection instanceof ReflectionMethod) {
 497              $class = new ReflectionClass($this->_class);
 498              $this->_reflection = new ReflectionMethod($class->newInstance(), $this->getName());
 499          } else {
 500              $this->_reflection = new ReflectionFunction($this->getName());
 501          }
 502      }
 503  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1