[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/zendframework/zend-code/src/Reflection/ -> MethodReflection.php (source)

   1  <?php
   2  /**
   3   * Zend Framework (http://framework.zend.com/)
   4   *
   5   * @link      http://github.com/zendframework/zf2 for the canonical source repository
   6   * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
   7   * @license   http://framework.zend.com/license/new-bsd New BSD License
   8   */
   9  
  10  namespace Zend\Code\Reflection;
  11  
  12  use ReflectionMethod as PhpReflectionMethod;
  13  use Zend\Code\Annotation\AnnotationManager;
  14  use Zend\Code\Scanner\AnnotationScanner;
  15  use Zend\Code\Scanner\CachingFileScanner;
  16  
  17  class MethodReflection extends PhpReflectionMethod implements ReflectionInterface
  18  {
  19      /**
  20       * Constant use in @MethodReflection to display prototype as an array
  21       */
  22      const PROTOTYPE_AS_ARRAY = 'prototype_as_array';
  23  
  24      /**
  25       * Constant use in @MethodReflection to display prototype as a string
  26       */
  27      const PROTOTYPE_AS_STRING = 'prototype_as_string';
  28  
  29      /**
  30       * @var AnnotationScanner
  31       */
  32      protected $annotations = null;
  33  
  34      /**
  35       * Retrieve method DocBlock reflection
  36       *
  37       * @return DocBlockReflection|false
  38       */
  39      public function getDocBlock()
  40      {
  41          if ('' == $this->getDocComment()) {
  42              return false;
  43          }
  44  
  45          $instance = new DocBlockReflection($this);
  46  
  47          return $instance;
  48      }
  49  
  50      /**
  51       * @param  AnnotationManager $annotationManager
  52       * @return AnnotationScanner
  53       */
  54      public function getAnnotations(AnnotationManager $annotationManager)
  55      {
  56          if (($docComment = $this->getDocComment()) == '') {
  57              return false;
  58          }
  59  
  60          if ($this->annotations) {
  61              return $this->annotations;
  62          }
  63  
  64          $cachingFileScanner = $this->createFileScanner($this->getFileName());
  65          $nameInformation    = $cachingFileScanner->getClassNameInformation($this->getDeclaringClass()->getName());
  66  
  67          if (!$nameInformation) {
  68              return false;
  69          }
  70  
  71          $this->annotations = new AnnotationScanner($annotationManager, $docComment, $nameInformation);
  72  
  73          return $this->annotations;
  74      }
  75  
  76      /**
  77       * Get start line (position) of method
  78       *
  79       * @param  bool $includeDocComment
  80       * @return int
  81       */
  82      public function getStartLine($includeDocComment = false)
  83      {
  84          if ($includeDocComment) {
  85              if ($this->getDocComment() != '') {
  86                  return $this->getDocBlock()->getStartLine();
  87              }
  88          }
  89  
  90          return parent::getStartLine();
  91      }
  92  
  93      /**
  94       * Get reflection of declaring class
  95       *
  96       * @return ClassReflection
  97       */
  98      public function getDeclaringClass()
  99      {
 100          $phpReflection  = parent::getDeclaringClass();
 101          $zendReflection = new ClassReflection($phpReflection->getName());
 102          unset($phpReflection);
 103  
 104          return $zendReflection;
 105      }
 106  
 107      /**
 108       * Get method prototype
 109       *
 110       * @return array
 111       */
 112      public function getPrototype($format = MethodReflection::PROTOTYPE_AS_ARRAY)
 113      {
 114          $returnType = 'mixed';
 115          $docBlock = $this->getDocBlock();
 116          if ($docBlock) {
 117              $return = $docBlock->getTag('return');
 118              $returnTypes = $return->getTypes();
 119              $returnType = count($returnTypes) > 1 ? implode('|', $returnTypes) : $returnTypes[0];
 120          }
 121  
 122          $declaringClass = $this->getDeclaringClass();
 123          $prototype = array(
 124              'namespace'  => $declaringClass->getNamespaceName(),
 125              'class'      => substr($declaringClass->getName(), strlen($declaringClass->getNamespaceName()) + 1),
 126              'name'       => $this->getName(),
 127              'visibility' => ($this->isPublic() ? 'public' : ($this->isPrivate() ? 'private' : 'protected')),
 128              'return'     => $returnType,
 129              'arguments'  => array(),
 130          );
 131  
 132          $parameters = $this->getParameters();
 133          foreach ($parameters as $parameter) {
 134              $prototype['arguments'][$parameter->getName()] = array(
 135                  'type'     => $parameter->getType(),
 136                  'required' => !$parameter->isOptional(),
 137                  'by_ref'   => $parameter->isPassedByReference(),
 138                  'default'  => $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null,
 139              );
 140          }
 141  
 142          if ($format == MethodReflection::PROTOTYPE_AS_STRING) {
 143              $line = $prototype['visibility'] . ' ' . $prototype['return'] . ' ' . $prototype['name'] . '(';
 144              $args = array();
 145              foreach ($prototype['arguments'] as $name => $argument) {
 146                  $argsLine = ($argument['type'] ? $argument['type'] . ' ' : '') . ($argument['by_ref'] ? '&' : '') . '$' . $name;
 147                  if (!$argument['required']) {
 148                      $argsLine .= ' = ' . var_export($argument['default'], true);
 149                  }
 150                  $args[] = $argsLine;
 151              }
 152              $line .= implode(', ', $args);
 153              $line .= ')';
 154  
 155              return $line;
 156          }
 157  
 158          return $prototype;
 159      }
 160  
 161      /**
 162       * Get all method parameter reflection objects
 163       *
 164       * @return ParameterReflection[]
 165       */
 166      public function getParameters()
 167      {
 168          $phpReflections  = parent::getParameters();
 169          $zendReflections = array();
 170          while ($phpReflections && ($phpReflection = array_shift($phpReflections))) {
 171              $instance = new ParameterReflection(
 172                  array($this->getDeclaringClass()->getName(), $this->getName()),
 173                  $phpReflection->getName()
 174              );
 175              $zendReflections[] = $instance;
 176              unset($phpReflection);
 177          }
 178          unset($phpReflections);
 179  
 180          return $zendReflections;
 181      }
 182  
 183      /**
 184       * Get method contents
 185       *
 186       * @param  bool $includeDocBlock
 187       * @return string
 188       */
 189      public function getContents($includeDocBlock = true)
 190      {
 191          $docComment = $this->getDocComment();
 192          $content  = ($includeDocBlock && !empty($docComment)) ? $docComment . "\n" : '';
 193          $content .= $this->extractMethodContents();
 194  
 195          return $content;
 196      }
 197  
 198      /**
 199       * Get method body
 200       *
 201       * @return string
 202       */
 203      public function getBody()
 204      {
 205          return $this->extractMethodContents(true);
 206      }
 207  
 208      /**
 209       * Tokenize method string and return concatenated body
 210       *
 211       * @param bool $bodyOnly
 212       * @return string
 213       */
 214      protected function extractMethodContents($bodyOnly = false)
 215      {
 216          $fileName = $this->getFileName();
 217  
 218          if ((class_exists($this->class) && false === $fileName) || ! file_exists($fileName)) {
 219              return '';
 220          }
 221  
 222          $lines = array_slice(
 223              file($fileName, FILE_IGNORE_NEW_LINES),
 224              $this->getStartLine() - 1,
 225              ($this->getEndLine() - ($this->getStartLine() - 1)),
 226              true
 227          );
 228  
 229          $functionLine = implode("\n", $lines);
 230          $tokens = token_get_all("<?php ". $functionLine);
 231  
 232          //remove first entry which is php open tag
 233          array_shift($tokens);
 234  
 235          if (!count($tokens)) {
 236              return '';
 237          }
 238  
 239          $capture = false;
 240          $firstBrace = false;
 241          $body = '';
 242  
 243          foreach ($tokens as $key => $token) {
 244              $tokenType  = (is_array($token)) ? token_name($token[0]) : $token;
 245              $tokenValue = (is_array($token)) ? $token[1] : $token;
 246  
 247              switch ($tokenType) {
 248                  case "T_FINAL":
 249                  case "T_ABSTRACT":
 250                  case "T_PUBLIC":
 251                  case "T_PROTECTED":
 252                  case "T_PRIVATE":
 253                  case "T_STATIC":
 254                  case "T_FUNCTION":
 255                      // check to see if we have a valid function
 256                      // then check if we are inside function and have a closure
 257                      if ($this->isValidFunction($tokens, $key, $this->getName())) {
 258                          if ($bodyOnly === false) {
 259                              //if first instance of tokenType grab prefixed whitespace
 260                              //and append to body
 261                              if ($capture === false) {
 262                                  $body .= $this->extractPrefixedWhitespace($tokens, $key);
 263                              }
 264                              $body .= $tokenValue;
 265                          }
 266  
 267                          $capture = true;
 268                      } else {
 269                          //closure test
 270                          if ($firstBrace && $tokenType == "T_FUNCTION") {
 271                              $body .= $tokenValue;
 272                              continue;
 273                          }
 274                          $capture = false;
 275                          continue;
 276                      }
 277                      break;
 278  
 279                  case "{":
 280                      if ($capture === false) {
 281                          continue;
 282                      }
 283  
 284                      if ($firstBrace === false) {
 285                          $firstBrace = true;
 286                          if ($bodyOnly === true) {
 287                              continue;
 288                          }
 289                      }
 290  
 291                      $body .= $tokenValue;
 292                      break;
 293  
 294                  case "}":
 295                      if ($capture === false) {
 296                          continue;
 297                      }
 298  
 299                      //check to see if this is the last brace
 300                      if ($this->isEndingBrace($tokens, $key)) {
 301                          //capture the end brace if not bodyOnly
 302                          if ($bodyOnly === false) {
 303                              $body .= $tokenValue;
 304                          }
 305  
 306                          break 2;
 307                      }
 308  
 309                      $body .= $tokenValue;
 310                      break;
 311  
 312                  default:
 313                      if ($capture === false) {
 314                          continue;
 315                      }
 316  
 317                      // if returning body only wait for first brace before capturing
 318                      if ($bodyOnly === true && $firstBrace !== true) {
 319                          continue;
 320                      }
 321  
 322                      $body .= $tokenValue;
 323                      break;
 324              }
 325          }
 326  
 327          //remove ending whitespace and return
 328          return rtrim($body);
 329      }
 330  
 331      /**
 332       * Take current position and find any whitespace
 333       *
 334       * @param array $haystack
 335       * @param int $position
 336       * @return string
 337       */
 338      protected function extractPrefixedWhitespace($haystack, $position)
 339      {
 340          $content = '';
 341          $count = count($haystack);
 342          if ($position+1 == $count) {
 343              return $content;
 344          }
 345  
 346          for ($i = $position-1;$i >= 0;$i--) {
 347              $tokenType = (is_array($haystack[$i])) ? token_name($haystack[$i][0]) : $haystack[$i];
 348              $tokenValue = (is_array($haystack[$i])) ? $haystack[$i][1] : $haystack[$i];
 349  
 350              //search only for whitespace
 351              if ($tokenType == "T_WHITESPACE") {
 352                  $content .= $tokenValue;
 353              } else {
 354                  break;
 355              }
 356          }
 357  
 358          return $content;
 359      }
 360  
 361      /**
 362       * Test for ending brace
 363       *
 364       * @param array $haystack
 365       * @param int $position
 366       * @return bool
 367       */
 368      protected function isEndingBrace($haystack, $position)
 369      {
 370          $count = count($haystack);
 371  
 372          //advance one position
 373          $position = $position+1;
 374  
 375          if ($position == $count) {
 376              return true;
 377          }
 378  
 379          for ($i = $position;$i < $count; $i++) {
 380              $tokenType = (is_array($haystack[$i])) ? token_name($haystack[$i][0]) : $haystack[$i];
 381              switch ($tokenType) {
 382                  case "T_FINAL":
 383                  case "T_ABSTRACT":
 384                  case "T_PUBLIC":
 385                  case "T_PROTECTED":
 386                  case "T_PRIVATE":
 387                  case "T_STATIC":
 388                      return true;
 389  
 390                  case "T_FUNCTION":
 391                      // If a function is encountered and that function is not a closure
 392                      // then return true.  otherwise the function is a closure, return false
 393                      if ($this->isValidFunction($haystack, $i)) {
 394                          return true;
 395                      }
 396                      return false;
 397  
 398                  case "}":
 399                  case ";";
 400                  case "T_BREAK":
 401                  case "T_CATCH":
 402                  case "T_DO":
 403                  case "T_ECHO":
 404                  case "T_ELSE":
 405                  case "T_ELSEIF":
 406                  case "T_EVAL":
 407                  case "T_EXIT":
 408                  case "T_FINALLY":
 409                  case "T_FOR":
 410                  case "T_FOREACH":
 411                  case "T_GOTO":
 412                  case "T_IF":
 413                  case "T_INCLUDE":
 414                  case "T_INCLUDE_ONCE":
 415                  case "T_PRINT":
 416                  case "T_STRING":
 417                  case "T_STRING_VARNAME":
 418                  case "T_THROW":
 419                  case "T_USE":
 420                  case "T_VARIABLE":
 421                  case "T_WHILE":
 422                  case "T_YIELD":
 423  
 424                      return false;
 425              }
 426          }
 427      }
 428  
 429      /**
 430       * Test to see if current position is valid function or
 431       * closure.  Returns true if it's a function and NOT a closure
 432       *
 433       * @param array $haystack
 434       * @param int $position
 435       * @param string $functionName
 436       * @return bool
 437       */
 438      protected function isValidFunction($haystack, $position, $functionName = null)
 439      {
 440          $isValid = false;
 441          $count = count($haystack);
 442          for ($i = $position+1; $i < $count; $i++) {
 443              $tokenType = (is_array($haystack[$i])) ? token_name($haystack[$i][0]) : $haystack[$i];
 444              $tokenValue = (is_array($haystack[$i])) ? $haystack[$i][1] : $haystack[$i];
 445  
 446              //check for occurance of ( or
 447              if ($tokenType == "T_STRING") {
 448                  //check to see if function name is passed, if so validate against that
 449                  if ($functionName !== null && $tokenValue != $functionName) {
 450                      $isValid = false;
 451                      break;
 452                  }
 453  
 454                  $isValid = true;
 455                  break;
 456              } elseif ($tokenValue == "(") {
 457                  break;
 458              }
 459          }
 460  
 461          return $isValid;
 462      }
 463  
 464      /**
 465       * @return string
 466       */
 467      public function toString()
 468      {
 469          return parent::__toString();
 470      }
 471  
 472      /**
 473       * @return string
 474       */
 475      public function __toString()
 476      {
 477          return parent::__toString();
 478      }
 479  
 480      /**
 481       * Creates a new FileScanner instance.
 482       *
 483       * By having this as a seperate method it allows the method to be overridden
 484       * if a different FileScanner is needed.
 485       *
 486       * @param  string $filename
 487       *
 488       * @return CachingFileScanner
 489       */
 490      protected function createFileScanner($filename)
 491      {
 492          return new CachingFileScanner($filename);
 493      }
 494  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1