/Builder/libs/ApiGen/TokenReflection/ReflectionConstant.php

https://github.com/PetrP/Orm · PHP · 339 lines · 160 code · 42 blank · 137 comment · 26 complexity · acc61281c09ee2f12748cc45cfce7f93 MD5 · raw file

  1. <?php
  2. /**
  3. * PHP Token Reflection
  4. *
  5. * Version 1.0.0 RC 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. namespace TokenReflection;
  16. /**
  17. * Tokenized constant reflection.
  18. */
  19. class ReflectionConstant extends ReflectionBase implements IReflectionConstant
  20. {
  21. /**
  22. * Name of the declaring class.
  23. *
  24. * @var String
  25. */
  26. private $declaringClassName;
  27. /**
  28. * Constant namespace name.
  29. *
  30. * @var string
  31. */
  32. private $namespaceName;
  33. /**
  34. * Constant value.
  35. *
  36. * @var mixed
  37. */
  38. private $value;
  39. /**
  40. * Constant value definition in tokens.
  41. *
  42. * @var array|string
  43. */
  44. private $valueDefinition = array();
  45. /**
  46. * Imported namespace/class aliases.
  47. *
  48. * @var array
  49. */
  50. private $aliases = array();
  51. /**
  52. * Returns the unqualified name (UQN).
  53. *
  54. * @return string
  55. */
  56. public function getShortName()
  57. {
  58. $name = $this->getName();
  59. if (null !== $this->namespaceName && $this->namespaceName !== ReflectionNamespace::NO_NAMESPACE_NAME) {
  60. $name = substr($name, strlen($this->namespaceName) + 1);
  61. }
  62. return $name;
  63. }
  64. /**
  65. * Returns the name of the declaring class.
  66. *
  67. * @return string|null
  68. */
  69. public function getDeclaringClassName()
  70. {
  71. return $this->declaringClassName;
  72. }
  73. /**
  74. * Returns a reflection of the declaring class.
  75. *
  76. * @return \TokenReflection\ReflectionClass|null
  77. */
  78. public function getDeclaringClass()
  79. {
  80. if (null === $this->declaringClassName) {
  81. return null;
  82. }
  83. return $this->getBroker()->getClass($this->declaringClassName);
  84. }
  85. /**
  86. * Returns the namespace name.
  87. *
  88. * @return string
  89. */
  90. public function getNamespaceName()
  91. {
  92. return null === $this->namespaceName || $this->namespaceName === ReflectionNamespace::NO_NAMESPACE_NAME ? '' : $this->namespaceName;
  93. }
  94. /**
  95. * Returns if the class is defined within a namespace.
  96. *
  97. * @return boolean
  98. */
  99. public function inNamespace()
  100. {
  101. return '' !== $this->getNamespaceName();
  102. }
  103. /**
  104. * Returns the constant value.
  105. *
  106. * @return mixed
  107. */
  108. public function getValue()
  109. {
  110. if (is_array($this->valueDefinition)) {
  111. $this->value = Resolver::getValueDefinition($this->valueDefinition, $this);
  112. $this->valueDefinition = Resolver::getSourceCode($this->valueDefinition);
  113. }
  114. return $this->value;
  115. }
  116. /**
  117. * Returns the constant value definition.
  118. *
  119. * @return string
  120. */
  121. public function getValueDefinition()
  122. {
  123. return is_array($this->valueDefinition) ? Resolver::getSourceCode($this->valueDefinition) : $this->valueDefinition;
  124. }
  125. /**
  126. * Returns the originaly provided value definition.
  127. *
  128. * @return string
  129. */
  130. public function getOriginalValueDefinition()
  131. {
  132. return $this->valueDefinition;
  133. }
  134. /**
  135. * Returns the string representation of the reflection object.
  136. *
  137. * @return string
  138. */
  139. public function __toString()
  140. {
  141. return sprintf(
  142. "Constant [ %s %s ] { %s }\n",
  143. strtolower(gettype($this->getValue())),
  144. $this->getName(),
  145. $this->getValue()
  146. );
  147. }
  148. /**
  149. * Exports a reflected object.
  150. *
  151. * @param \TokenReflection\Broker $broker Broker instance
  152. * @param string|object|null $class Class name, class instance or null
  153. * @param string $constant Constant name
  154. * @param boolean $return Return the export instead of outputting it
  155. * @return string|null
  156. * @throws \TokenReflection\Exception\Runtime If requested parameter doesn't exist
  157. */
  158. public static function export(Broker $broker, $class, $constant, $return = false)
  159. {
  160. $className = is_object($class) ? get_class($class) : $class;
  161. $constantName = $constant;
  162. if (null === $className) {
  163. $constant = $broker->getConstant($constantName);
  164. if (null === $constant) {
  165. throw new Exception\Runtime(sprintf('Constant %s does not exist.', $constantName), Exception\Runtime::DOES_NOT_EXIST);
  166. }
  167. } else {
  168. $class = $broker->getClass($className);
  169. if ($class instanceof Dummy\ReflectionClass) {
  170. throw new Exception\Runtime(sprintf('Class %s does not exist.', $className), Exception\Runtime::DOES_NOT_EXIST);
  171. }
  172. $constant = $class->getConstantReflection($constantName);
  173. }
  174. if ($return) {
  175. return $constant->__toString();
  176. }
  177. echo $constant->__toString();
  178. }
  179. /**
  180. * Returns imported namespaces and aliases from the declaring namespace.
  181. *
  182. * @return array
  183. */
  184. public function getNamespaceAliases()
  185. {
  186. return null === $this->declaringClassName ? $this->aliases : $this->getDeclaringClass()->getNamespaceAliases();
  187. }
  188. /**
  189. * Processes the parent reflection object.
  190. *
  191. * @param \TokenReflection\IReflection $parent Parent reflection object
  192. * @return \TokenReflection\ReflectionBase
  193. * @throws \TokenReflection\Exception\Parse If an invalid parent reflection object was provided
  194. */
  195. protected function processParent(IReflection $parent)
  196. {
  197. if ($parent instanceof ReflectionFileNamespace) {
  198. $this->namespaceName = $parent->getName();
  199. $this->aliases = $parent->getNamespaceAliases();
  200. } elseif ($parent instanceof ReflectionClass) {
  201. $this->declaringClassName = $parent->getName();
  202. } else {
  203. throw new Exception\Parse(sprintf('The parent object has to be an instance of TokenReflection\ReflectionFileNamespace or TokenReflection\ReflectionClass, "%s" given.', get_class($parent)), Exception\Parse::INVALID_PARENT);
  204. }
  205. return parent::processParent($parent);
  206. }
  207. /**
  208. * Find the appropriate docblock.
  209. *
  210. * @param \TokenReflection\Stream $tokenStream Token substream
  211. * @param \TokenReflection\IReflection $parent Parent reflection
  212. * @return \TokenReflection\ReflectionConstant
  213. */
  214. protected function parseDocComment(Stream $tokenStream, IReflection $parent)
  215. {
  216. $position = $tokenStream->key() - 1;
  217. while ($position > 0 && !$tokenStream->is(T_CONST, $position)) {
  218. $position--;
  219. }
  220. $actual = $tokenStream->key();
  221. parent::parseDocComment($tokenStream->seek($position), $parent);
  222. $tokenStream->seek($actual);
  223. return $this;
  224. }
  225. /**
  226. * Parses reflected element metadata from the token stream.
  227. *
  228. * @param \TokenReflection\Stream $tokenStream Token substream
  229. * @param \TokenReflection\IReflection $parent Parent reflection object
  230. * @return \TokenReflection\ReflectionConstant
  231. */
  232. protected function parse(Stream $tokenStream, IReflection $parent)
  233. {
  234. return $this
  235. ->parseName($tokenStream)
  236. ->parseValue($tokenStream, $parent);
  237. }
  238. /**
  239. * Parses the constant name.
  240. *
  241. * @param \TokenReflection\Stream $tokenStream Token substream
  242. * @return \TokenReflection\ReflectionConstant
  243. * @throws \TokenReflection\Exception\Parse If the constant name could not be determined
  244. */
  245. protected function parseName(Stream $tokenStream)
  246. {
  247. try {
  248. if ($tokenStream->is(T_CONST)) {
  249. $tokenStream->skipWhitespaces();
  250. }
  251. if (!$tokenStream->is(T_STRING)) {
  252. throw new Exception\Parse('The constant name could not be determined.', Exception\Parse::PARSE_ELEMENT_ERROR);
  253. }
  254. if (null === $this->namespaceName || $this->namespaceName === ReflectionNamespace::NO_NAMESPACE_NAME) {
  255. $this->name = $tokenStream->getTokenValue();
  256. } else {
  257. $this->name = $this->namespaceName . '\\' . $tokenStream->getTokenValue();
  258. }
  259. $tokenStream->skipWhitespaces();
  260. return $this;
  261. } catch (Exception $e) {
  262. throw new Exception\Parse('Could not parse constant name.', Exception\Parse::PARSE_ELEMENT_ERROR, $e);
  263. }
  264. }
  265. /**
  266. * Parses the constant value.
  267. *
  268. * @param \TokenReflection\Stream $tokenStream Token substream
  269. * @param \TokenReflection\IReflection $parent Parent reflection object
  270. * @return \TokenReflection\ReflectionConstant
  271. * @throws \TokenReflection\Exception\Parse If the constant value could not be determined
  272. */
  273. private function parseValue(Stream $tokenStream, IReflection $parent)
  274. {
  275. try {
  276. if (!$tokenStream->is('=')) {
  277. throw new Exception\Parse('Could not find the definition start.', Exception\Parse::PARSE_ELEMENT_ERROR);
  278. }
  279. $tokenStream->skipWhitespaces();
  280. static $acceptedTokens = array('-' => true, '+' => true, T_STRING => true, T_NS_SEPARATOR => true, T_CONSTANT_ENCAPSED_STRING => true, T_DNUMBER => true, T_LNUMBER => true, T_DOUBLE_COLON => true);
  281. while (null !== ($type = $tokenStream->getType()) && isset($acceptedTokens[$type])) {
  282. $this->valueDefinition[] = $tokenStream->current();
  283. $tokenStream->next();
  284. }
  285. if (empty($this->valueDefinition)) {
  286. throw new Exception\Parse('Value definition is empty.', Exception\Parse::PARSE_ELEMENT_ERROR);
  287. }
  288. $value = $tokenStream->getTokenValue();
  289. if (null === $type || (',' !== $value && ';' !== $value)) {
  290. throw new Exception\Parse(sprintf('Invalid value definition: "%s".', $this->valueDefinition), Exception\Parse::PARSE_ELEMENT_ERROR);
  291. }
  292. return $this;
  293. } catch (Exception $e) {
  294. throw new Exception\Parse('Could not parse constant value.', Exception\Parse::PARSE_ELEMENT_ERROR, $e);
  295. }
  296. }
  297. }