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\Invalid;
17:
18: use TokenReflection;
19: use TokenReflection\Broker, TokenReflection\IReflectionClass, TokenReflection\ReflectionBase;
20: use ReflectionClass as InternalReflectionClass, TokenReflection\Exception;
21:
22: /**
23: * Invalid class reflection.
24: *
25: * The reflected class is not unique.
26: */
27: class ReflectionClass extends ReflectionElement implements IReflectionClass
28: {
29: /**
30: * Class name (FQN).
31: *
32: * @var string
33: */
34: private $name;
35:
36: /**
37: * Original definition file name.
38: *
39: * @var string
40: */
41: private $fileName;
42:
43: /**
44: * Reflection broker.
45: *
46: * @var \TokenReflection\Broker
47: */
48: private $broker;
49:
50: /**
51: * Constructor.
52: *
53: * @param string $className Class name
54: * @param string $fileName Original definiton file name
55: * @param \TokenReflection\Broker $broker Reflection broker
56: */
57: public function __construct($className, $fileName, Broker $broker)
58: {
59: $this->name = ltrim($className, '\\');
60: $this->fileName = $fileName;
61: $this->broker = $broker;
62: }
63:
64: /**
65: * Returns the name (FQN).
66: *
67: * @return string
68: */
69: public function getName()
70: {
71: return $this->name;
72: }
73:
74: /**
75: * Returns an element pretty (docblock compatible) name.
76: *
77: * @return string
78: */
79: public function getPrettyName()
80: {
81: return $this->name;
82: }
83:
84: /**
85: * Returns the unqualified name (UQN).
86: *
87: * @return string
88: */
89: public function getShortName()
90: {
91: $pos = strrpos($this->name, '\\');
92: return false === $pos ? $this->name : substr($this->name, $pos + 1);
93: }
94:
95: /**
96: * Returns the namespace name.
97: *
98: * @return string
99: */
100: public function getNamespaceName()
101: {
102: $pos = strrpos($this->name, '\\');
103: return false === $pos ? '' : substr($this->name, 0, $pos);
104: }
105:
106: /**
107: * Returns if the class is defined within a namespace.
108: *
109: * @return boolean
110: */
111: public function inNamespace()
112: {
113: return false !== strrpos($this->name, '\\');
114: }
115:
116: /**
117: * Returns imported namespaces and aliases from the declaring namespace.
118: *
119: * @return array
120: */
121: public function getNamespaceAliases()
122: {
123: return array();
124: }
125:
126: /**
127: * Returns the PHP extension reflection.
128: *
129: * @return null
130: */
131: public function getExtension()
132: {
133: return null;
134: }
135:
136: /**
137: * Returns the PHP extension name.
138: *
139: * @return boolean
140: */
141: public function getExtensionName()
142: {
143: return false;
144: }
145:
146: /**
147: * Returns the file name the reflection object is defined in.
148: *
149: * @return null
150: */
151: public function getFileName()
152: {
153: return $this->fileName;
154: }
155:
156: /**
157: * Returns a file reflection.
158: *
159: * @return \TokenReflection\ReflectionFile
160: * @throws \TokenReflection\Exception\RuntimeException If the file is not stored inside the broker
161: */
162: public function getFileReflection()
163: {
164: throw new Exception\BrokerException($this->getBroker(), sprintf('Class was not parsed from a file', $this->getName()), Exception\BrokerException::UNSUPPORTED);
165: }
166:
167: /**
168: * Returns the definition start line number in the file.
169: *
170: * @return null
171: */
172: public function getStartLine()
173: {
174: return null;
175: }
176:
177: /**
178: * Returns the definition end line number in the file.
179: *
180: * @return null
181: */
182: public function getEndLine()
183: {
184: return null;
185: }
186:
187: /**
188: * Returns the appropriate docblock definition.
189: *
190: * @return boolean
191: */
192: public function getDocComment()
193: {
194: return false;
195: }
196:
197: /**
198: * Checks if there is a particular annotation.
199: *
200: * @param string $name Annotation name
201: * @return boolean
202: */
203: public function hasAnnotation($name)
204: {
205: return false;
206: }
207:
208: /**
209: * Returns a particular annotation value.
210: *
211: * @param string $name Annotation name
212: * @return null
213: */
214: public function getAnnotation($name)
215: {
216: return null;
217: }
218:
219: /**
220: * Returns parsed docblock.
221: *
222: * @return array
223: */
224: public function getAnnotations()
225: {
226: return array();
227: }
228:
229: /**
230: * Returns modifiers.
231: *
232: * @return integer
233: */
234: public function getModifiers()
235: {
236: return 0;
237: }
238:
239: /**
240: * Returns if the class is abstract.
241: *
242: * @return boolean
243: */
244: public function isAbstract()
245: {
246: return false;
247: }
248:
249: /**
250: * Returns if the class is final.
251: *
252: * @return boolean
253: */
254: public function isFinal()
255: {
256: return false;
257: }
258:
259: /**
260: * Returns if the class is an interface.
261: *
262: * @return boolean
263: */
264: public function isInterface()
265: {
266: return false;
267: }
268:
269: /**
270: * Returns if the class is an exception or its descendant.
271: *
272: * @return boolean
273: */
274: public function isException()
275: {
276: return false;
277: }
278:
279: /**
280: * Returns if it is possible to create an instance of this class.
281: *
282: * @return boolean
283: */
284: public function isInstantiable()
285: {
286: return false;
287: }
288:
289: /**
290: * Returns traits used by this class.
291: *
292: * @return array
293: */
294: public function getTraits()
295: {
296: return array();
297: }
298:
299: /**
300: * Returns traits used by this class and not its parents.
301: *
302: * @return array
303: */
304: public function getOwnTraits()
305: {
306: return array();
307: }
308:
309: /**
310: * Returns names of used traits.
311: *
312: * @return array
313: */
314: public function getTraitNames()
315: {
316: return array();
317: }
318:
319: /**
320: * Returns traits used by this class and not its parents.
321: *
322: * @return array
323: */
324: public function getOwnTraitNames()
325: {
326: return array();
327: }
328:
329: /**
330: * Returns method aliases from traits.
331: *
332: * @return array
333: */
334: public function getTraitAliases()
335: {
336: return array();
337: }
338:
339: /**
340: * Returns if the class is a trait.
341: *
342: * @return boolean
343: */
344: public function isTrait()
345: {
346: return false;
347: }
348:
349: /**
350: * Returns if the class uses a particular trait.
351: *
352: * @param \ReflectionClass|\TokenReflection\IReflectionClass|string $trait Trait reflection or name
353: * @return boolean
354: */
355: public function usesTrait($trait)
356: {
357: return false;
358: }
359:
360: /**
361: * Returns if objects of this class are cloneable.
362: *
363: * Introduced in PHP 5.4.
364: *
365: * @return boolean
366: * @see http://svn.php.net/viewvc/php/php-src/trunk/ext/reflection/php_reflection.c?revision=307971&view=markup#l4059
367: */
368: public function isCloneable()
369: {
370: return false;
371: }
372:
373: /**
374: * Returns if the class is iterateable.
375: *
376: * Returns true if the class implements the Traversable interface.
377: *
378: * @return boolean
379: */
380: public function isIterateable()
381: {
382: return false;
383: }
384:
385: /**
386: * Returns if the reflection object is internal.
387: *
388: * @return boolean
389: */
390: public function isInternal()
391: {
392: return false;
393: }
394:
395: /**
396: * Returns if the reflection object is user defined.
397: *
398: * @return boolean
399: */
400: public function isUserDefined()
401: {
402: return true;
403: }
404:
405: /**
406: * Returns if the current reflection comes from a tokenized source.
407: *
408: * @return boolean
409: */
410: public function isTokenized()
411: {
412: return true;
413: }
414:
415: /**
416: * Returns if the current class is a subclass of the given class.
417: *
418: * @param string|object $class Class name or reflection object
419: * @return boolean
420: */
421: public function isSubclassOf($class)
422: {
423: return false;
424: }
425:
426: /**
427: * Returns the parent class reflection.
428: *
429: * @return null
430: */
431: public function getParentClass()
432: {
433: return false;
434: }
435:
436: /**
437: * Returns the parent classes reflections.
438: *
439: * @return array
440: */
441: public function getParentClasses()
442: {
443: return array();
444: }
445:
446: /**
447: * Returns the parent classes names.
448: *
449: * @return array
450: */
451: public function getParentClassNameList()
452: {
453: return array();
454: }
455:
456: /**
457: * Returns the parent class reflection.
458: *
459: * @return null
460: */
461: public function getParentClassName()
462: {
463: return null;
464: }
465:
466: /**
467: * Returns if the class implements the given interface.
468: *
469: * @param string|object $interface Interface name or reflection object
470: * @return boolean
471: * @throws \TokenReflection\Exception\RuntimeException If the provided parameter is not an interface.
472: */
473: public function implementsInterface($interface)
474: {
475: if (is_object($interface)) {
476: if (!$interface instanceof IReflectionClass) {
477: throw new Exception\RuntimeException(sprintf('Parameter must be a string or an instance of class reflection, "%s" provided.', get_class($interface)), Exception\RuntimeException::INVALID_ARGUMENT, $this);
478: }
479:
480: $interfaceName = $interface->getName();
481:
482: if (!$interface->isInterface()) {
483: throw new Exception\RuntimeException(sprintf('"%s" is not an interface.', $interfaceName), Exception\RuntimeException::INVALID_ARGUMENT, $this);
484: }
485: }
486:
487: // Only validation, always returns false
488: return false;
489: }
490:
491: /**
492: * Returns interface reflections.
493: *
494: * @return array
495: */
496: public function getInterfaces()
497: {
498: return array();
499: }
500:
501: /**
502: * Returns interface names.
503: *
504: * @return array
505: */
506: public function getInterfaceNames()
507: {
508: return array();
509: }
510:
511: /**
512: * Returns interfaces implemented by this class, not its parents.
513: *
514: * @return array
515: */
516: public function getOwnInterfaces()
517: {
518: return array();
519: }
520:
521: /**
522: * Returns names of interfaces implemented by this class, not its parents.
523: *
524: * @return array
525: */
526: public function getOwnInterfaceNames()
527: {
528: return array();
529: }
530:
531: /**
532: * Returns the class constructor reflection.
533: *
534: * @return null
535: */
536: public function getConstructor()
537: {
538: return null;
539: }
540:
541: /**
542: * Returns the class desctructor reflection.
543: *
544: * @return null
545: */
546: public function getDestructor()
547: {
548: return null;
549: }
550:
551: /**
552: * Returns if the class implements the given method.
553: *
554: * @param string $name Method name
555: * @return boolean
556: */
557: public function hasMethod($name)
558: {
559: return false;
560: }
561:
562: /**
563: * Returns a method reflection.
564: *
565: * @param string $name Method name
566: * @throws \TokenReflection\Exception\RuntimeException If the requested method does not exist.
567: */
568: public function getMethod($name)
569: {
570: throw new Exception\RuntimeException(sprintf('There is no method "%s".', $name), Exception\RuntimeException::DOES_NOT_EXIST, $this);
571: }
572:
573: /**
574: * Returns method reflections.
575: *
576: * @param integer $filter Methods filter
577: * @return array
578: */
579: public function getMethods($filter = null)
580: {
581: return array();
582: }
583:
584: /**
585: * Returns if the class implements (and not its parents) the given method.
586: *
587: * @param string $name Method name
588: * @return boolean
589: */
590: public function hasOwnMethod($name)
591: {
592: return false;
593: }
594:
595: /**
596: * Returns methods declared by this class, not its parents.
597: *
598: * @param integer $filter Methods filter
599: * @return array
600: */
601: public function getOwnMethods($filter = null)
602: {
603: return array();
604: }
605:
606: /**
607: * Returns if the class imports the given method from traits.
608: *
609: * @param string $name Method name
610: * @return boolean
611: */
612: public function hasTraitMethod($name)
613: {
614: return false;
615: }
616:
617: /**
618: * Returns method reflections imported from traits.
619: *
620: * @param integer $filter Methods filter
621: * @return array
622: */
623: public function getTraitMethods($filter = null)
624: {
625: return array();
626: }
627:
628: /**
629: * Returns if the class defines the given constant.
630: *
631: * @param string $name Constant name.
632: * @return boolean
633: */
634: public function hasConstant($name)
635: {
636: return false;
637: }
638:
639: /**
640: * Returns a constant value.
641: *
642: * @param string $name Constant name
643: * @throws \TokenReflection\Exception\RuntimeException If the requested constant does not exist.
644: */
645: public function getConstant($name)
646: {
647: throw new Exception\RuntimeException(sprintf('There is no constant "%s".', $name), Exception\RuntimeException::DOES_NOT_EXIST, $this);
648: }
649:
650: /**
651: * Returns a constant reflection.
652: *
653: * @param string $name Constant name
654: * @throws \TokenReflection\Exception\RuntimeException If the requested constant does not exist.
655: */
656: public function getConstantReflection($name)
657: {
658: throw new Exception\RuntimeException(sprintf('There is no constant "%s".', $name), Exception\RuntimeException::DOES_NOT_EXIST, $this);
659: }
660:
661: /**
662: * Returns an array of constant values.
663: *
664: * @return array
665: */
666: public function getConstants()
667: {
668: return array();
669: }
670:
671: /**
672: * Returns an array of constant reflections.
673: *
674: * @return array
675: */
676: public function getConstantReflections()
677: {
678: return array();
679: }
680:
681: /**
682: * Returns if the class (and not its parents) defines the given constant.
683: *
684: * @param string $name Constant name.
685: * @return boolean
686: */
687: public function hasOwnConstant($name)
688: {
689: return false;
690: }
691:
692: /**
693: * Returns constants declared by this class, not its parents.
694: *
695: * @return array
696: */
697: public function getOwnConstants()
698: {
699: return array();
700: }
701:
702: /**
703: * Returns an array of constant reflections defined by this class not its parents.
704: *
705: * @return array
706: */
707: public function getOwnConstantReflections()
708: {
709: return array();
710: }
711:
712: /**
713: * Returns default properties.
714: *
715: * @return array
716: */
717: public function getDefaultProperties()
718: {
719: return array();
720: }
721:
722: /**
723: * Returns if the class implements the given property.
724: *
725: * @param string $name Property name
726: * @return boolean
727: */
728: public function hasProperty($name)
729: {
730: return false;
731: }
732:
733: /**
734: * Returns class properties.
735: *
736: * @param integer $filter Property types
737: * @return array
738: */
739: public function getProperties($filter = null)
740: {
741: return array();
742: }
743:
744: /**
745: * Return a property reflections.
746: *
747: * @param string $name Property name
748: * @throws \TokenReflection\Exception\RuntimeException If the requested property does not exist.
749: */
750: public function getProperty($name)
751: {
752: throw new Exception\RuntimeException(sprintf('There is no property "%s".', $name), Exception\RuntimeException::DOES_NOT_EXIST, $this);
753: }
754:
755: /**
756: * Returns if the class (and not its parents) implements the given property.
757: *
758: * @param string $name Property name
759: * @return boolean
760: */
761: public function hasOwnProperty($name)
762: {
763: return false;
764: }
765:
766: /**
767: * Returns properties declared by this class, not its parents.
768: *
769: * @param integer $filter Properties filter
770: * @return array
771: */
772: public function getOwnProperties($filter = null)
773: {
774: return array();
775: }
776:
777: /**
778: * Returns if the class imports the given property from traits.
779: *
780: * @param string $name Property name
781: * @return boolean
782: */
783: public function hasTraitProperty($name)
784: {
785: return false;
786: }
787:
788: /**
789: * Returns property reflections imported from traits.
790: *
791: * @param integer $filter Properties filter
792: * @return array
793: */
794: public function getTraitProperties($filter = null)
795: {
796: return array();
797: }
798:
799: /**
800: * Returns static properties reflections.
801: *
802: * @return array
803: */
804: public function getStaticProperties()
805: {
806: return array();
807: }
808:
809: /**
810: * Returns a value of a static property.
811: *
812: * @param string $name Property name
813: * @param mixed $default Default value
814: * @throws \TokenReflection\Exception\RuntimeException If the requested static property does not exist.
815: */
816: public function getStaticPropertyValue($name, $default = null)
817: {
818: throw new Exception\RuntimeException(sprintf('There is no static property "%s".', $name), Exception\RuntimeException::DOES_NOT_EXIST, $this);
819: }
820:
821: /**
822: * Returns reflections of direct subclasses.
823: *
824: * @return array
825: */
826: public function getDirectSubclasses()
827: {
828: return array();
829: }
830:
831: /**
832: * Returns names of direct subclasses.
833: *
834: * @return array
835: */
836: public function getDirectSubclassNames()
837: {
838: return array();
839: }
840:
841: /**
842: * Returns reflections of indirect subclasses.
843: *
844: * @return array
845: */
846: public function getIndirectSubclasses()
847: {
848: return array();
849: }
850:
851: /**
852: * Returns names of indirect subclasses.
853: *
854: * @return array
855: */
856: public function getIndirectSubclassNames()
857: {
858: return array();
859: }
860:
861: /**
862: * Returns reflections of classes directly implementing this interface.
863: *
864: * @return array
865: */
866: public function getDirectImplementers()
867: {
868: return array();
869: }
870:
871: /**
872: * Returns names of classes directly implementing this interface.
873: *
874: * @return array
875: */
876: public function getDirectImplementerNames()
877: {
878: return array();
879: }
880:
881: /**
882: * Returns reflections of classes indirectly implementing this interface.
883: *
884: * @return array
885: */
886: public function getIndirectImplementers()
887: {
888: return array();
889: }
890:
891: /**
892: * Returns names of classes indirectly implementing this interface.
893: *
894: * @return array
895: */
896: public function getIndirectImplementerNames()
897: {
898: return array();
899: }
900:
901: /**
902: * Returns if the given object is an instance of this class.
903: *
904: * @param object $object Instance
905: * @return boolean
906: * @throws \TokenReflection\Exception\RuntimeException If the provided argument is not an object.
907: */
908: public function isInstance($object)
909: {
910: if (!is_object($object)) {
911: throw new Exception\RuntimeException(sprintf('Parameter must be a class instance, "%s" provided.', gettype($object)), Exception\RuntimeException::INVALID_ARGUMENT, $this);
912: }
913:
914: return $this->name === get_class($object) || is_subclass_of($object, $this->name);
915: }
916:
917: /**
918: * Creates a new class instance without using a constructor.
919: *
920: * @return object
921: * @throws \TokenReflection\Exception\RuntimeException If the class inherits from an internal class.
922: */
923: public function newInstanceWithoutConstructor()
924: {
925: if (!class_exists($this->name, true)) {
926: throw new Exception\RuntimeException('Could not create an instance; class does not exist.', Exception\RuntimeException::DOES_NOT_EXIST, $this);
927: }
928:
929: $reflection = new \TokenReflection\Php\ReflectionClass($this->name, $this->getBroker());
930: return $reflection->newInstanceWithoutConstructor();
931: }
932:
933: /**
934: * Creates a new instance using variable number of parameters.
935: *
936: * Use any number of constructor parameters as function parameters.
937: *
938: * @param mixed $args
939: * @return object
940: */
941: public function newInstance($args)
942: {
943: return $this->newInstanceArgs(func_get_args());
944: }
945:
946: /**
947: * Creates a new instance using an array of parameters.
948: *
949: * @param array $args Array of constructor parameters
950: * @return object
951: * @throws \TokenReflection\Exception\RuntimeException If the required class does not exist.
952: */
953: public function newInstanceArgs(array $args = array())
954: {
955: if (!class_exists($this->name, true)) {
956: throw new Exception\RuntimeException('Could not create an instance of class; class does not exist.', Exception\RuntimeException::DOES_NOT_EXIST, $this);
957: }
958:
959: $reflection = new InternalReflectionClass($this->name);
960: return $reflection->newInstanceArgs($args);
961: }
962:
963: /**
964: * Sets a static property value.
965: *
966: * @param string $name Property name
967: * @param mixed $value Property value
968: * @throws \TokenReflection\Exception\RuntimeException If the requested static property does not exist.
969: */
970: public function setStaticPropertyValue($name, $value)
971: {
972: throw new Exception\RuntimeException(sprintf('There is no static property "%s".', $name), Exception\RuntimeException::DOES_NOT_EXIST, $this);
973: }
974:
975: /**
976: * Returns the string representation of the reflection object.
977: *
978: * @return string
979: */
980: public function __toString()
981: {
982: return sprintf(
983: "Class|Interface [ <user> class|interface %s ] {\n %s%s%s%s%s\n}\n",
984: $this->getName(),
985: "\n\n - Constants [0] {\n }",
986: "\n\n - Static properties [0] {\n }",
987: "\n\n - Static methods [0] {\n }",
988: "\n\n - Properties [0] {\n }",
989: "\n\n - Methods [0] {\n }"
990: );
991: }
992:
993: /**
994: * Exports a reflected object.
995: *
996: * @param \TokenReflection\Broker $broker Broker instance
997: * @param string|object $className Class name or class instance
998: * @param boolean $return Return the export instead of outputting it
999: * @return string|null
1000: * @throws \TokenReflection\Exception\RuntimeException If requested parameter doesn't exist.
1001: */
1002: public static function export(Broker $broker, $className, $return = false)
1003: {
1004: TokenReflection\ReflectionClass::export($broker, $className, $return);
1005: }
1006:
1007: /**
1008: * Outputs the reflection subject source code.
1009: *
1010: * @return string
1011: */
1012: public function getSource()
1013: {
1014: return '';
1015: }
1016:
1017: /**
1018: * Returns the start position in the file token stream.
1019: *
1020: * @return integer
1021: */
1022: public function getStartPosition()
1023: {
1024: return -1;
1025: }
1026:
1027: /**
1028: * Returns the end position in the file token stream.
1029: *
1030: * @return integer
1031: */
1032: public function getEndPosition()
1033: {
1034: return -1;
1035: }
1036:
1037: /**
1038: * Returns if the class definition is complete.
1039: *
1040: * Invalid classes are always complete.
1041: *
1042: * @return boolean
1043: */
1044: public function isComplete()
1045: {
1046: return true;
1047: }
1048:
1049: /**
1050: * Returns if the class definition is valid.
1051: *
1052: * @return boolean
1053: */
1054: public function isValid()
1055: {
1056: return false;
1057: }
1058:
1059: /**
1060: * Returns if the reflection subject is deprecated.
1061: *
1062: * @return boolean
1063: */
1064: public function isDeprecated()
1065: {
1066: return false;
1067: }
1068:
1069: /**
1070: * Returns the reflection broker used by this reflection object.
1071: *
1072: * @return \TokenReflection\Broker
1073: */
1074: public function getBroker()
1075: {
1076: return $this->broker;
1077: }
1078:
1079: /**
1080: * Magic __get method.
1081: *
1082: * @param string $key Variable name
1083: * @return mixed
1084: */
1085: final public function __get($key)
1086: {
1087: return ReflectionBase::get($this, $key);
1088: }
1089:
1090: /**
1091: * Magic __isset method.
1092: *
1093: * @param string $key Variable name
1094: * @return boolean
1095: */
1096: final public function __isset($key)
1097: {
1098: return ReflectionBase::exists($this, $key);
1099: }
1100: }
1101: