Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

MethodReflection.php

Zuletzt modifiziert: 09.10.2024, 12:57 - Dateigröße: 14.50 KiB


 001  <?php
 002  /**
 003   * Zend Framework (http://framework.zend.com/)
 004   *
 005   * @link      http://github.com/zendframework/zf2 for the canonical source repository
 006   * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
 007   * @license   http://framework.zend.com/license/new-bsd New BSD License
 008   */
 009   
 010  namespace Zend\Code\Reflection;
 011   
 012  use ReflectionMethod as PhpReflectionMethod;
 013  use Zend\Code\Annotation\AnnotationManager;
 014  use Zend\Code\Scanner\AnnotationScanner;
 015  use Zend\Code\Scanner\CachingFileScanner;
 016   
 017  class MethodReflection extends PhpReflectionMethod implements ReflectionInterface
 018  {
 019      /**
 020       * Constant use in @MethodReflection to display prototype as an array
 021       */
 022      const PROTOTYPE_AS_ARRAY = 'prototype_as_array';
 023   
 024      /**
 025       * Constant use in @MethodReflection to display prototype as a string
 026       */
 027      const PROTOTYPE_AS_STRING = 'prototype_as_string';
 028   
 029      /**
 030       * @var AnnotationScanner
 031       */
 032      protected $annotations = null;
 033   
 034      /**
 035       * Retrieve method DocBlock reflection
 036       *
 037       * @return DocBlockReflection|false
 038       */
 039      public function getDocBlock()
 040      {
 041          if ('' == $this->getDocComment()) {
 042              return false;
 043          }
 044   
 045          $instance = new DocBlockReflection($this);
 046   
 047          return $instance;
 048      }
 049   
 050      /**
 051       * @param  AnnotationManager $annotationManager
 052       * @return AnnotationScanner
 053       */
 054      public function getAnnotations(AnnotationManager $annotationManager)
 055      {
 056          if (($docComment = $this->getDocComment()) == '') {
 057              return false;
 058          }
 059   
 060          if ($this->annotations) {
 061              return $this->annotations;
 062          }
 063   
 064          $cachingFileScanner = $this->createFileScanner($this->getFileName());
 065          $nameInformation    = $cachingFileScanner->getClassNameInformation($this->getDeclaringClass()->getName());
 066   
 067          if (!$nameInformation) {
 068              return false;
 069          }
 070   
 071          $this->annotations = new AnnotationScanner($annotationManager, $docComment, $nameInformation);
 072   
 073          return $this->annotations;
 074      }
 075   
 076      /**
 077       * Get start line (position) of method
 078       *
 079       * @param  bool $includeDocComment
 080       * @return int
 081       */
 082      public function getStartLine($includeDocComment = false)
 083      {
 084          if ($includeDocComment) {
 085              if ($this->getDocComment() != '') {
 086                  return $this->getDocBlock()->getStartLine();
 087              }
 088          }
 089   
 090          return parent::getStartLine();
 091      }
 092   
 093      /**
 094       * Get reflection of declaring class
 095       *
 096       * @return ClassReflection
 097       */
 098      public function getDeclaringClass()
 099      {
 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  }
 495