Overview

Namespaces

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

Classes

  • Memory
  • 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\Broker\Backend;
 17: 
 18: use TokenReflection;
 19: use TokenReflection\Stream\FileStream, TokenReflection\Exception, TokenReflection\Broker, TokenReflection\Php, TokenReflection\Dummy;
 20: 
 21: /**
 22:  * Memory broker backend.
 23:  *
 24:  * Stores parsed reflection objects in memory.
 25:  */
 26: class Memory implements Broker\Backend
 27: {
 28:     /**
 29:      * List of declared class names.
 30:      *
 31:      * @var array
 32:      */
 33:     private $declaredClasses = array();
 34: 
 35:     /**
 36:      * Namespaces storage.
 37:      *
 38:      * @var array
 39:      */
 40:     private $namespaces = array();
 41: 
 42:     /**
 43:      * All tokenized constants cache.
 44:      *
 45:      * @var array
 46:      */
 47:     private $allConstants;
 48: 
 49:     /**
 50:      * All tokenized classes cache.
 51:      *
 52:      * @var array
 53:      */
 54:     private $allClasses;
 55: 
 56:     /**
 57:      * All tokenized functions cache.
 58:      *
 59:      * @var array
 60:      */
 61:     private $allFunctions;
 62: 
 63:     /**
 64:      * Token streams storage.
 65:      *
 66:      * @var array
 67:      */
 68:     private $tokenStreams = array();
 69: 
 70:     /**
 71:      * Processed files storage.
 72:      *
 73:      * @var array
 74:      */
 75:     private $files = array();
 76: 
 77:     /**
 78:      * Reflection broker.
 79:      *
 80:      * @var \TokenReflection\Broker
 81:      */
 82:     private $broker;
 83: 
 84:     /**
 85:      * Determines if token streams are stored within the backend.
 86:      *
 87:      * @var boolean
 88:      */
 89:     private $storingTokenStreams;
 90: 
 91:     /**
 92:      * Returns if a file with the given filename has been processed.
 93:      *
 94:      * @param string $fileName File name
 95:      * @return boolean
 96:      */
 97:     public function hasFile($fileName)
 98:     {
 99:         return isset($this->files[$fileName]);
100:     }
101: 
102:     /**
103:      * Returns a file reflection.
104:      *
105:      * @param string $fileName File name
106:      * @return \TokenReflection\ReflectionFile
107:      * @throws \TokenReflection\Exception\BrokerException If the requested file has not been processed
108:      */
109:     public function getFile($fileName)
110:     {
111:         if (!isset($this->files[$fileName])) {
112:             throw new Exception\BrokerException($this->getBroker(), sprintf('File "%s" has not been processed.', $fileName), Exception\BrokerException::DOES_NOT_EXIST);
113:         }
114: 
115:         return $this->files[$fileName];
116:     }
117: 
118:     /**
119:      * Returns file reflections.
120:      *
121:      * @return array
122:      */
123:     public function getFiles()
124:     {
125:         return $this->files;
126:     }
127: 
128:     /**
129:      * Returns if there was such namespace processed (FQN expected).
130:      *
131:      * @param string $namespaceName Namespace name
132:      * @return boolean
133:      */
134:     public function hasNamespace($namespaceName)
135:     {
136:         return isset($this->namespaces[ltrim($namespaceName, '\\')]);
137:     }
138: 
139:     /**
140:      * Returns a reflection object of the given namespace.
141:      *
142:      * @param string $namespaceName Namespace name
143:      * @return \TokenReflection\IReflectionNamespace
144:      * @throws \TokenReflection\Exception\BrokerException If the requested namespace does not exist.
145:      */
146:     public function getNamespace($namespaceName)
147:     {
148:         if (!isset($this->namespaces[TokenReflection\ReflectionNamespace::NO_NAMESPACE_NAME])) {
149:             $this->namespaces[TokenReflection\ReflectionNamespace::NO_NAMESPACE_NAME] = new TokenReflection\ReflectionNamespace(TokenReflection\ReflectionNamespace::NO_NAMESPACE_NAME, $this->broker);
150:         }
151: 
152:         $namespaceName = ltrim($namespaceName, '\\');
153:         if (!isset($this->namespaces[$namespaceName])) {
154:             throw new Exception\BrokerException($this->getBroker(), sprintf('Namespace %s does not exist.', $namespaceName), Exception\BrokerException::DOES_NOT_EXIST);
155:         }
156: 
157:         return $this->namespaces[$namespaceName];
158:     }
159: 
160:     /**
161:      * Returns all present namespaces.
162:      *
163:      * @return array
164:      */
165:     public function getNamespaces()
166:     {
167:         return $this->namespaces;
168:     }
169: 
170:     /**
171:      * Returns if there was such class processed (FQN expected).
172:      *
173:      * @param string $className Class name
174:      * @return boolean
175:      */
176:     public function hasClass($className)
177:     {
178:         $className = ltrim($className, '\\');
179:         if ($pos = strrpos($className, '\\')) {
180:             $namespace = substr($className, 0, $pos);
181: 
182:             if (!isset($this->namespaces[$namespace])) {
183:                 return false;
184:             }
185: 
186:             $namespace = $this->getNamespace($namespace);
187:             $className = substr($className, $pos + 1);
188:         } else {
189:             $namespace = $this->getNamespace(TokenReflection\ReflectionNamespace::NO_NAMESPACE_NAME);
190:         }
191: 
192:         return $namespace->hasClass($className);
193:     }
194: 
195:     /**
196:      * Returns a reflection object of the given class (FQN expected).
197:      *
198:      * @param string $className CLass bame
199:      * @return \TokenReflection\IReflectionClass
200:      */
201:     public function getClass($className)
202:     {
203:         if (empty($this->declaredClasses)) {
204:             $this->declaredClasses = array_flip(array_merge(get_declared_classes(), get_declared_interfaces()));
205:         }
206: 
207:         $className = ltrim($className, '\\');
208:         try {
209:             $ns = $this->getNamespace(
210:                 ($boundary = strrpos($className, '\\'))
211:                 // Class within a namespace
212:                 ? substr($className, 0, $boundary)
213:                 // Class without a namespace
214:                 : TokenReflection\ReflectionNamespace::NO_NAMESPACE_NAME
215:             );
216: 
217:             return $ns->getClass($className);
218:         } catch (Exception\BaseException $e) {
219:             if (isset($this->declaredClasses[$className])) {
220:                 $reflection = new Php\ReflectionClass($className, $this->broker);
221:                 if ($reflection->isInternal()) {
222:                     return $reflection;
223:                 }
224:             }
225: 
226:             return new Dummy\ReflectionClass($className, $this->broker);
227:         }
228:     }
229: 
230:     /**
231:      * Returns all classes from all namespaces.
232:      *
233:      * @param integer $type Returned class types (multiple values may be OR-ed)
234:      * @return array
235:      */
236:     public function getClasses($type = self::TOKENIZED_CLASSES)
237:     {
238:         if (null === $this->allClasses) {
239:             $this->allClasses = $this->parseClassLists();
240:         }
241: 
242:         $result = array();
243:         foreach ($this->allClasses as $classType => $classes) {
244:             if ($type & $classType) {
245:                 $result = array_merge($result, $classes);
246:             }
247:         }
248:         return $result;
249:     }
250: 
251:     /**
252:      * Returns if there was such constant processed (FQN expected).
253:      *
254:      * @param string $constantName Constant name
255:      * @return boolean
256:      */
257:     public function hasConstant($constantName)
258:     {
259:         $constantName = ltrim($constantName, '\\');
260: 
261:         if ($pos = strpos($constantName, '::')) {
262:             $className = substr($constantName, 0, $pos);
263:             $constantName = substr($constantName, $pos + 2);
264: 
265:             if (!$this->hasClass($className)) {
266:                 return false;
267:             }
268: 
269:             $parent = $this->getClass($className);
270:         } else {
271:             if ($pos = strrpos($constantName, '\\')) {
272:                 $namespace = substr($constantName, 0, $pos);
273:                 if (!$this->hasNamespace($namespace)) {
274:                     return false;
275:                 }
276: 
277:                 $parent = $this->getNamespace($namespace);
278:                 $constantName = substr($constantName, $pos + 1);
279:             } else {
280:                 $parent = $this->getNamespace(TokenReflection\ReflectionNamespace::NO_NAMESPACE_NAME);
281:             }
282:         }
283: 
284:         return $parent->hasConstant($constantName);
285:     }
286: 
287:     /**
288:      * Returns a reflection object of a constant (FQN expected).
289:      *
290:      * @param string $constantName Constant name
291:      * @return \TokenReflection\IReflectionConstant
292:      * @throws \TokenReflection\Exception\RuntimeException If the requested constant does not exist.
293:      */
294:     public function getConstant($constantName)
295:     {
296:         static $declared = array();
297:         if (empty($declared)) {
298:             $declared = get_defined_constants();
299:         }
300: 
301:         if ($boundary = strpos($constantName, '::')) {
302:             // Class constant
303:             $className = substr($constantName, 0, $boundary);
304:             $constantName = substr($constantName, $boundary + 2);
305: 
306:             return $this->getClass($className)->getConstantReflection($constantName);
307:         }
308: 
309:         try {
310:             $constantName = ltrim($constantName, '\\');
311:             if ($boundary = strrpos($constantName, '\\')) {
312:                 $ns = $this->getNamespace(substr($constantName, 0, $boundary));
313:                 $constantName = substr($constantName, $boundary + 1);
314:             } else {
315:                 $ns = $this->getNamespace(TokenReflection\ReflectionNamespace::NO_NAMESPACE_NAME);
316:             }
317: 
318:             return $ns->getConstant($constantName);
319:         } catch (Exception\BaseException $e) {
320:             if (isset($declared[$constantName])) {
321:                 $reflection = new Php\ReflectionConstant($constantName, $declared[$constantName], $this->broker);
322:                 if ($reflection->isInternal()) {
323:                     return $reflection;
324:                 }
325:             }
326: 
327:             throw new Exception\BrokerException($this->getBroker(), sprintf('Constant %s does not exist.', $constantName), Exception\BrokerException::DOES_NOT_EXIST);
328:         }
329:     }
330: 
331:     /**
332:      * Returns all constants from all namespaces.
333:      *
334:      * @return array
335:      */
336:     public function getConstants()
337:     {
338:         if (null === $this->allConstants) {
339:             $this->allConstants = array();
340:             foreach ($this->namespaces as $namespace) {
341:                 foreach ($namespace->getConstants() as $constant) {
342:                     $this->allConstants[$constant->getName()] = $constant;
343:                 }
344:             }
345:         }
346: 
347:         return $this->allConstants;
348:     }
349: 
350:     /**
351:      * Returns if there was such function processed (FQN expected).
352:      *
353:      * @param string $functionName Function name
354:      * @return boolean
355:      */
356:     public function hasFunction($functionName)
357:     {
358:         $functionName = ltrim($functionName, '\\');
359:         if ($pos = strrpos($functionName, '\\')) {
360:             $namespace = substr($functionName, 0, $pos);
361:             if (!isset($this->namespaces[$namespace])) {
362:                 return false;
363:             }
364: 
365:             $namespace = $this->getNamespace($namespace);
366:             $functionName = substr($functionName, $pos + 1);
367:         } else {
368:             $namespace = $this->getNamespace(TokenReflection\ReflectionNamespace::NO_NAMESPACE_NAME);
369:         }
370: 
371:         return $namespace->hasFunction($functionName);
372:     }
373: 
374:     /**
375:      * Returns a reflection object of a function (FQN expected).
376:      *
377:      * @param string $functionName Function name
378:      * @return \TokenReflection\IReflectionFunction
379:      * @throws \TokenReflection\Exception\RuntimeException If the requested function does not exist.
380:      */
381:     public function getFunction($functionName)
382:     {
383:         static $declared = array();
384:         if (empty($declared)) {
385:             $functions = get_defined_functions();
386:             $declared = array_flip($functions['internal']);
387:         }
388: 
389:         $functionName = ltrim($functionName, '\\');
390:         try {
391:             $ns = $this->getNamespace(
392:                 ($boundary = strrpos($functionName, '\\'))
393:                 // Function within a namespace
394:                 ? substr($functionName, 0, $boundary)
395:                 // Function wihout a namespace
396:                 : TokenReflection\ReflectionNamespace::NO_NAMESPACE_NAME
397:             );
398: 
399:             return $ns->getFunction($functionName);
400:         } catch (Exception\BaseException $e) {
401:             if (isset($declared[$functionName])) {
402:                 return new Php\ReflectionFunction($functionName, $this->broker);
403:             }
404: 
405:             throw new Exception\BrokerException($this->getBroker(), sprintf('Function %s does not exist.', $functionName), Exception\BrokerException::DOES_NOT_EXIST);
406:         }
407:     }
408: 
409:     /**
410:      * Returns all functions from all namespaces.
411:      *
412:      * @return array
413:      */
414:     public function getFunctions()
415:     {
416:         if (null === $this->allFunctions) {
417:             $this->allFunctions = array();
418:             foreach ($this->namespaces as $namespace) {
419:                 foreach ($namespace->getFunctions() as $function) {
420:                     $this->allFunctions[$function->getName()] = $function;
421:                 }
422:             }
423:         }
424: 
425:         return $this->allFunctions;
426:     }
427: 
428:     /**
429:      * Returns if the given file was already processed.
430:      *
431:      * @param string $fileName File name
432:      * @return boolean
433:      */
434:     public function isFileProcessed($fileName)
435:     {
436:         return isset($this->tokenStreams[Broker::getRealPath($fileName)]);
437:     }
438: 
439:     /**
440:      * Returns an array of tokens for a particular file.
441:      *
442:      * @param string $fileName File name
443:      * @return \TokenReflection\Stream\StreamBase
444:      * @throws \TokenReflection\Exception\BrokerException If the requested file was not processed.
445:      */
446:     public function getFileTokens($fileName)
447:     {
448:         $realName = Broker::getRealPath($fileName);
449:         if (!isset($this->tokenStreams[$realName])) {
450:             throw new Exception\BrokerException($this->getBroker(), sprintf('File "%s" was not processed yet.', $fileName), Exception\BrokerException::DOES_NOT_EXIST);
451:         }
452: 
453:         return true === $this->tokenStreams[$realName] ? new FileStream($realName) : $this->tokenStreams[$realName];
454:     }
455: 
456:     /**
457:      * Adds a file to the backend storage.
458:      *
459:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token stream
460:      * @param \TokenReflection\ReflectionFile $file File reflection object
461:      * @return \TokenReflection\Broker\Backend\Memory
462:      */
463:     public function addFile(TokenReflection\Stream\StreamBase $tokenStream, TokenReflection\ReflectionFile $file)
464:     {
465:         $this->tokenStreams[$file->getName()] = $this->storingTokenStreams ? $tokenStream : true;
466:         $this->files[$file->getName()] = $file;
467: 
468:         $errors = array();
469: 
470:         foreach ($file->getNamespaces() as $fileNamespace) {
471:             try {
472:                 $namespaceName = $fileNamespace->getName();
473:                 if (!isset($this->namespaces[$namespaceName])) {
474:                     $this->namespaces[$namespaceName] = new TokenReflection\ReflectionNamespace($namespaceName, $file->getBroker());
475:                 }
476: 
477:                 $this->namespaces[$namespaceName]->addFileNamespace($fileNamespace);
478:             } catch (Exception\FileProcessingException $e) {
479:                 $errors = array_merge($errors, $e->getReasons());
480:             } catch (\Exception $e) {
481:                 echo $e->getTraceAsString();
482:                 die($e->getMessage());
483:             }
484:         }
485: 
486:         // Reset all-*-cache
487:         $this->allClasses = null;
488:         $this->allFunctions = null;
489:         $this->allConstants = null;
490: 
491:         if (!empty($errors)) {
492:             throw new Exception\FileProcessingException($errors, $file);
493:         }
494: 
495:         return $this;
496:     }
497: 
498:     /**
499:      * Sets the reflection broker instance.
500:      *
501:      * @param \TokenReflection\Broker $broker Reflection broker
502:      * @return \TokenReflection\Broker\Backend\Memory
503:      */
504:     public function setBroker(Broker $broker)
505:     {
506:         $this->broker = $broker;
507:         return $this;
508:     }
509: 
510:     /**
511:      * Returns the reflection broker instance.
512:      *
513:      * @return \TokenReflection\Broker $broker Reflection broker
514:      */
515:     public function getBroker()
516:     {
517:         return $this->broker;
518:     }
519: 
520:     /**
521:      * Sets if token streams are stored in the backend.
522:      *
523:      * @param boolean $store
524:      * @return \TokenReflection\Broker\Backend
525:      */
526:     public function setStoringTokenStreams($store)
527:     {
528:         $this->storingTokenStreams = (bool) $store;
529:         return $this;
530:     }
531: 
532:     /**
533:      * Returns if token streams are stored in the backend.
534:      *
535:      * @return boolean
536:      */
537:     public function getStoringTokenStreams()
538:     {
539:         return $this->storingTokenStreams;
540:     }
541: 
542:     /**
543:      * Prepares and returns used class lists.
544:      *
545:      * @return array
546:      */
547:     protected function parseClassLists()
548:     {
549:         // Initialize the all-classes-cache
550:         $allClasses = array(
551:             self::TOKENIZED_CLASSES => array(),
552:             self::INTERNAL_CLASSES => array(),
553:             self::NONEXISTENT_CLASSES => array()
554:         );
555: 
556:         foreach ($this->namespaces as $namespace) {
557:             foreach ($namespace->getClasses() as $class) {
558:                 $allClasses[self::TOKENIZED_CLASSES][$class->getName()] = $class;
559:             }
560:         }
561: 
562:         foreach ($allClasses[self::TOKENIZED_CLASSES] as $className => $class) {
563:             foreach (array_merge($class->getParentClasses(), $class->getInterfaces()) as $parent) {
564:                 if ($parent->isInternal()) {
565:                     $allClasses[self::INTERNAL_CLASSES][$parent->getName()] = $parent;
566:                 } elseif (!$parent->isTokenized()) {
567:                     $allClasses[self::NONEXISTENT_CLASSES][$parent->getName()] = $parent;
568:                 }
569:             }
570:         }
571: 
572:         return $allClasses;
573:     }
574: }
575: 
PHP Token Reflection API documentation generated by ApiGen 2.8.0