Overview

Namespaces

  • TokenReflection
    • Broker
      • Backend
    • Dummy
    • Exception
    • Invalid
    • Php
    • Stream

Classes

  • Broker
  • ReflectionAnnotation
  • ReflectionBase
  • ReflectionClass
  • ReflectionConstant
  • ReflectionElement
  • ReflectionFile
  • ReflectionFileNamespace
  • ReflectionFunction
  • ReflectionFunctionBase
  • ReflectionMethod
  • ReflectionNamespace
  • ReflectionParameter
  • ReflectionProperty
  • Resolver

Interfaces

  • IReflection
  • IReflectionClass
  • IReflectionConstant
  • IReflectionExtension
  • IReflectionFunction
  • IReflectionFunctionBase
  • IReflectionMethod
  • IReflectionNamespace
  • IReflectionParameter
  • IReflectionProperty
  • Overview
  • Namespace
  • Class
  • Tree
  • Download
  1: <?php
  2: /**
  3:  * PHP Token Reflection
  4:  *
  5:  * Version 1.3.1
  6:  *
  7:  * LICENSE
  8:  *
  9:  * This source file is subject to the new BSD license that is bundled
 10:  * with this library in the file LICENSE.
 11:  *
 12:  * @author Ondřej Nešpor
 13:  * @author Jaroslav Hanslík
 14:  */
 15: 
 16: namespace TokenReflection;
 17: 
 18: use TokenReflection\Exception, TokenReflection\Stream\StreamBase as Stream;
 19: use ReflectionMethod as InternalReflectionMethod, ReflectionClass as InternalReflectionClass;
 20: 
 21: /**
 22:  * Tokenized class method reflection.
 23:  */
 24: class ReflectionMethod extends ReflectionFunctionBase implements IReflectionMethod
 25: {
 26:     /**
 27:      * An implemented abstract method.
 28:      *
 29:      * @see http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend_compile.h?revision=306939&view=markup#l114
 30:      * ZEND_ACC_IMPLICIT_PUBLIC
 31:      *
 32:      * @var integer
 33:      */
 34:     const IS_IMPLEMENTED_ABSTRACT = 0x08;
 35: 
 36:     /**
 37:      * Access level of this method has changed from the original implementation.
 38:      *
 39:      * @see http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend_compile.h?revision=306939&view=markup#l134
 40:      * ZEND_ACC_CHANGED
 41:      *
 42:      * @var integer
 43:      */
 44:     const ACCESS_LEVEL_CHANGED = 0x800;
 45: 
 46:     /**
 47:      * Method is constructor.
 48:      *
 49:      * Legacy constructors are not supported.
 50:      *
 51:      * @see http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend_compile.h?revision=306939&view=markup#l138
 52:      * ZEND_ACC_CTOR
 53:      *
 54:      * @var integer
 55:      */
 56:     const IS_CONSTRUCTOR = 0x2000;
 57: 
 58:     /**
 59:      * Method is destructor.
 60:      *
 61:      * @see http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend_compile.h?revision=306939&view=markup#l139
 62:      * ZEND_ACC_DTOR
 63:      *
 64:      * @var integer
 65:      */
 66:     const IS_DESTRUCTOR = 0x4000;
 67: 
 68:     /**
 69:      * Method is __clone().
 70:      *
 71:      * @see http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend_compile.h?revision=306939&view=markup#l140
 72:      * ZEND_ACC_CLONE
 73:      *
 74:      * @var integer
 75:      */
 76:     const IS_CLONE = 0x8000;
 77: 
 78:     /**
 79:      * Method can be called statically (although not defined static).
 80:      *
 81:      * @see http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend_compile.h?revision=306939&view=markup#l143
 82:      * ZEND_ACC_ALLOW_STATIC
 83:      *
 84:      * @var integer
 85:      */
 86:     const IS_ALLOWED_STATIC = 0x10000;
 87: 
 88:     /**
 89:      * Declaring class name.
 90:      *
 91:      * @var string
 92:      */
 93:     private $declaringClassName;
 94: 
 95:     /**
 96:      * Method prototype reflection.
 97:      *
 98:      * @var \TokenReflection\IReflectionMethod
 99:      */
100:     private $prototype;
101: 
102:     /**
103:      * Method modifiers.
104:      *
105:      * @var integer
106:      */
107:     protected $modifiers = 0;
108: 
109:     /**
110:      * Determined if the method is accessible.
111:      *
112:      * @var boolean
113:      */
114:     private $accessible = false;
115: 
116:     /**
117:      * Determines if modifiers are complete.
118:      *
119:      * @var boolean
120:      */
121:     private $modifiersComplete = false;
122: 
123:     /**
124:      * The original name when importing from a trait.
125:      *
126:      * @var string|null
127:      */
128:     private $originalName = null;
129: 
130:     /**
131:      * The original method when importing from a trait.
132:      *
133:      * @var \TokenReflection\IReflectionMethod|null
134:      */
135:     private $original = null;
136: 
137:     /**
138:      * The original modifiers value when importing from a trait.
139:      *
140:      * @var integer|null
141:      */
142:     private $originalModifiers = null;
143: 
144:     /**
145:      * Declaring trait name.
146:      *
147:      * @var string
148:      */
149:     private $declaringTraitName;
150: 
151:     /**
152:      * Returns the declaring class reflection.
153:      *
154:      * @return \TokenReflection\ReflectionClass|null
155:      */
156:     public function getDeclaringClass()
157:     {
158:         return null === $this->declaringClassName ? null : $this->getBroker()->getClass($this->declaringClassName);
159:     }
160: 
161:     /**
162:      * Returns the declaring class name.
163:      *
164:      * @return string|null
165:      */
166:     public function getDeclaringClassName()
167:     {
168:         return $this->declaringClassName;
169:     }
170: 
171:     /**
172:      * Returns method modifiers.
173:      *
174:      * @return integer
175:      */
176:     public function getModifiers()
177:     {
178:         if (!$this->modifiersComplete && !($this->modifiers & (self::ACCESS_LEVEL_CHANGED | self::IS_IMPLEMENTED_ABSTRACT))) {
179:             $declaringClass = $this->getDeclaringClass();
180:             $parentClass = $declaringClass->getParentClass();
181:             if (false !== $parentClass && $parentClass->hasMethod($this->name)) {
182:                 $parentClassMethod = $parentClass->getMethod($this->name);
183: 
184:                 // Access level changed
185:                 if (($this->isPublic() || $this->isProtected()) && $parentClassMethod->is(self::ACCESS_LEVEL_CHANGED | InternalReflectionMethod::IS_PRIVATE)) {
186:                     $this->modifiers |= self::ACCESS_LEVEL_CHANGED;
187:                 }
188: 
189:                 // Implemented abstract
190:                 if ($parentClassMethod->isAbstract() && !$this->isAbstract()) {
191:                     $this->modifiers |= self::IS_IMPLEMENTED_ABSTRACT;
192:                 }
193:             } else {
194:                 // Check if it is an implementation of an interface method
195:                 foreach ($declaringClass->getInterfaces() as $interface) {
196:                     if ($interface->hasOwnMethod($this->name)) {
197:                         $this->modifiers |= self::IS_IMPLEMENTED_ABSTRACT;
198:                         break;
199:                     }
200:                 }
201:             }
202: 
203:             // Set if modifiers definition is complete
204:             $this->modifiersComplete = $this->isComplete() || (($this->modifiers & self::IS_IMPLEMENTED_ABSTRACT) && ($this->modifiers & self::ACCESS_LEVEL_CHANGED));
205:         }
206: 
207:         return $this->modifiers;
208:     }
209: 
210:     /**
211:      * Returns if the method is abstract.
212:      *
213:      * @return boolean
214:      */
215:     public function isAbstract()
216:     {
217:         return (bool) ($this->modifiers & InternalReflectionMethod::IS_ABSTRACT);
218:     }
219: 
220:     /**
221:      * Returns if the method is final.
222:      *
223:      * @return boolean
224:      */
225:     public function isFinal()
226:     {
227:         return (bool) ($this->modifiers & InternalReflectionMethod::IS_FINAL);
228:     }
229: 
230:     /**
231:      * Returns if the method is private.
232:      *
233:      * @return boolean
234:      */
235:     public function isPrivate()
236:     {
237:         return (bool) ($this->modifiers & InternalReflectionMethod::IS_PRIVATE);
238:     }
239: 
240:     /**
241:      * Returns if the method is protected.
242:      *
243:      * @return boolean
244:      */
245:     public function isProtected()
246:     {
247:         return (bool) ($this->modifiers & InternalReflectionMethod::IS_PROTECTED);
248:     }
249: 
250:     /**
251:      * Returns if the method is public.
252:      *
253:      * @return boolean
254:      */
255:     public function isPublic()
256:     {
257:         return (bool) ($this->modifiers & InternalReflectionMethod::IS_PUBLIC);
258:     }
259: 
260:     /**
261:      * Returns if the method is static.
262:      *
263:      * @return boolean
264:      */
265:     public function isStatic()
266:     {
267:         return (bool) ($this->modifiers & InternalReflectionMethod::IS_STATIC);
268:     }
269: 
270:     /**
271:      * Shortcut for isPublic(), ... methods that allows or-ed modifiers.
272:      *
273:      * The {@see getModifiers()} method is called only when really necessary making this
274:      * a more efficient way of doing
275:      * <code>
276:      *     if ($method->getModifiers() & $filter) {
277:      *        ...
278:      *     }
279:      * </code>
280:      *
281:      * @param integer $filter Filter
282:      * @return boolean
283:      */
284:     public function is($filter = null)
285:     {
286:         // See self::ACCESS_LEVEL_CHANGED | self::IS_IMPLEMENTED_ABSTRACT
287:         static $computedModifiers = 0x808;
288: 
289:         if (null === $filter || ($this->modifiers & $filter)) {
290:             return true;
291:         } elseif (($filter & $computedModifiers) && !$this->modifiersComplete) {
292:             return (bool) ($this->getModifiers() & $filter);
293:         }
294: 
295:         return false;
296:     }
297: 
298:     /**
299:      * Returns if the method is a constructor.
300:      *
301:      * @return boolean
302:      */
303:     public function isConstructor()
304:     {
305:         return (bool) ($this->modifiers & self::IS_CONSTRUCTOR);
306:     }
307: 
308:     /**
309:      * Returns if the method is a destructor.
310:      *
311:      * @return boolean
312:      */
313:     public function isDestructor()
314:     {
315:         return (bool) ($this->modifiers & self::IS_DESTRUCTOR);
316:     }
317: 
318:     /**
319:      * Returns the method prototype.
320:      *
321:      * @return \TokenReflection\ReflectionMethod
322:      * @throws \TokenReflection\Exception\RuntimeException If the method has no prototype.
323:      */
324:     public function getPrototype()
325:     {
326:         if (null === $this->prototype) {
327:             $prototype = null;
328: 
329:             $declaring = $this->getDeclaringClass();
330:             if (($parent = $declaring->getParentClass()) && $parent->hasMethod($this->name)) {
331:                 $method = $parent->getMethod($this->name);
332: 
333:                 if (!$method->isPrivate()) {
334:                     try {
335:                         $prototype = $method->getPrototype();
336:                     } catch (Exception\RuntimeException $e) {
337:                         $prototype = $method;
338:                     }
339:                 }
340:             }
341: 
342:             if (null === $prototype) {
343:                 foreach ($declaring->getOwnInterfaces() as $interface) {
344:                     if ($interface->hasMethod($this->name)) {
345:                         $prototype = $interface->getMethod($this->name);
346:                         break;
347:                     }
348:                 }
349:             }
350: 
351:             $this->prototype = $prototype ?: ($this->isComplete() ? false : null);
352:         }
353: 
354:         if (empty($this->prototype)) {
355:             throw new Exception\RuntimeException('Method has no prototype.', Exception\RuntimeException::DOES_NOT_EXIST, $this);
356:         }
357: 
358:         return $this->prototype;
359:     }
360: 
361:     /**
362:      * Returns an element pretty (docblock compatible) name.
363:      *
364:      * @return string
365:      */
366:     public function getPrettyName()
367:     {
368:         return sprintf('%s::%s', $this->declaringClassName ?: $this->declaringTraitName, parent::getPrettyName());
369:     }
370: 
371:     /**
372:      * Returns the string representation of the reflection object.
373:      *
374:      * @return string
375:      */
376:     public function __toString()
377:     {
378:         $internal = '';
379:         $overwrite = '';
380:         $prototype = '';
381: 
382:         $declaringClassParent = $this->getDeclaringClass()->getParentClass();
383:         try {
384:             $prototype = ', prototype ' . $this->getPrototype()->getDeclaringClassName();
385:         } catch (Exception\RuntimeException $e) {
386:             if ($declaringClassParent && $declaringClassParent->isInternal()) {
387:                 $internal = 'internal:' . $parentClass->getExtensionName();
388:             }
389:         }
390: 
391:         if ($declaringClassParent && $declaringClassParent->hasMethod($this->name)) {
392:             $parentMethod = $declaringClassParent->getMethod($this->name);
393:             $overwrite = ', overwrites ' . $parentMethod->getDeclaringClassName();
394:         }
395: 
396:         if ($this->isConstructor()) {
397:             $cdtor = ', ctor';
398:         } elseif ($this->isDestructor()) {
399:             $cdtor = ', dtor';
400:         } else {
401:             $cdtor = '';
402:         }
403: 
404:         $parameters = '';
405:         if ($this->getNumberOfParameters() > 0) {
406:             $buffer = '';
407:             foreach ($this->getParameters() as $parameter) {
408:                 $buffer .= "\n    " . $parameter->__toString();
409:             }
410:             $parameters = sprintf(
411:                 "\n\n  - Parameters [%d] {%s\n  }",
412:                 $this->getNumberOfParameters(),
413:                 $buffer
414:             );
415:         }
416:         // @todo support inherits
417:         return sprintf(
418:             "%sMethod [ <%s%s%s%s> %s%s%s%s%s%s method %s%s ] {\n  @@ %s %d - %d%s\n}\n",
419:             $this->getDocComment() ? $this->getDocComment() . "\n" : '',
420:             !empty($internal) ? $internal : 'user',
421:             $overwrite,
422:             $prototype,
423:             $cdtor,
424:             $this->isAbstract() ? 'abstract ' : '',
425:             $this->isFinal() ? 'final ' : '',
426:             $this->isStatic() ? 'static ' : '',
427:             $this->isPublic() ? 'public' : '',
428:             $this->isPrivate() ? 'private' : '',
429:             $this->isProtected() ? 'protected' : '',
430:             $this->returnsReference() ? '&' : '',
431:             $this->getName(),
432:             $this->getFileName(),
433:             $this->getStartLine(),
434:             $this->getEndLine(),
435:             $parameters
436:         );
437:     }
438: 
439:     /**
440:      * Exports a reflected object.
441:      *
442:      * @param \TokenReflection\Broker $broker Broker instance
443:      * @param string|object $class Class name or class instance
444:      * @param string $method Method name
445:      * @param boolean $return Return the export instead of outputting it
446:      * @return string|null
447:      * @throws \TokenReflection\Exception\RuntimeException If requested parameter doesn't exist.
448:      */
449:     public static function export(Broker $broker, $class, $method, $return = false)
450:     {
451:         $className = is_object($class) ? get_class($class) : $class;
452:         $methodName = $method;
453: 
454:         $class = $broker->getClass($className);
455:         if ($class instanceof Invalid\ReflectionClass) {
456:             throw new Exception\RuntimeException('Class is invalid.', Exception\RuntimeException::UNSUPPORTED);
457:         } elseif ($class instanceof Dummy\ReflectionClass) {
458:             throw new Exception\RuntimeException(sprintf('Class %s does not exist.', $className), Exception\RuntimeException::DOES_NOT_EXIST);
459:         }
460:         $method = $class->getMethod($methodName);
461: 
462:         if ($return) {
463:             return $method->__toString();
464:         }
465: 
466:         echo $method->__toString();
467:     }
468: 
469:     /**
470:      * Calls the method on an given instance.
471:      *
472:      * @param object $object Class instance
473:      * @param mixed $args
474:      * @return mixed
475:      */
476:     public function invoke($object, $args)
477:     {
478:         $params = func_get_args();
479:         return $this->invokeArgs(array_shift($params), $params);
480:     }
481: 
482:     /**
483:      * Calls the method on an given object.
484:      *
485:      * @param object $object Class instance
486:      * @param array $args Method parameter values
487:      * @return mixed
488:      * @throws \TokenReflection\Exception\RuntimeException If it is not possible to invoke the method.
489:      */
490:     public function invokeArgs($object, array $args = array())
491:     {
492:         $declaringClass = $this->getDeclaringClass();
493:         if (!$declaringClass->isInstance($object)) {
494:             throw new Exception\RuntimeException(sprintf('Expected instance of or subclass of "%s".', $this->declaringClassName), Exception\RuntimeException::INVALID_ARGUMENT, $this);
495:         }
496: 
497:         if ($this->isPublic()) {
498:             return call_user_func_array(array($object, $this->getName()), $args);
499:         } elseif ($this->isAccessible()) {
500:             $refClass = new InternalReflectionClass($object);
501:             $refMethod = $refClass->getMethod($this->name);
502: 
503:             $refMethod->setAccessible(true);
504:             $value = $refMethod->invokeArgs($object, $args);
505:             $refMethod->setAccessible(false);
506: 
507:             return $value;
508:         }
509: 
510:         throw new Exception\RuntimeException('Only public methods can be invoked.', Exception\RuntimeException::NOT_ACCESSBILE, $this);
511:     }
512: 
513:     /**
514:      * Returns if the property is set accessible.
515:      *
516:      * @return boolean
517:      */
518:     public function isAccessible()
519:     {
520:         return $this->accessible;
521:     }
522: 
523:     /**
524:      * Sets a method to be accessible or not.
525:      *
526:      * @param boolean $accessible
527:      */
528:     public function setAccessible($accessible)
529:     {
530:         $this->accessible = (bool) $accessible;
531:     }
532: 
533:     /**
534:      * Returns if the definition is complete.
535:      *
536:      * Technically returns if the declaring class definition is complete.
537:      *
538:      * @return boolean
539:      */
540:     private function isComplete()
541:     {
542:         return $this->getDeclaringClass()->isComplete();
543:     }
544: 
545:     /**
546:      * Returns imported namespaces and aliases from the declaring namespace.
547:      *
548:      * @return array
549:      */
550:     public function getNamespaceAliases()
551:     {
552:         return $this->getDeclaringClass()->getNamespaceAliases();
553:     }
554: 
555:     /**
556:      * Returns the function/method as closure.
557:      *
558:      * @param object $object Object
559:      * @return \Closure
560:      */
561:     public function getClosure($object)
562:     {
563:         $declaringClass = $this->getDeclaringClass();
564:         if (!$declaringClass->isInstance($object)) {
565:             throw new Exception\RuntimeException(sprintf('Expected instance of or subclass of "%s".', $this->declaringClassName), Exception\RuntimeException::INVALID_ARGUMENT, $this);
566:         }
567: 
568:         $that = $this;
569:         return function() use ($object, $that) {
570:             return $that->invokeArgs($object, func_get_args());
571:         };
572:     }
573: 
574:     /**
575:      * Creates a method alias of the given name and access level for the given class.
576:      *
577:      * @param \TokenReflection\ReflectionClass $parent New parent class
578:      * @param string $name New method name
579:      * @param integer $accessLevel New access level
580:      * @return \TokenReflection\ReflectionMethod
581:      * @throws \TokenReflection\Exception\RuntimeException If an invalid method access level was found.
582:      */
583:     public function alias(ReflectionClass $parent, $name = null, $accessLevel = null)
584:     {
585:         static $possibleLevels = array(InternalReflectionMethod::IS_PUBLIC => true, InternalReflectionMethod::IS_PROTECTED => true, InternalReflectionMethod::IS_PRIVATE => true);
586: 
587:         $method = clone $this;
588: 
589:         $method->declaringClassName = $parent->getName();
590:         if (null !== $name) {
591:             $method->originalName = $this->name;
592:             $method->name = $name;
593:         }
594:         if (null !== $accessLevel) {
595:             if (!isset($possibleLevels[$accessLevel])) {
596:                 throw new Exception\RuntimeException(sprintf('Invalid method access level: "%s".', $accessLevel), Exception\RuntimeException::INVALID_ARGUMENT, $this);
597:             }
598: 
599:             $method->modifiers &= ~(InternalReflectionMethod::IS_PUBLIC | InternalReflectionMethod::IS_PROTECTED | InternalReflectionMethod::IS_PRIVATE);
600:             $method->modifiers |= $accessLevel;
601: 
602:             $method->originalModifiers = $this->getModifiers();
603:         }
604: 
605:         foreach ($this->parameters as $parameterName => $parameter) {
606:             $method->parameters[$parameterName] = $parameter->alias($method);
607:         }
608: 
609:         return $method;
610:     }
611: 
612:     /**
613:      * Returns the original name when importing from a trait.
614:      *
615:      * @return string|null
616:      */
617:     public function getOriginalName()
618:     {
619:         return $this->originalName;
620:     }
621: 
622:     /**
623:      * Returns the original method when importing from a trait.
624:      *
625:      * @return \TokenReflection\IReflectionMethod|null
626:      */
627:     public function getOriginal()
628:     {
629:         return $this->original;
630:     }
631: 
632:     /**
633:      * Returns the original modifiers value when importing from a trait.
634:      *
635:      * @return integer|null
636:      */
637:     public function getOriginalModifiers()
638:     {
639:         return $this->originalModifiers;
640:     }
641: 
642:     /**
643:      * Returns the defining trait.
644:      *
645:      * @return \TokenReflection\IReflectionClass|null
646:      */
647:     public function getDeclaringTrait()
648:     {
649:         return null === $this->declaringTraitName ? null : $this->getBroker()->getClass($this->declaringTraitName);
650:     }
651: 
652:     /**
653:      * Returns the declaring trait name.
654:      *
655:      * @return string|null
656:      */
657:     public function getDeclaringTraitName()
658:     {
659:         return $this->declaringTraitName;
660:     }
661: 
662:     /**
663:      * Processes the parent reflection object.
664:      *
665:      * @param \TokenReflection\IReflection $parent Parent reflection object
666:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream
667:      * @return \TokenReflection\ReflectionElement
668:      * @throws \TokenReflection\Exception\ParseException If an invalid parent reflection object was provided.
669:      */
670:     protected function processParent(IReflection $parent, Stream $tokenStream)
671:     {
672:         if (!$parent instanceof ReflectionClass) {
673:             throw new Exception\ParseException($this, $tokenStream, 'The parent object has to be an instance of TokenReflection\ReflectionClass.', Exception\ParseException::INVALID_PARENT);
674:         }
675: 
676:         $this->declaringClassName = $parent->getName();
677:         if ($parent->isTrait()) {
678:             $this->declaringTraitName = $parent->getName();
679:         }
680:         return parent::processParent($parent, $tokenStream);
681:     }
682: 
683:     /**
684:      * Parses reflected element metadata from the token stream.
685:      *
686:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream
687:      * @param \TokenReflection\IReflection $parent Parent reflection object
688:      * @return \TokenReflection\ReflectionMethod
689:      * @throws \TokenReflection\Exception\Parse If the class could not be parsed.
690:      */
691:     protected function parse(Stream $tokenStream, IReflection $parent)
692:     {
693:         return $this
694:             ->parseBaseModifiers($tokenStream)
695:             ->parseReturnsReference($tokenStream)
696:             ->parseName($tokenStream)
697:             ->parseInternalModifiers($parent);
698:     }
699: 
700:     /**
701:      * Parses base method modifiers (abstract, final, public, ...).
702:      *
703:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream
704:      * @return \TokenReflection\ReflectionMethod
705:      */
706:     private function parseBaseModifiers(Stream $tokenStream)
707:     {
708:         while (true) {
709:             switch ($tokenStream->getType()) {
710:                 case T_ABSTRACT:
711:                     $this->modifiers |= InternalReflectionMethod::IS_ABSTRACT;
712:                     break;
713:                 case T_FINAL:
714:                     $this->modifiers |= InternalReflectionMethod::IS_FINAL;
715:                     break;
716:                 case T_PUBLIC:
717:                     $this->modifiers |= InternalReflectionMethod::IS_PUBLIC;
718:                     break;
719:                 case T_PRIVATE:
720:                     $this->modifiers |= InternalReflectionMethod::IS_PRIVATE;
721:                     break;
722:                 case T_PROTECTED:
723:                     $this->modifiers |= InternalReflectionMethod::IS_PROTECTED;
724:                     break;
725:                 case T_STATIC:
726:                     $this->modifiers |= InternalReflectionMethod::IS_STATIC;
727:                     break;
728:                 case T_FUNCTION:
729:                 case null:
730:                     break 2;
731:                 default:
732:                     break;
733:             }
734: 
735:             $tokenStream->skipWhitespaces();
736:         }
737: 
738:         if (!($this->modifiers & (InternalReflectionMethod::IS_PRIVATE | InternalReflectionMethod::IS_PROTECTED))) {
739:             $this->modifiers |= InternalReflectionMethod::IS_PUBLIC;
740:         }
741: 
742:         return $this;
743:     }
744: 
745:     /**
746:      * Parses internal PHP method modifiers (abstract, final, public, ...).
747:      *
748:      * @param \TokenReflection\ReflectionClass $class Parent class
749:      * @return \TokenReflection\ReflectionMethod
750:      */
751:     private function parseInternalModifiers(ReflectionClass $class)
752:     {
753:         $name = strtolower($this->name);
754:         // In PHP 5.3.3+ the ctor can be named only __construct in namespaced classes
755:         if ('__construct' === $name || ((!$class->inNamespace() || PHP_VERSION_ID < 50303) && strtolower($class->getShortName()) === $name)) {
756:             $this->modifiers |= self::IS_CONSTRUCTOR;
757:         } elseif ('__destruct' === $name) {
758:             $this->modifiers |= self::IS_DESTRUCTOR;
759:         } elseif ('__clone' === $name) {
760:             $this->modifiers |= self::IS_CLONE;
761:         }
762: 
763:         if ($class->isInterface()) {
764:             $this->modifiers |= InternalReflectionMethod::IS_ABSTRACT;
765:         } else {
766:             // Can be called statically, see http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend_API.c?revision=309853&view=markup#l1795
767:             static $notAllowed = array('__clone' => true, '__tostring' => true, '__get' => true, '__set' => true, '__isset' => true, '__unset' => true);
768:             if (!$this->isStatic() && !$this->isConstructor() && !$this->isDestructor() && !isset($notAllowed[$name])) {
769:                 $this->modifiers |= self::IS_ALLOWED_STATIC;
770:             }
771:         }
772: 
773:         return $this;
774:     }
775: }
776: 
PHP Token Reflection API documentation generated by ApiGen 2.8.0