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