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: 
 20: /**
 21:  * Base abstract class for tokenized function and method.
 22:  */
 23: abstract class ReflectionFunctionBase extends ReflectionElement implements IReflectionFunctionBase
 24: {
 25:     /**
 26:      * Function/method namespace name.
 27:      *
 28:      * @var string
 29:      */
 30:     protected $namespaceName;
 31: 
 32:     /**
 33:      * Determines if the function/method returns its value as reference.
 34:      *
 35:      * @var boolean
 36:      */
 37:     private $returnsReference = false;
 38: 
 39:     /**
 40:      * Parameters.
 41:      *
 42:      * @var array
 43:      */
 44:     protected $parameters = array();
 45: 
 46:     /**
 47:      * Static variables defined within the function/method.
 48:      *
 49:      * @var array
 50:      */
 51:     private $staticVariables = array();
 52: 
 53:     /**
 54:      * Definitions of static variables defined within the function/method.
 55:      *
 56:      * @var array
 57:      */
 58:     private $staticVariablesDefinition = array();
 59: 
 60:     /**
 61:      * Returns the name (FQN).
 62:      *
 63:      * @return string
 64:      */
 65:     public function getName()
 66:     {
 67:         if (null !== $this->namespaceName && ReflectionNamespace::NO_NAMESPACE_NAME !== $this->namespaceName) {
 68:             return $this->namespaceName . '\\' . $this->name;
 69:         }
 70: 
 71:         return $this->name;
 72:     }
 73: 
 74:     /**
 75:      * Returns the unqualified name (UQN).
 76:      *
 77:      * @return string
 78:      */
 79:     public function getShortName()
 80:     {
 81:         return $this->name;
 82:     }
 83: 
 84:     /**
 85:      * Returns the namespace name.
 86:      *
 87:      * @return string
 88:      */
 89:     public function getNamespaceName()
 90:     {
 91:         return null === $this->namespaceName || $this->namespaceName === ReflectionNamespace::NO_NAMESPACE_NAME ? '' : $this->namespaceName;
 92:     }
 93: 
 94:     /**
 95:      * Returns if the function/method is defined within a namespace.
 96:      *
 97:      * @return boolean
 98:      */
 99:     public function inNamespace()
100:     {
101:         return '' !== $this->getNamespaceName();
102:     }
103: 
104:     /**
105:      * Returns if the function/method is a closure.
106:      *
107:      * @return boolean
108:      */
109:     public function isClosure()
110:     {
111:         return false;
112:     }
113: 
114:     /**
115:      * Returns this pointer bound to closure.
116:      *
117:      * @return null
118:      */
119:     public function getClosureThis()
120:     {
121:         return null;
122:     }
123: 
124:     /**
125:      * Returns the closure scope class.
126:      *
127:      * @return string|null
128:      */
129:     public function getClosureScopeClass()
130:     {
131:         return null;
132:     }
133: 
134:     /**
135:      * Returns if the function/method returns its value as reference.
136:      *
137:      * @return boolean
138:      */
139:     public function returnsReference()
140:     {
141:         return $this->returnsReference;
142:     }
143: 
144:     /**
145:      * Returns a particular function/method parameter.
146:      *
147:      * @param integer|string $parameter Parameter name or position
148:      * @return \TokenReflection\ReflectionParameter
149:      * @throws \TokenReflection\Exception\RuntimeException If there is no parameter of the given name.
150:      * @throws \TokenReflection\Exception\RuntimeException If there is no parameter at the given position.
151:      */
152:     public function getParameter($parameter)
153:     {
154:         if (is_numeric($parameter)) {
155:             if (!isset($this->parameters[$parameter])) {
156:                 throw new Exception\RuntimeException(sprintf('There is no parameter at position "%d".', $parameter), Exception\RuntimeException::DOES_NOT_EXIST, $this);
157:             }
158:             return $this->parameters[$parameter];
159:         } else {
160:             foreach ($this->parameters as $reflection) {
161:                 if ($reflection->getName() === $parameter) {
162:                     return $reflection;
163:                 }
164:             }
165: 
166:             throw new Exception\RuntimeException(sprintf('There is no parameter "%s".', $parameter), Exception\RuntimeException::DOES_NOT_EXIST, $this);
167:         }
168:     }
169: 
170:     /**
171:      * Returns parameters.
172:      *
173:      * @return array
174:      */
175:     public function getParameters()
176:     {
177:         return $this->parameters;
178:     }
179: 
180:     /**
181:      * Returns the number of parameters.
182:      *
183:      * @return integer
184:      */
185:     public function getNumberOfParameters()
186:     {
187:         return count($this->parameters);
188:     }
189: 
190:     /**
191:      * Returns the number of required parameters.
192:      *
193:      * @return integer
194:      */
195:     public function getNumberOfRequiredParameters()
196:     {
197:         $count = 0;
198:         array_walk($this->parameters, function(ReflectionParameter $parameter) use (&$count) {
199:             if (!$parameter->isOptional()) {
200:                 $count++;
201:             }
202:         });
203:         return $count;
204:     }
205: 
206:     /**
207:      * Returns static variables.
208:      *
209:      * @return array
210:      */
211:     public function getStaticVariables()
212:     {
213:         if (empty($this->staticVariables) && !empty($this->staticVariablesDefinition)) {
214:             foreach ($this->staticVariablesDefinition as $variableName => $variableDefinition) {
215:                 $this->staticVariables[$variableName] = Resolver::getValueDefinition($variableDefinition, $this);
216:             }
217:         }
218: 
219:         return $this->staticVariables;
220:     }
221: 
222:     /**
223:      * Returns an element pretty (docblock compatible) name.
224:      *
225:      * @return string
226:      */
227:     public function getPrettyName()
228:     {
229:         return $this->name . '()';
230:     }
231: 
232:     /**
233:      * Creates aliases to parameters.
234:      *
235:      * @throws \TokenReflection\Exception\RuntimeException When called on a ReflectionFunction instance.
236:      */
237:     protected final function aliasParameters()
238:     {
239:         if (!$this instanceof ReflectionMethod) {
240:             throw new Exception\RuntimeException('Only method parameters can be aliased.', Exception\RuntimeException::UNSUPPORTED, $this);
241:         }
242: 
243:         foreach ($this->parameters as $index => $parameter) {
244:             $this->parameters[$index] = $parameter->alias($this);
245:         }
246:     }
247: 
248:     /**
249:      * Parses if the function/method returns its value as reference.
250:      *
251:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream
252:      * @return \TokenReflection\ReflectionFunctionBase
253:      * @throws \TokenReflection\Exception\ParseException If could not be determined if the function\method returns its value by reference.
254:      */
255:     final protected function parseReturnsReference(Stream $tokenStream)
256:     {
257:         if (!$tokenStream->is(T_FUNCTION)) {
258:             throw new Exception\ParseException($this, $tokenStream, 'Could not find the function keyword.', Exception\ParseException::UNEXPECTED_TOKEN);
259:         }
260: 
261:         $tokenStream->skipWhitespaces(true);
262: 
263:         $type = $tokenStream->getType();
264: 
265:         if ('&' === $type) {
266:             $this->returnsReference = true;
267:             $tokenStream->skipWhitespaces(true);
268:         } elseif (T_STRING !== $type) {
269:             throw new Exception\ParseException($this, $tokenStream, 'Unexpected token found.', Exception\ParseException::UNEXPECTED_TOKEN);
270:         }
271: 
272:         return $this;
273:     }
274: 
275:     /**
276:      * Parses the function/method name.
277:      *
278:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream
279:      * @return \TokenReflection\ReflectionMethod
280:      * @throws \TokenReflection\Exception\ParseException If the class name could not be determined.
281:      */
282:     final protected function parseName(Stream $tokenStream)
283:     {
284:         $this->name = $tokenStream->getTokenValue();
285: 
286:         $tokenStream->skipWhitespaces(true);
287: 
288:         return $this;
289:     }
290: 
291:     /**
292:      * Parses child reflection objects from the token stream.
293:      *
294:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream
295:      * @param \TokenReflection\IReflection $parent Parent reflection object
296:      * @return \TokenReflection\ReflectionElement
297:      */
298:     final protected function parseChildren(Stream $tokenStream, IReflection $parent)
299:     {
300:         return $this
301:             ->parseParameters($tokenStream)
302:             ->parseStaticVariables($tokenStream);
303:     }
304: 
305:     /**
306:      * Parses function/method parameters.
307:      *
308:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream
309:      * @return \TokenReflection\ReflectionFunctionBase
310:      * @throws \TokenReflection\Exception\ParseException If parameters could not be parsed.
311:      */
312:     final protected function parseParameters(Stream $tokenStream)
313:     {
314:         if (!$tokenStream->is('(')) {
315:             throw new Exception\ParseException($this, $tokenStream, 'Could find the start token.', Exception\ParseException::UNEXPECTED_TOKEN);
316:         }
317: 
318:         static $accepted = array(T_NS_SEPARATOR => true, T_STRING => true, T_ARRAY => true, T_CALLABLE => true, T_VARIABLE => true, '&' => true);
319: 
320:         $tokenStream->skipWhitespaces(true);
321: 
322:         while (null !== ($type = $tokenStream->getType()) && ')' !== $type) {
323:             if (isset($accepted[$type])) {
324:                 $parameter = new ReflectionParameter($tokenStream, $this->getBroker(), $this);
325:                 $this->parameters[] = $parameter;
326:             }
327: 
328:             if ($tokenStream->is(')')) {
329:                 break;
330:             }
331: 
332:             $tokenStream->skipWhitespaces(true);
333:         }
334: 
335:         $tokenStream->skipWhitespaces();
336: 
337:         return $this;
338:     }
339: 
340:     /**
341:      * Parses static variables.
342:      *
343:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream
344:      * @return \TokenReflection\ReflectionFunctionBase
345:      * @throws \TokenReflection\Exception\ParseException If static variables could not be parsed.
346:      */
347:     final protected function parseStaticVariables(Stream $tokenStream)
348:     {
349:         $type = $tokenStream->getType();
350:         if ('{' === $type) {
351:             if ($this->getBroker()->isOptionSet(Broker::OPTION_PARSE_FUNCTION_BODY)) {
352:                 $tokenStream->skipWhitespaces(true);
353: 
354:                 while ('}' !== ($type = $tokenStream->getType())) {
355:                     switch ($type) {
356:                         case T_STATIC:
357:                             $type = $tokenStream->skipWhitespaces(true)->getType();
358:                             if (T_VARIABLE !== $type) {
359:                                 // Late static binding
360:                                 break;
361:                             }
362: 
363:                             while (T_VARIABLE === $type) {
364:                                 $variableName = $tokenStream->getTokenValue();
365:                                 $variableDefinition = array();
366: 
367:                                 $type = $tokenStream->skipWhitespaces(true)->getType();
368:                                 if ('=' === $type) {
369:                                     $type = $tokenStream->skipWhitespaces(true)->getType();
370:                                     $level = 0;
371:                                     while ($tokenStream->valid()) {
372:                                         switch ($type) {
373:                                             case '(':
374:                                             case '[':
375:                                             case '{':
376:                                             case T_CURLY_OPEN:
377:                                             case T_DOLLAR_OPEN_CURLY_BRACES:
378:                                                 $level++;
379:                                                 break;
380:                                             case ')':
381:                                             case ']':
382:                                             case '}':
383:                                                 $level--;
384:                                                 break;
385:                                             case ';':
386:                                             case ',':
387:                                                 if (0 === $level) {
388:                                                     break 2;
389:                                                 }
390:                                             default:
391:                                                 break;
392:                                         }
393: 
394:                                         $variableDefinition[] = $tokenStream->current();
395:                                         $type = $tokenStream->skipWhitespaces(true)->getType();
396:                                     }
397: 
398:                                     if (!$tokenStream->valid()) {
399:                                         throw new Exception\ParseException($this, $tokenStream, 'Invalid end of token stream.', Exception\ParseException::READ_BEYOND_EOS);
400:                                     }
401:                                 }
402: 
403:                                 $this->staticVariablesDefinition[substr($variableName, 1)] = $variableDefinition;
404: 
405:                                 if (',' === $type) {
406:                                     $type = $tokenStream->skipWhitespaces(true)->getType();
407:                                 } else {
408:                                     break;
409:                                 }
410:                             }
411: 
412:                             break;
413:                         case T_FUNCTION:
414:                             // Anonymous function -> skip to its end
415:                             if (!$tokenStream->find('{')) {
416:                                 throw new Exception\ParseException($this, $tokenStream, 'Could not find beginning of the anonymous function.', Exception\ParseException::UNEXPECTED_TOKEN);
417:                             }
418:                             // Break missing intentionally
419:                         case '{':
420:                         case '[':
421:                         case '(':
422:                         case T_CURLY_OPEN:
423:                         case T_DOLLAR_OPEN_CURLY_BRACES:
424:                             $tokenStream->findMatchingBracket()->skipWhitespaces(true);
425:                             break;
426:                         default:
427:                             $tokenStream->skipWhitespaces();
428:                             break;
429:                     }
430:                 }
431:             } else {
432:                 $tokenStream->findMatchingBracket();
433:             }
434:         } elseif (';' !== $type) {
435:             throw new Exception\ParseException($this, $tokenStream, 'Unexpected token found.', Exception\ParseException::UNEXPECTED_TOKEN);
436:         }
437: 
438:         return $this;
439:     }
440: }
441: 
PHP Token Reflection API documentation generated by ApiGen 2.8.0