Pelzini

This is the code documentation for the Pelzini project

source of /processor/quality_check_transformer.php

Contains the QualityCheckTransformer 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 QualityCheckTransformer} class
  24.  *
  25.  * @package Transformers
  26.  * @author Josh
  27.  * @since 0.2
  28.  **/
  29.  
  30. /**
  31.  * This is a transformer that does quality checks on the codebase
  32.  *
  33.  * It checks that the documentation has the required tags. Currently the 'required tags' are only the summary
  34.  *
  35.  * The documentation is created in a report called the {@link Quality check report}.
  36.  **/
  37. class QualityCheckTransformer extends Transformer {
  38. private $offending_items;
  39. private $required_tags;
  40.  
  41.  
  42. /**
  43.   * Set up the quality check transformer
  44.   *
  45.   * @param array $required_tags Docblock tags which will be reported if missing
  46.   **/
  47. public function __construct(array $required_tags = null)
  48. {
  49. $this->required_tags = $required_tags;
  50. if (empty($this->required_tags)) {
  51. $this->required_tags = array('@summary');
  52. }
  53. }
  54.  
  55.  
  56. /**
  57.   * Transforms the data model before outputting.
  58.   *
  59.   * This transformer generates a report of objects that do not have good enough documentation
  60.   *
  61.   * @param array $parser_model The data model to transform
  62.   * @return array The new data model, or null if there was an error
  63.   **/
  64. public function transform(&$parser_model)
  65. {
  66. $this->offending_items = array();
  67.  
  68. foreach ($parser_model as $item) {
  69. if ($item instanceof CodeParserItem) {
  70. $this->check_files($item);
  71. }
  72. }
  73.  
  74. if (count($this->offending_items) == 0) {
  75. return null;
  76. }
  77. ksort($this->offending_items);
  78.  
  79. $report = "The following items have insufficent documentation:";
  80. foreach ($this->offending_items as $type => $items) {
  81. natcasesort($items);
  82.  
  83. $report .= "\n\n<b>{$type}:</b>\n - ";
  84. $report .= implode("\n - ", $items);
  85. }
  86.  
  87. $document = new ParserDocument();
  88. $document->name = "Quality check report";
  89. $document->description = htmlify_text($report);
  90. $parser_model[] = $document;
  91.  
  92. return $parser_model;
  93. }
  94.  
  95.  
  96. /**
  97.   * Checks that a file has high-enough quality documentation
  98.   **/
  99. private function check_files($item)
  100. {
  101. $tags = $item->getDocblockTags();
  102. $problems = array();
  103.  
  104. // classes and interfaces
  105. foreach ($item->classes as $sub) {
  106. if ($sub instanceof ParserClass) {
  107. $this->check_class($sub);
  108.  
  109. } else if ($sub instanceof ParserInterface) {
  110. $this->check_interface($sub);
  111. }
  112. }
  113.  
  114. // functions
  115. foreach ($item->functions as $sub) {
  116. $this->check_function($sub);
  117. }
  118.  
  119. // the files
  120. foreach ($this->required_tags as $tag_name) {
  121. if (!isset($tags[$tag_name]) or $tags[$tag_name] == '') {
  122. if ($tag_name == '@summary') {
  123. $tag_name = 'summary';
  124. } else {
  125. $tag_name .= ' tag';
  126. }
  127.  
  128. $problems[] = "No {$tag_name}";
  129. }
  130. }
  131.  
  132. if (count($problems)) {
  133. $this->offending_items['Files'][] = '{@link ' . $item->name . '}: <i>' . implode(', ', $problems) . '</i>';
  134. }
  135. }
  136.  
  137.  
  138. /**
  139.   * Checks that a class has high-enough quality documentation
  140.   **/
  141. private function check_class($item)
  142. {
  143. $tags = $item->getDocblockTags();
  144. $problems = array();
  145.  
  146. foreach ($this->required_tags as $tag_name) {
  147. if (!isset($tags[$tag_name]) or $tags[$tag_name] == '') {
  148. if ($tag_name == '@summary') {
  149. $tag_name = 'summary';
  150. } else {
  151. $tag_name .= ' tag';
  152. }
  153.  
  154. $problems[] = "No {$tag_name}";
  155. }
  156. }
  157.  
  158. if (count($problems)) {
  159. $this->offending_items['Classes'][] = '{@link ' . $item->name . '}: <i>' . implode(', ', $problems) . '</i>';
  160. }
  161.  
  162. foreach ($item->functions as $sub) {
  163. $this->check_function($sub, ' from class {@link ' . $item->name . '}');
  164. }
  165. }
  166.  
  167.  
  168. /**
  169.   * Checks that an interface has high-enough quality documentation
  170.   **/
  171. private function check_interface($item)
  172. {
  173. $tags = $item->getDocblockTags();
  174. $problems = array();
  175.  
  176. foreach ($this->required_tags as $tag_name) {
  177. if (!isset($tags[$tag_name]) or $tags[$tag_name] == '') {
  178. if ($tag_name == '@summary') {
  179. $tag_name = 'summary';
  180. } else {
  181. $tag_name .= ' tag';
  182. }
  183.  
  184. $problems[] = "No {$tag_name}";
  185. }
  186. }
  187.  
  188. if (count($problems)) {
  189. $this->offending_items['Interfaces'][] = '{@link ' . $item->name . '}: <i>' . implode(', ', $problems) . '</i>';
  190. }
  191.  
  192. foreach ($item->functions as $sub) {
  193. $this->check_function($sub, ' from interface {@link ' . $item->name . '}');
  194. }
  195. }
  196.  
  197.  
  198. /**
  199.   * Checks that a function has high-enough quality documentation
  200.   **/
  201. private function check_function($item, $from = null)
  202. {
  203. $tags = $item->getDocblockTags();
  204. $problems = array();
  205.  
  206. foreach ($this->required_tags as $tag_name) {
  207. if (!isset($tags[$tag_name]) or $tags[$tag_name] == '') {
  208. if ($tag_name == '@summary') {
  209. $tag_name = 'summary';
  210. } else {
  211. $tag_name .= ' tag';
  212. }
  213.  
  214. $problems[] = "No {$tag_name}";
  215. }
  216. }
  217.  
  218. if (count($problems)) {
  219. $this->offending_items['Functions'][] = '{@link ' . $item->name . '}' . $from . ': <i>' . implode(', ', $problems) . '</i>';
  220. }
  221.  
  222. foreach ($item->args as $arg) {
  223. if ($arg->description == '') {
  224. $this->offending_items['Function arguments'][] = '{@link ' . $item->name . '}' . $from . ': <i>No description for ' . $arg->name . '</i>';
  225. }
  226. }
  227. }
  228.  
  229.  
  230. }
  231.  
  232.  
  233. ?>
  234.