PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://github.com/androa/Docblox
PHP | 270 lines | 147 code | 24 blank | 99 comment | 9 complexity | c1adb457076fb78a161ba84577241d05 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * DocBlox
  4. *
  5. * @category DocBlox
  6. * @package Parser
  7. * @subpackage Tag_Definitions
  8. * @author Mike van Riel <mike.vanriel@naenius.com>
  9. * @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
  10. * @license http://www.opensource.org/licenses/mit-license.php MIT
  11. * @link http://docblox-project.org
  12. */
  13. /**
  14. * Generic Definition which adds the basic tag information to the structure file.
  15. *
  16. * @category DocBlox
  17. * @package Parser
  18. * @subpackage Tag_Definitions
  19. * @author Mike van Riel <mike.vanriel@naenius.com>
  20. * @license http://www.opensource.org/licenses/mit-license.php MIT
  21. * @link http://docblox-project.org
  22. */
  23. class DocBlox_Parser_DocBlock_Tag_Definition
  24. {
  25. /** @var SimpleXMLElement */
  26. protected $xml = null;
  27. /** @var DocBlox_Reflection_DocBlock_Tag */
  28. protected $tag = null;
  29. /**
  30. * @var string
  31. */
  32. protected $namespace = '';
  33. /**
  34. * @var array
  35. */
  36. protected $namespace_aliases = array();
  37. /**
  38. * Initializes this object with the given data and sets the name and description.
  39. *
  40. * @param string $namespace Namespace where this tag occurs.
  41. * @param string[] $namespace_aliases aliases used for all namespaces at the location of this tag.
  42. * @param SimpleXMLElement $xml
  43. * @param DocBlox_Reflection_DocBlock_Tag $tag
  44. */
  45. public function __construct($namespace, $namespace_aliases, SimpleXMLElement $xml, DocBlox_Reflection_DocBlock_Tag $tag)
  46. {
  47. $this->xml = $xml;
  48. $this->tag = $tag;
  49. $this->setNamespace($namespace);
  50. $this->setNamespaceAliases($namespace_aliases);
  51. $this->setName($this->tag->getName());
  52. $this->setDescription($this->tag->getDescription());
  53. if (method_exists($this->tag, 'getTypes')) {
  54. $this->setTypes($this->tag->getTypes());
  55. }
  56. }
  57. /**
  58. * Creates a new instance of this class or one of the specialized sub-classes.
  59. *
  60. * @todo replace the switch statement with an intelligent container / plugin system.
  61. *
  62. * @param string $namespace Namespace where this tag occurs.
  63. * @param string[] $namespace_aliases aliases used for all namespaces at the location of this tag.
  64. * @param SimpleXMLElement $xml root xml element for this tag.
  65. * @param DocBlox_Reflection_DocBlock_Tag $tag The actual tag as reflected.
  66. *
  67. * @return DocBlox_Parser_DocBlock_Tag_Definition
  68. */
  69. public static function create($namespace, $namespace_aliases, SimpleXMLElement $xml, DocBlox_Reflection_DocBlock_Tag $tag)
  70. {
  71. switch ($tag->getName())
  72. {
  73. case 'param':
  74. $def = new DocBlox_Parser_DocBlock_Tag_Definition_Param($namespace, $namespace_aliases, $xml, $tag);
  75. break;
  76. case 'link':
  77. $def = new DocBlox_Parser_DocBlock_Tag_Definition_Link($namespace, $namespace_aliases, $xml, $tag);
  78. break;
  79. default:
  80. $def = new self($namespace, $namespace_aliases, $xml, $tag);
  81. break;
  82. }
  83. $def->configure();
  84. return $def;
  85. }
  86. /**
  87. * Hook method where children can extend the structure with extra information.
  88. *
  89. * @return void
  90. */
  91. protected function configure()
  92. {
  93. }
  94. /**
  95. * Setter for the name so it can be overridden.
  96. *
  97. * @param string $name
  98. *
  99. * @return void
  100. */
  101. public function setName($name)
  102. {
  103. $this->xml['name'] = $name;
  104. }
  105. /**
  106. * Setter for the description so it can be overridden.
  107. *
  108. * @param string $description
  109. *
  110. * @return void
  111. */
  112. public function setDescription($description)
  113. {
  114. $description = htmlspecialchars($description, ENT_QUOTES, 'UTF-8');
  115. $this->xml['description'] = trim($description);
  116. }
  117. /**
  118. * Sets the namespace for this tag; is used to determine type info.
  119. *
  120. * @param string $namespace
  121. *
  122. * @return void
  123. */
  124. public function setNamespace($namespace)
  125. {
  126. $this->namespace = $namespace;
  127. }
  128. /**
  129. * Returns the namespace identifier for this tag.
  130. *
  131. * @return string
  132. */
  133. public function getNamespace()
  134. {
  135. return $this->namespace;
  136. }
  137. /**
  138. * Adds type information to the structure.
  139. *
  140. * @todo Move this method to a better spot with namespace and alias access (together with namespace and alias stuff).
  141. *
  142. * @param string[] $types
  143. *
  144. * @return void
  145. */
  146. public function setTypes($types)
  147. {
  148. foreach ($types as $type) {
  149. if ($type == '') {
  150. continue;
  151. }
  152. $type = trim($this->expandType($type));
  153. // strip ampersands
  154. $name = str_replace('&', '', $type);
  155. $type_object = $this->xml->addChild('type', $name);
  156. // register whether this variable is by reference by checking the first and last character
  157. $type_object['by_reference'] = ((substr($type, 0, 1) === '&') || (substr($type, -1) === '&'))
  158. ? 'true'
  159. : 'false';
  160. }
  161. $this->xml['type'] = $this->expandType($this->tag->getType());
  162. }
  163. /**
  164. * Tries to expand a type to it's full namespaced equivalent.
  165. *
  166. * @param string $type Type to expand into full namespaced equivalent
  167. *
  168. * @return string
  169. */
  170. protected function expandType($type)
  171. {
  172. if ($type === null) {
  173. return null;
  174. }
  175. $non_objects = array(
  176. 'string', 'int', 'integer', 'bool', 'boolean', 'float', 'double',
  177. 'object', 'mixed', 'array', 'resource', 'void', 'null', 'callback'
  178. );
  179. $namespace = $this->getNamespace() == 'default' ? '' : $this->getNamespace() . '\\';
  180. $type = explode('|', $type);
  181. foreach ($type as &$item) {
  182. $item = trim($item);
  183. // add support for array notation
  184. $is_array = false;
  185. if (substr($item, -2) == '[]') {
  186. $item = substr($item, 0, -2);
  187. $is_array = true;
  188. }
  189. if ((substr($item, 0, 1) != '\\') && (!in_array(strtolower($item), $non_objects))) {
  190. $type_parts = explode('\\', $item);
  191. // if the first part is the keyword 'namespace', replace it with the current namespace
  192. if ($type_parts[0] == 'namespace') {
  193. $type_parts[0] = $this->getNamespace();
  194. $item = implode('\\', $type_parts);
  195. }
  196. // if the first segment is an alias; replace with full name
  197. if (isset($this->namespace_aliases[$type_parts[0]])) {
  198. $type_parts[0] = $this->namespace_aliases[$type_parts[0]];
  199. $item = implode('\\', $type_parts);
  200. } elseif (count($type_parts) == 1) {
  201. // prefix the item with the namespace if there is only one part and no alias
  202. $item = $namespace . $item;
  203. }
  204. }
  205. // re-add the array notation markers
  206. if ($is_array) {
  207. $item .= '[]';
  208. }
  209. // full paths always start with a slash
  210. if (isset($item[0]) && ($item[0] !== '\\')) {
  211. $item = '\\' . $item;
  212. }
  213. }
  214. return implode('|', $type);
  215. }
  216. /**
  217. * Sets the aliases for all namespaces.
  218. *
  219. * @param string[] $namespace_aliases
  220. *
  221. * @return void
  222. */
  223. public function setNamespaceAliases($namespace_aliases)
  224. {
  225. $this->namespace_aliases = $namespace_aliases;
  226. }
  227. /**
  228. * Returns all aliases for namespaces at the location of this tag.
  229. *
  230. * @return array
  231. */
  232. public function getNamespaceAliases()
  233. {
  234. return $this->namespace_aliases;
  235. }
  236. }