1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: namespace TokenReflection;
17:
18: use TokenReflection\Stream\StreamBase as Stream, TokenReflection\Exception;
19:
20: 21: 22:
23: class ReflectionConstant extends ReflectionElement implements IReflectionConstant
24: {
25: 26: 27: 28: 29:
30: private $declaringClassName;
31:
32: 33: 34: 35: 36:
37: private $namespaceName;
38:
39: 40: 41: 42: 43:
44: private $value;
45:
46: 47: 48: 49: 50:
51: private $valueDefinition = array();
52:
53: 54: 55: 56: 57:
58: private $aliases = array();
59:
60: 61: 62: 63: 64:
65: public function getShortName()
66: {
67: $name = $this->getName();
68: if (null !== $this->namespaceName && $this->namespaceName !== ReflectionNamespace::NO_NAMESPACE_NAME) {
69: $name = substr($name, strlen($this->namespaceName) + 1);
70: }
71:
72: return $name;
73: }
74:
75: 76: 77: 78: 79:
80: public function getDeclaringClassName()
81: {
82: return $this->declaringClassName;
83: }
84:
85: 86: 87: 88: 89:
90: public function getDeclaringClass()
91: {
92: if (null === $this->declaringClassName) {
93: return null;
94: }
95:
96: return $this->getBroker()->getClass($this->declaringClassName);
97: }
98:
99: 100: 101: 102: 103:
104: public function getNamespaceName()
105: {
106: return null === $this->namespaceName || $this->namespaceName === ReflectionNamespace::NO_NAMESPACE_NAME ? '' : $this->namespaceName;
107: }
108:
109: 110: 111: 112: 113:
114: public function inNamespace()
115: {
116: return '' !== $this->getNamespaceName();
117: }
118:
119: 120: 121: 122: 123:
124: public function getValue()
125: {
126: if (is_array($this->valueDefinition)) {
127: $this->value = Resolver::getValueDefinition($this->valueDefinition, $this);
128: $this->valueDefinition = Resolver::getSourceCode($this->valueDefinition);
129: }
130:
131: return $this->value;
132: }
133:
134: 135: 136: 137: 138:
139: public function getValueDefinition()
140: {
141: return is_array($this->valueDefinition) ? Resolver::getSourceCode($this->valueDefinition) : $this->valueDefinition;
142: }
143:
144: 145: 146: 147: 148:
149: public function getOriginalValueDefinition()
150: {
151: return $this->valueDefinition;
152: }
153:
154: 155: 156: 157: 158:
159: public function __toString()
160: {
161: return sprintf(
162: "Constant [ %s %s ] { %s }\n",
163: strtolower(gettype($this->getValue())),
164: $this->getName(),
165: $this->getValue()
166: );
167: }
168:
169: 170: 171: 172: 173: 174: 175: 176: 177: 178:
179: public static function export(Broker $broker, $class, $constant, $return = false)
180: {
181: $className = is_object($class) ? get_class($class) : $class;
182: $constantName = $constant;
183:
184: if (null === $className) {
185: $constant = $broker->getConstant($constantName);
186: if (null === $constant) {
187: throw new Exception\RuntimeException('Constant does not exist.', Exception\RuntimeException::DOES_NOT_EXIST);
188: }
189: } else {
190: $class = $broker->getClass($className);
191: if ($class instanceof Invalid\ReflectionClass) {
192: throw new Exception\RuntimeException('Class is invalid.', Exception\RuntimeException::UNSUPPORTED);
193: } elseif ($class instanceof Dummy\ReflectionClass) {
194: throw new Exception\RuntimeException('Class does not exist.', Exception\RuntimeException::DOES_NOT_EXIST, $class);
195: }
196: $constant = $class->getConstantReflection($constantName);
197: }
198:
199: if ($return) {
200: return $constant->__toString();
201: }
202:
203: echo $constant->__toString();
204: }
205:
206: 207: 208: 209: 210:
211: public function getNamespaceAliases()
212: {
213: return null === $this->declaringClassName ? $this->aliases : $this->getDeclaringClass()->getNamespaceAliases();
214: }
215:
216: 217: 218: 219: 220:
221: public function getPrettyName()
222: {
223: return null === $this->declaringClassName ? parent::getPrettyName() : sprintf('%s::%s', $this->declaringClassName, $this->name);
224: }
225:
226: 227: 228: 229: 230:
231: public function isValid()
232: {
233: return true;
234: }
235:
236: 237: 238: 239: 240: 241: 242: 243:
244: protected function processParent(IReflection $parent, Stream $tokenStream)
245: {
246: if ($parent instanceof ReflectionFileNamespace) {
247: $this->namespaceName = $parent->getName();
248: $this->aliases = $parent->getNamespaceAliases();
249: } elseif ($parent instanceof ReflectionClass) {
250: $this->declaringClassName = $parent->getName();
251: } else {
252: throw new Exception\ParseException($this, $tokenStream, sprintf('Invalid parent reflection provided: "%s".', get_class($parent)), Exception\ParseException::INVALID_PARENT);
253: }
254:
255: return parent::processParent($parent, $tokenStream);
256: }
257:
258: 259: 260: 261: 262: 263: 264:
265: protected function (Stream $tokenStream, IReflection $parent)
266: {
267: $position = $tokenStream->key() - 1;
268: while ($position > 0 && !$tokenStream->is(T_CONST, $position)) {
269: $position--;
270: }
271:
272: $actual = $tokenStream->key();
273:
274: parent::parseDocComment($tokenStream->seek($position), $parent);
275:
276: $tokenStream->seek($actual);
277:
278: return $this;
279: }
280:
281: 282: 283: 284: 285: 286: 287:
288: protected function parse(Stream $tokenStream, IReflection $parent)
289: {
290: if ($tokenStream->is(T_CONST)) {
291: $tokenStream->skipWhitespaces(true);
292: }
293:
294: if (false === $this->docComment->getDocComment()) {
295: parent::parseDocComment($tokenStream, $parent);
296: }
297:
298: return $this
299: ->parseName($tokenStream)
300: ->parseValue($tokenStream, $parent);
301: }
302:
303: 304: 305: 306: 307: 308: 309:
310: protected function parseName(Stream $tokenStream)
311: {
312: if (!$tokenStream->is(T_STRING)) {
313: throw new Exception\ParseException($this, $tokenStream, 'The constant name could not be determined.', Exception\ParseException::LOGICAL_ERROR);
314: }
315:
316: if (null === $this->namespaceName || $this->namespaceName === ReflectionNamespace::NO_NAMESPACE_NAME) {
317: $this->name = $tokenStream->getTokenValue();
318: } else {
319: $this->name = $this->namespaceName . '\\' . $tokenStream->getTokenValue();
320: }
321:
322: $tokenStream->skipWhitespaces(true);
323:
324: return $this;
325: }
326:
327: 328: 329: 330: 331: 332: 333: 334:
335: private function parseValue(Stream $tokenStream, IReflection $parent)
336: {
337: if (!$tokenStream->is('=')) {
338: throw new Exception\ParseException($this, $tokenStream, 'Could not find the definition start.', Exception\ParseException::UNEXPECTED_TOKEN);
339: }
340:
341: $tokenStream->skipWhitespaces(true);
342:
343: static $acceptedTokens = array(
344: '-' => true,
345: '+' => true,
346: T_STRING => true,
347: T_NS_SEPARATOR => true,
348: T_CONSTANT_ENCAPSED_STRING => true,
349: T_DNUMBER => true,
350: T_LNUMBER => true,
351: T_DOUBLE_COLON => true,
352: T_CLASS_C => true,
353: T_DIR => true,
354: T_FILE => true,
355: T_FUNC_C => true,
356: T_LINE => true,
357: T_METHOD_C => true,
358: T_NS_C => true,
359: T_TRAIT_C => true
360: );
361:
362: while (null !== ($type = $tokenStream->getType())) {
363: if (T_START_HEREDOC === $type) {
364: $this->valueDefinition[] = $tokenStream->current();
365: while (null !== $type && T_END_HEREDOC !== $type) {
366: $tokenStream->next();
367: $this->valueDefinition[] = $tokenStream->current();
368: $type = $tokenStream->getType();
369: };
370: $tokenStream->next();
371: } elseif (isset($acceptedTokens[$type])) {
372: $this->valueDefinition[] = $tokenStream->current();
373: $tokenStream->next();
374: } elseif ($tokenStream->isWhitespace(true)) {
375: $tokenStream->skipWhitespaces(true);
376: } else {
377: break;
378: }
379: }
380:
381: if (empty($this->valueDefinition)) {
382: throw new Exception\ParseException($this, $tokenStream, 'Value definition is empty.', Exception\ParseException::LOGICAL_ERROR);
383: }
384:
385: $value = $tokenStream->getTokenValue();
386: if (null === $type || (',' !== $value && ';' !== $value)) {
387: throw new Exception\ParseException($this, $tokenStream, 'Invalid value definition.', Exception\ParseException::LOGICAL_ERROR);
388: }
389:
390: return $this;
391: }
392: }
393: