[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |