Pelzini

This is the code documentation for the Pelzini project

source of /processor/functions.php

Useful functions
  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.  * Useful functions
  24.  *
  25.  * @package Processor
  26.  * @author Josh
  27.  * @since 0.1
  28.  **/
  29.  
  30. /**
  31.  * Automatically loads the classes that are needed
  32.  **/
  33. function processor_autoload($class)
  34. {
  35. $filename = preg_replace('/([A-Z])/', '_$1', $class);
  36. $filename = __DIR__ . '/' . strtolower(substr($filename, 1)) . '.php';
  37. if (file_exists($filename)) require_once $filename;
  38. }
  39.  
  40. spl_autoload_register('processor_autoload');
  41.  
  42. require_once __DIR__ . '/constants.php';
  43.  
  44.  
  45. /**
  46.  * Parses a DocBlock comment tag
  47.  * Accepts the raw comment text of the comment straight from the file, including all the stars in the middle
  48.  * Returns an array of tags. Each paremeter will contain an array of the tags that existed, one for each tag
  49.  * The summary is returned in a 'summary' tag.
  50.  *
  51.  * The output for a function with two param tags, a return tag and a summary will be something like the following:
  52.  * array {
  53.  * ['@summary'] = '...',
  54.  * ['@param'] {
  55.  * [0] = '...',
  56.  * [1] = '...'
  57.  * },
  58.  * ['@return'] {
  59.  * [0] = '...',
  60.  * }
  61.  * }
  62.  *
  63.  * @param string $comment The raw comment text
  64.  * @return array The parsed comments, as per the example provided above
  65.  **/
  66. function parse_doc_comment($comment)
  67. {
  68. $comment = preg_replace('/^\/\*\*/', '', $comment);
  69. $comment = preg_replace('/\*\/$/m', '', $comment);
  70. $comment = preg_replace('/^\s*\**/m', '', $comment);
  71.  
  72.  
  73. // split into lines
  74. $lines = explode("\n", $comment);
  75.  
  76. // process one line at a time
  77. $output = array();
  78. $buffer = null;
  79. $current = null;
  80. foreach ($lines as $line) {
  81.  
  82. $line = preg_replace('/^\s/', '', $line);
  83. $line = rtrim($line);
  84. $trimline = ltrim($line);
  85.  
  86. // process special words
  87. if ($trimline != '' and $trimline[0] == '@') {
  88. @list($word, $value) = preg_split('/\s+/', $trimline, 2);
  89.  
  90. // tags
  91. if ($current != null) {
  92. parse_tag ($output, $current, $buffer);
  93. $buffer = null;
  94. }
  95. $current = $word;
  96. $buffer = $value;
  97.  
  98. // non tag - could be part of the summary, or could be a continuation of a tag
  99. } else {
  100. if ($current != null) {
  101. $buffer .= "\n" . $line;
  102.  
  103. } else {
  104. $current = '@summary';
  105. $buffer = $line;
  106. }
  107. }
  108.  
  109. }
  110.  
  111. if ($current != null) {
  112. parse_tag ($output, $current, $buffer);
  113. }
  114.  
  115. return $output;
  116. }
  117.  
  118.  
  119. /**
  120.  * Processes the parsing of an individual tag
  121.  **/
  122. function parse_tag(&$output, $tag, $buffer)
  123. {
  124. if ($tag == '@summary') {
  125. $output[$tag] = trim($buffer);
  126.  
  127. } else {
  128. if (! isset($output[$tag])) {
  129. $output[$tag] = array();
  130. }
  131. $output[$tag][] = rtrim($buffer);
  132. }
  133. }
  134.  
  135.  
  136. /**
  137.  * Outputs a status message
  138.  *
  139.  * @param string $message The message to output
  140.  **/
  141. function output_status($message)
  142. {
  143. if (PHP_SAPI == 'cli') {
  144. $message = preg_replace('/<a[^>]* href=[\'"](.+?)[\'"][^>]*>(.*?)<\/a>/i', '$2 [LINK: $1]', $message);
  145. echo strip_tags($message) . "\n";
  146.  
  147. } else {
  148. echo $message . "<br>";
  149. }
  150. flush();
  151. }
  152.  
  153.  
  154. /**
  155.  * Gets all the filenames in a directory and in the subdirectories
  156.  **/
  157. function get_filenames($base_dir, $directory, array $exclude_dirs)
  158. {
  159. $exclude_dir = preg_replace('!^/!', '', $directory);
  160. if (in_array($exclude_dir, $exclude_dirs)) return null;
  161.  
  162. $handle = opendir($base_dir . $directory);
  163. if ($handle === false) return null;
  164.  
  165. $files = array();
  166. while (($file = readdir($handle)) !== false) {
  167. if ($file[0] == '.') continue;
  168.  
  169. if (is_dir($base_dir . $directory . '/'. $file)) {
  170. // If its a directory, get the files in it
  171. $files2 = get_filenames($base_dir, $directory . '/'. $file, $exclude_dirs);
  172. if (is_array($files2)) {
  173. $files = array_merge($files, $files2);
  174. }
  175.  
  176. } else {
  177. // Otherwise just add the file to our list
  178. $files[] = $directory . '/'. $file;
  179. }
  180. }
  181.  
  182. closedir($handle);
  183.  
  184. return $files;
  185. }
  186.  
  187.  
  188. /**
  189.  * This will take the provided text, and turn it into HTML
  190.  * If it contains HTML, it will validate it, otherwise it
  191.  * will wrap everything in a PRE
  192.  *
  193.  * This function also removes extra spaces from the beginning of lines
  194.  * but will do so in a manner that indenting is preserved
  195.  **/
  196. function htmlify_text($text)
  197. {
  198. if ($text == '') return null;
  199.  
  200. // if the code contains block level HTML, output it as is
  201. // todo: come up with a smarter solution
  202. $has_block_html = preg_match('/<(p|div|pre|table)( .*)?>/i', $text);
  203. if ($has_block_html) {
  204. return $text;
  205. }
  206.  
  207. // otherwise, we do clever indenting
  208. $lines = explode("\n", $text);
  209. $min_num_spaces = 1000;
  210. foreach ($lines as $line) {
  211. if (trim($line) == '') continue;
  212. $num_spaces = 0;
  213. for ($i = 0; $i < strlen($line); $i++) {
  214. if ($line[$i] != ' ') break;
  215. ++$num_spaces;
  216. }
  217. $min_num_spaces = min($min_num_spaces, $num_spaces);
  218. }
  219.  
  220. // remove trailing whitespace
  221. $text = '';
  222. $j = 0;
  223. foreach ($lines as $line) {
  224. if ($j++ > 0) $text .= "\n";
  225. $text .= substr($line, $min_num_spaces);
  226. }
  227.  
  228. // remove invalid HTML tags
  229. $text = str_replace('&', '&amp;', $text);
  230. $replacer = function(array $matches) {
  231. return htmlify_check_tag(stripslashes($matches[0]), stripslashes($matches[1]));
  232. };
  233. $text = preg_replace_callback('/<\/?([a-z]+)(?>\s|"[^"]*"|\'[^\']*\'|[^\'">])*>/i', $replacer, $text);
  234. $text = preg_replace('/<([^\/a-z])/i', '&lt;$1', $text);
  235. $text = preg_replace('/([^"\'a-z])>/i', '$1&gt;', $text);
  236. $text = str_replace('"', '&quot;', $text);
  237.  
  238. // wrap it all in a PRE
  239. $text = "<pre>\n{$text}</pre>";
  240.  
  241. return $text;
  242. }
  243.  
  244.  
  245. /**
  246.  * Does processing on a single HTML tag, as provided by a regex in {@link htmlify_text}
  247.  *
  248.  * @param string $full_match The full tag that was found (e.g. '<select name="blah">')
  249.  * @param string $tag_name The name of the tag that was found (e.g. 'select')
  250.  * @return string What the tag should be replaced with
  251.  **/
  252. function htmlify_check_tag($full_match, $tag_name)
  253. {;
  254. // valid tags get used as-is
  255. $valid_tags = array ('b', 'i', 'em', 'strong');
  256. if (in_array($tag_name, $valid_tags)) {
  257. return $full_match;
  258. }
  259.  
  260. // everything else gets encoded
  261. $full_match = str_replace('<', '&lt;', $full_match);
  262. $full_match = str_replace('>', '&gt;', $full_match);
  263. return $full_match;
  264. }
  265.  
  266.  
  267. /**
  268.  * Processes the javadoc tags for a specific parser item
  269.  **/
  270. function process_javadoc_tags(CodeParserItem $parser_item, $parent)
  271. {
  272. if ($parent != null) {
  273. $parent->cascadeTags($parser_item);
  274. }
  275.  
  276. $parser_item->processTags();
  277. }
  278.  
  279.  
  280. ?>
  281.