PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/DocBlox/Plugin/Core/Parser/DocBlock/Tag/Definition.php

http://github.com/mvriel/Docblox
PHP | 422 lines | 344 code | 15 blank | 63 comment | 11 complexity | d3e01d5bb2b5e7eaaa7ab8ef623cf7d9 MD5 | raw file
Possible License(s): LGPL-3.0, BSD-3-Clause, CC-BY-SA-3.0
  1. <?php
  2. /**
  3. * DocBlox
  4. *
  5. * PHP Version 5
  6. *
  7. * @category DocBlox
  8. * @package Parser
  9. * @subpackage Tag_Definitions
  10. * @author Mike van Riel <mike.vanriel@naenius.com>
  11. * @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT
  13. * @link http://docblox-project.org
  14. */
  15. /**
  16. * Generic Definition which adds the basic tag information to the structure file.
  17. *
  18. * @category DocBlox
  19. * @package Parser
  20. * @subpackage Tag_Definitions
  21. * @author Mike van Riel <mike.vanriel@naenius.com>
  22. * @license http://www.opensource.org/licenses/mit-license.php MIT
  23. * @link http://docblox-project.org
  24. */
  25. class DocBlox_Plugin_Core_Parser_DocBlock_Tag_Definition
  26. extends DocBlox_Parser_Abstract
  27. {
  28. /** @var SimpleXMLElement */
  29. protected $xml = null;
  30. /** @var DocBlox_Reflection_DocBlock_Tag */
  31. protected $tag = null;
  32. /**
  33. * @var string
  34. */
  35. protected $namespace = '';
  36. /**
  37. * @var array
  38. */
  39. protected $namespace_aliases = array();
  40. /**
  41. * Initializes this object with the given data and sets the name and
  42. * description.
  43. *
  44. * @param string $namespace Namespace where
  45. * this tag occurs.
  46. * @param string[] $namespace_aliases Aliases used
  47. * for all namespaces at the location of this tag.
  48. * @param SimpleXMLElement $xml XML to enhance.
  49. * @param DocBlox_Reflection_DocBlock_Tag $tag Tag object to
  50. * use.
  51. */
  52. public function __construct(
  53. $namespace, $namespace_aliases, SimpleXMLElement $xml,
  54. DocBlox_Reflection_DocBlock_Tag $tag
  55. ) {
  56. $this->xml = $xml;
  57. $this->tag = $tag;
  58. $this->setNamespace($namespace);
  59. $this->setNamespaceAliases($namespace_aliases);
  60. $this->setName($this->tag->getName());
  61. $this->setDescription($this->tag->getDescription());
  62. if (method_exists($this->tag, 'getTypes')) {
  63. $this->setTypes($this->tag->getTypes());
  64. }
  65. if (method_exists($this->tag, 'getReference')) {
  66. $this->setReference($this->tag->getReference());
  67. }
  68. }
  69. /**
  70. * Creates a new instance of this class or one of the specialized sub-classes.
  71. *
  72. * @param string $namespace Namespace where
  73. * this tag occurs.
  74. * @param string[] $namespace_aliases Aliases used
  75. * for all namespaces at the location of this tag.
  76. * @param SimpleXMLElement $xml Root xml element
  77. * for this tag.
  78. * @param DocBlox_Reflection_DocBlock_Tag $tag The actual tag
  79. * as reflected.
  80. *
  81. * @todo replace the switch statement with an intelligent container /
  82. * plugin system.
  83. *
  84. * @return DocBlox_Parser_DocBlock_Tag_Definition
  85. */
  86. public static function create(
  87. $namespace, $namespace_aliases, SimpleXMLElement $xml,
  88. DocBlox_Reflection_DocBlock_Tag $tag
  89. ) {
  90. $tag_name = $tag->getName();
  91. // check whether the tag name is namespaced and replace alias with full
  92. // name to get the FQCN form
  93. if (strpos($tag_name, '\\') !== false) {
  94. $tag_name = explode('\\', $tag_name);
  95. if ((count($tag_name) > 1)
  96. && isset($namespace_aliases[$tag_name[0]])
  97. ) {
  98. $tag_name[0] = $namespace_aliases[$tag_name[0]];
  99. }
  100. $tag_name = implode('\\', $tag_name);
  101. if ($tag_name[0] != '\\') {
  102. $tag_name = '\\' . $tag_name;
  103. }
  104. }
  105. switch ($tag_name)
  106. {
  107. case 'property-write':
  108. case 'property-read':
  109. case 'property':
  110. case 'param':
  111. $def = new DocBlox_Plugin_Core_Parser_DocBlock_Tag_Definition_Param(
  112. $namespace, $namespace_aliases, $xml, $tag
  113. );
  114. break;
  115. case 'see':
  116. $def = new DocBlox_Plugin_Core_Parser_DocBlock_Tag_Definition_See(
  117. $namespace, $namespace_aliases, $xml, $tag
  118. );
  119. break;
  120. case 'method':
  121. $def = new DocBlox_Plugin_Core_Parser_DocBlock_Tag_Definition_Method(
  122. $namespace, $namespace_aliases, $xml, $tag
  123. );
  124. break;
  125. case 'uses':
  126. $def = new DocBlox_Plugin_Core_Parser_DocBlock_Tag_Definition_Uses(
  127. $namespace, $namespace_aliases, $xml, $tag
  128. );
  129. break;
  130. case 'link':
  131. $def = new DocBlox_Plugin_Core_Parser_DocBlock_Tag_Definition_Link(
  132. $namespace, $namespace_aliases, $xml, $tag
  133. );
  134. break;
  135. case '\Doctrine\ORM\Mapping\column':
  136. case '\Doctrine\ORM\Mapping\ChangeTrackingPolicy':
  137. case '\Doctrine\ORM\Mapping\DiscriminatorColumn':
  138. case '\Doctrine\ORM\Mapping\DiscriminatorMap':
  139. case '\Doctrine\ORM\Mapping\Entity':
  140. case '\Doctrine\ORM\Mapping\GeneratedValue':
  141. case '\Doctrine\ORM\Mapping\HasLifecycleCallbacks':
  142. case '\Doctrine\ORM\Mapping\Id':
  143. case '\Doctrine\ORM\Mapping\InheritanceType':
  144. case '\Doctrine\ORM\Mapping\JoinColumn':
  145. case '\Doctrine\ORM\Mapping\JoinTable':
  146. case '\Doctrine\ORM\Mapping\ManyToOne':
  147. case '\Doctrine\ORM\Mapping\ManyToMany':
  148. case '\Doctrine\ORM\Mapping\MappedSuperclass':
  149. case '\Doctrine\ORM\Mapping\OneToOne':
  150. case '\Doctrine\ORM\Mapping\OneToMany':
  151. case '\Doctrine\ORM\Mapping\OrderBy':
  152. case '\Doctrine\ORM\Mapping\PostLoad':
  153. case '\Doctrine\ORM\Mapping\PostPersist':
  154. case '\Doctrine\ORM\Mapping\PostRemove':
  155. case '\Doctrine\ORM\Mapping\PostUpdate':
  156. case '\Doctrine\ORM\Mapping\PrePersist':
  157. case '\Doctrine\ORM\Mapping\PreRemove':
  158. case '\Doctrine\ORM\Mapping\PreUpdate':
  159. case '\Doctrine\ORM\Mapping\SequenceGenerator':
  160. case '\Doctrine\ORM\Mapping\Table':
  161. case '\Doctrine\ORM\Mapping\UniqueConstraint':
  162. case '\Doctrine\ORM\Mapping\Version':
  163. case 'Column':
  164. case 'ChangeTrackingPolicy':
  165. case 'DiscriminatorColumn':
  166. case 'DiscriminatorMap':
  167. case 'Entity':
  168. case 'GeneratedValue':
  169. case 'HasLifecycleCallbacks':
  170. case 'Id':
  171. case 'InheritanceType':
  172. case 'JoinColumn':
  173. case 'JoinTable':
  174. case 'ManyToOne':
  175. case 'ManyToMany':
  176. case 'MappedSuperclass':
  177. case 'OneToOne':
  178. case 'OneToMany':
  179. case 'OrderBy':
  180. case 'PostLoad':
  181. case 'PostPersist':
  182. case 'PostRemove':
  183. case 'PostUpdate':
  184. case 'PrePersist':
  185. case 'PreRemove':
  186. case 'PreUpdate':
  187. case 'SequenceGenerator':
  188. case 'Table':
  189. case 'UniqueConstraint':
  190. case 'Version':
  191. $def = new DocBlox_Plugin_Core_Parser_DocBlock_Tag_Definition_Doctrine(
  192. $namespace, $namespace_aliases, $xml, $tag
  193. );
  194. break;
  195. default:
  196. $def = new self(
  197. $namespace, $namespace_aliases, $xml, $tag
  198. );
  199. break;
  200. }
  201. $def->configure();
  202. return $def;
  203. }
  204. /**
  205. * Hook method where children can extend the structure with extra information.
  206. *
  207. * @return void
  208. */
  209. protected function configure()
  210. {
  211. }
  212. /**
  213. * Setter for the name so it can be overridden.
  214. *
  215. * @param string $name Name for this definition.
  216. *
  217. * @return void
  218. */
  219. public function setName($name)
  220. {
  221. $this->xml['name'] = $name;
  222. }
  223. /**
  224. * Setter for the reference so it can be overridden.
  225. *
  226. * @param string $name Name of the element to which is referred.
  227. *
  228. * @return void
  229. */
  230. public function setReference($name)
  231. {
  232. $this->xml['refers'] = $name;
  233. }
  234. /**
  235. * Setter for the description so it can be overridden.
  236. *
  237. * @param string $description Description for this definition.
  238. *
  239. * @return void
  240. */
  241. public function setDescription($description)
  242. {
  243. $this->xml['description'] = trim($description);
  244. }
  245. /**
  246. * Sets the namespace for this tag; is used to determine type info.
  247. *
  248. * @param string $namespace Namespace name for this definition.
  249. *
  250. * @return void
  251. */
  252. public function setNamespace($namespace)
  253. {
  254. $this->namespace = $namespace;
  255. }
  256. /**
  257. * Returns the namespace identifier for this tag.
  258. *
  259. * @return string
  260. */
  261. public function getNamespace()
  262. {
  263. return $this->namespace;
  264. }
  265. /**
  266. * Adds type information to the structure.
  267. *
  268. * @param string[] $types Array with types in any format; will be transformed
  269. * to FQCN.
  270. *
  271. * @todo Move this method to a better spot with namespace and alias access
  272. * (together with namespace and alias stuff).
  273. *
  274. * @return void
  275. */
  276. public function setTypes($types)
  277. {
  278. foreach ($types as $type) {
  279. if ($type == '') {
  280. continue;
  281. }
  282. $type = trim($this->expandType($type));
  283. // strip ampersands
  284. $name = str_replace('&', '', $type);
  285. $type_object = $this->xml->addChild('type', $name);
  286. // register whether this variable is by reference by checking
  287. // the first and last character
  288. $type_object['by_reference'] = ((substr($type, 0, 1) === '&')
  289. || (substr($type, -1) === '&'))
  290. ? 'true'
  291. : 'false';
  292. }
  293. $this->xml['type'] = $this->expandType($this->tag->getType());
  294. }
  295. /**
  296. * Tries to expand a type to it's full namespaced equivalent.
  297. *
  298. * @param string $type Type to expand into full namespaced
  299. * equivalent.
  300. * @param bool $ignore_non_objects whether to ignore reserved words, when
  301. * false it will not expand a set of keywords.
  302. *
  303. * @return string
  304. */
  305. protected function expandType($type, $ignore_non_objects = false)
  306. {
  307. if ($type === null) {
  308. return null;
  309. }
  310. $non_objects = array();
  311. if (!$ignore_non_objects) {
  312. $non_objects = array(
  313. 'string', 'int', 'integer', 'bool', 'boolean', 'float', 'double',
  314. 'object', 'mixed', 'array', 'resource', 'void', 'null',
  315. 'callback', 'false', 'true'
  316. );
  317. }
  318. $namespace = $this->getNamespace() == 'default'
  319. ? ''
  320. : $this->getNamespace() . '\\';
  321. $type = explode('|', $type);
  322. foreach ($type as &$item) {
  323. $item = trim($item);
  324. // add support for array notation
  325. $is_array = false;
  326. if (substr($item, -2) == '[]') {
  327. $item = substr($item, 0, -2);
  328. $is_array = true;
  329. }
  330. if ((substr($item, 0, 1) != '\\')
  331. && (!in_array(strtolower($item), $non_objects))
  332. ) {
  333. $type_parts = explode('\\', $item);
  334. // if the first part is the keyword 'namespace', replace it
  335. // with the current namespace
  336. if ($type_parts[0] == 'namespace') {
  337. $type_parts[0] = $this->getNamespace();
  338. $item = implode('\\', $type_parts);
  339. }
  340. // if the first segment is an alias; replace with full name
  341. if (isset($this->namespace_aliases[$type_parts[0]])) {
  342. $type_parts[0] = $this->namespace_aliases[$type_parts[0]];
  343. $item = implode('\\', $type_parts);
  344. } elseif (count($type_parts) == 1) {
  345. // prefix the item with the namespace if there is only one
  346. // part and no alias
  347. $item = $namespace . $item;
  348. }
  349. }
  350. // re-add the array notation markers
  351. if ($is_array) {
  352. $item .= '[]';
  353. }
  354. // full paths always start with a slash
  355. if (isset($item[0]) && ($item[0] !== '\\')
  356. && (!in_array(strtolower($item), $non_objects))
  357. ) {
  358. $item = '\\' . $item;
  359. }
  360. }
  361. return implode('|', $type);
  362. }
  363. /**
  364. * Sets the aliases for all namespaces.
  365. *
  366. * @param string[] $namespace_aliases Array of aliases.
  367. *
  368. * @return void
  369. */
  370. public function setNamespaceAliases($namespace_aliases)
  371. {
  372. $this->namespace_aliases = $namespace_aliases;
  373. }
  374. /**
  375. * Returns all aliases for namespaces at the location of this tag.
  376. *
  377. * @return array
  378. */
  379. public function getNamespaceAliases()
  380. {
  381. return $this->namespace_aliases;
  382. }
  383. }