Pelzini

This is the code documentation for the Pelzini project

source of /processor/code_parser_item.php

Contains the CodeParserItem class
  1. <?php
  2. /*
  3. Copyright 2008 Josh Heidenreich
  4.  
  5. This file is part of Pelzini.
  6.  
  7. Pelzini is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11.  
  12. Pelzini is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Pelzini. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20.  
  21.  
  22. /**
  23.  * Contains the {@link CodeParserItem} class
  24.  *
  25.  * @package Parser model
  26.  * @author Josh Heidenreich
  27.  * @since 0.1
  28.  **/
  29.  
  30. /**
  31.  * Stores information about parser items that are actual source code.
  32.  * Typically these parser items have authors and versions, so all of that information
  33.  * is stored in this class.
  34.  *
  35.  * @todo Add get/set methods instead of using public variables
  36.  **/
  37. abstract class CodeParserItem extends ParserItem {
  38. public $authors;
  39. public $since;
  40. public $tables;
  41. public $see;
  42. public $info_tags;
  43. public $deprecated;
  44. public $example;
  45. public $linenum = 0;
  46.  
  47. protected $docblock_tags;
  48.  
  49.  
  50. /**
  51.   * Processes the docblock tags for a specific item
  52.   **/
  53. abstract protected function processSpecificDocblockTags($docblock_tags);
  54.  
  55.  
  56. /**
  57.   * Executes a function for this ParserItem, and all of its children ParserItems
  58.   *
  59.   * The function will be called with a two arguments, the ParserItem that it should operate on, and the parent
  60.   * of the parser item
  61.   **/
  62. public function treeWalk($function_name, ParserItem $parent_item = null)
  63. {
  64. call_user_func($function_name, $this, $parent_item);
  65. }
  66.  
  67.  
  68. /**
  69.   * This constructor must be called by extending classes
  70.   **/
  71. protected function __construct()
  72. {
  73. parent::__construct();
  74.  
  75. $this->docblock_tags = array();
  76. $this->authors = array();
  77. $this->since = null;
  78. $this->tables = array();
  79. $this->see = array();
  80. $this->example = array();
  81. $this->info_tags = array();
  82. }
  83.  
  84.  
  85. /**
  86.   * This parses a comment for a specific item
  87.   **/
  88. public function applyComment($comment)
  89. {
  90. $this->docblock_tags = parse_doc_comment ($comment);
  91. }
  92.  
  93.  
  94. /**
  95.   * Processes the tags for a specific item
  96.   **/
  97. public function processTags()
  98. {
  99. $this->processGenericDocblockTags($this->docblock_tags);
  100. $this->processSpecificDocblockTags($this->docblock_tags);
  101. }
  102.  
  103.  
  104. /**
  105.   * Cascades parent Docblock tags into a child item
  106.   * Only cascades the tags specified in the config
  107.   *
  108.   * @param ParserItem $child The child item to cascade the tags into
  109.   **/
  110. public function cascadeTags($child)
  111. {
  112. $cascaseDocblockTags = array('@author', '@since');
  113.  
  114. $child_tags = $child->getDocblockTags();
  115.  
  116. foreach ($cascaseDocblockTags as $cascade_tag) {
  117. if (! in_array($cascade_tag, array_keys($child_tags))) {
  118. $child_tags[$cascade_tag] = @$this->docblock_tags[$cascade_tag];
  119. }
  120. }
  121.  
  122. $child->setDocblockTags($child_tags);
  123. }
  124.  
  125.  
  126. /**
  127.   * Gets the Docblock tags of this item
  128.   **/
  129. public function getDocblockTags()
  130. {
  131. return $this->docblock_tags;
  132. }
  133.  
  134.  
  135. /**
  136.   * Sets the Docblock tags for this item
  137.   *
  138.   * @param array $tags The new docblock tags.
  139.   **/
  140. public function setDocblockTags($tags)
  141. {
  142. $this->docblock_tags = $tags;
  143. }
  144.  
  145.  
  146. /**
  147.   * Processes general DocBlock tags that should apply to everything
  148.   **/
  149. protected function processGenericDocblockTags($docblock_tags)
  150. {
  151. // @author
  152. if (@count($docblock_tags['@author']) > 0) {
  153. // This regex is for taking an author string, and getting the name (required),
  154. // email address (optional) and description (optional).
  155. // The format, simply put, is:
  156. // {Name} (<{Email}>)? ({Description})?
  157. // There is also some extra cleverness, such as you can use a comma, colon or semi-colon
  158. // to seperate the name part and the description part
  159. //
  160. // | name part || email address part || desc part |
  161. $expression = '/^((?:[a-z] ?)+)(?:\s*<([-a-z._]+@[-a-z.]+)>)?(?:\s*[,:;]?\s*(.*))?$/si';
  162.  
  163. foreach ($docblock_tags['@author'] as $author) {
  164. if (preg_match($expression, $author, $matches)) {
  165. $author = new ParserAuthor();
  166. $author->name = $matches[1];
  167. $author->email = $matches[2];
  168. $author->description = $matches[3];
  169.  
  170. $this->authors[] = $author;
  171. }
  172. }
  173. }
  174.  
  175. // @since
  176. if (@count($docblock_tags['@since']) > 0) {
  177. $this->since = $docblock_tags['@since'][0];
  178. }
  179.  
  180. // @table
  181. if (@count($docblock_tags['@table']) > 0) {
  182. $valid_actions = array('select', 'insert', 'update', 'delete');
  183.  
  184. foreach ($docblock_tags['@table'] as $table_def) {
  185. if ($table_def == '') continue;
  186.  
  187. $parts = explode(' ', $table_def, 3);
  188.  
  189. $found_action = false;
  190. foreach ($valid_actions as $action) {
  191. if (strcasecmp($parts[0], $action) == 0) {
  192. $found_action = true;
  193. break;
  194. }
  195. }
  196.  
  197.  
  198. $table = new ParserTable();
  199.  
  200. if ($found_action) {
  201. $table->action = strtoupper($parts[0]);
  202. $table->name = $parts[1];
  203. $table->description = $parts[2];
  204.  
  205. } else {
  206. $table->name = $parts[0];
  207. $table->description = $parts[1] . ' ' . $parts[2];
  208. }
  209.  
  210. $this->tables[] = $table;
  211. }
  212. }
  213.  
  214. // @see
  215. if (@count($docblock_tags['@see']) > 0) {
  216. foreach ($docblock_tags['@see'] as $see) {
  217. $this->see[] = $see;
  218. }
  219. }
  220.  
  221. // @tag
  222. if (@count($docblock_tags['@tag']) > 0) {
  223. foreach ($docblock_tags['@tag'] as $info_tag) {
  224. $this->info_tags[] = $info_tag;
  225. }
  226. }
  227.  
  228. // @example
  229. if (@count($docblock_tags['@example']) > 0) {
  230. foreach ($docblock_tags['@example'] as $example) {
  231. $example = trim($example, "\r\n");
  232. $example = str_replace("\t", " ", $example);
  233.  
  234. $lines = preg_split('/\n/', $example);
  235. $lead = 1000;
  236. foreach ($lines as $ln) {
  237. if (!$ln) continue;
  238. preg_match('/^ +/', $ln, $matches);
  239. $lead = min($lead, strlen(@$matches[0]));
  240. }
  241.  
  242. foreach ($lines as &$ln) {
  243. $ln = substr($ln, $lead);
  244. }
  245. unset($ln);
  246.  
  247. $this->example[] = implode("\n", $lines);
  248. }
  249. }
  250.  
  251. // @deprecated
  252. if (@count($docblock_tags['@deprecated']) > 0) {
  253. $this->deprecated = $docblock_tags['@deprecated'][0];
  254. }
  255. }
  256.  
  257.  
  258. /**
  259.   * Debugging use only
  260.   **/
  261. protected function dump()
  262. {
  263. echo '<br>Authors: '; foreach ($this->authors as $a) $a->dump();
  264. echo '<br>Tables: '; foreach ($this->tables as $a) $a->dump();
  265. echo '<br>Since: ', $this->since;
  266.  
  267. //parent::dump();
  268. }
  269.  
  270.  
  271. }
  272.  
  273.  
  274. ?>
  275.