PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/userguide/classes/kohana/kodoc.php

https://bitbucket.org/alvinpd/monsterninja
PHP | 321 lines | 194 code | 53 blank | 74 comment | 20 complexity | bdc3bb1cb71308f9a09829f0e9af2d88 MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Documentation generator.
  4. *
  5. * @package Kohana/Userguide
  6. * @category Base
  7. * @author Kohana Team
  8. * @copyright (c) 2008-2009 Kohana Team
  9. * @license http://kohanaphp.com/license
  10. */
  11. class Kohana_Kodoc {
  12. public static function factory($class)
  13. {
  14. return new Kodoc_Class($class);
  15. }
  16. /**
  17. * Creates an html list of all classes sorted by category (or package if no category)
  18. *
  19. * @return string the html for the menu
  20. */
  21. public static function menu()
  22. {
  23. $classes = Kodoc::classes();
  24. foreach ($classes as $class)
  25. {
  26. if (isset($classes['kohana_'.$class]))
  27. {
  28. // Remove extended classes
  29. unset($classes['kohana_'.$class]);
  30. }
  31. }
  32. ksort($classes);
  33. $menu = array();
  34. $route = Route::get('docs/api');
  35. foreach ($classes as $class)
  36. {
  37. $class = Kodoc_Class::factory($class);
  38. // Test if we should show this class
  39. if ( ! Kodoc::show_class($class))
  40. continue;
  41. $link = HTML::anchor($route->uri(array('class' => $class->class->name)), $class->class->name);
  42. if (isset($class->tags['package']))
  43. {
  44. foreach ($class->tags['package'] as $package)
  45. {
  46. if (isset($class->tags['category']))
  47. {
  48. foreach ($class->tags['category'] as $category)
  49. {
  50. $menu[$package][$category][] = $link;
  51. }
  52. }
  53. else
  54. {
  55. $menu[$package]['Base'][] = $link;
  56. }
  57. }
  58. }
  59. else
  60. {
  61. $menu['[Unknown]']['Base'][] = $link;
  62. }
  63. }
  64. // Sort the packages
  65. ksort($menu);
  66. return View::factory('userguide/api/menu')
  67. ->bind('menu', $menu);
  68. }
  69. /**
  70. * Returns an array of all the classes available, built by listing all files in the classes folder and then trying to create that class.
  71. *
  72. * This means any empty class files (as in complety empty) will cause an exception
  73. *
  74. * @param array array of files, obtained using Kohana::list_files
  75. * @return array an array of all the class names
  76. */
  77. public static function classes(array $list = NULL)
  78. {
  79. if ($list === NULL)
  80. {
  81. $list = Kohana::list_files('classes');
  82. }
  83. $classes = array();
  84. foreach ($list as $name => $path)
  85. {
  86. if (is_array($path))
  87. {
  88. $classes += Kodoc::classes($path);
  89. }
  90. else
  91. {
  92. // Remove "classes/" and the extension
  93. $class = substr($name, 8, -(strlen(EXT)));
  94. // Convert slashes to underscores
  95. $class = str_replace(DIRECTORY_SEPARATOR, '_', strtolower($class));
  96. $classes[$class] = $class;
  97. }
  98. }
  99. return $classes;
  100. }
  101. /**
  102. * Get all classes and methods of files in a list.
  103. *
  104. * > I personally don't like this as it was used on the index page. Way too much stuff on one page. It has potential for a package index page though.
  105. * > For example: class_methods( Kohana::list_files('classes/sprig') ) could make a nice index page for the sprig package in the api browser
  106. * > ~bluehawk
  107. *
  108. */
  109. public static function class_methods(array $list = NULL)
  110. {
  111. $list = Kodoc::classes($list);
  112. $classes = array();
  113. foreach ($list as $class)
  114. {
  115. $_class = new ReflectionClass($class);
  116. if (stripos($_class->name, 'Kohana') === 0)
  117. {
  118. // Skip the extension stuff stuff
  119. continue;
  120. }
  121. $methods = array();
  122. foreach ($_class->getMethods() as $_method)
  123. {
  124. $declares = $_method->getDeclaringClass()->name;
  125. if (stripos($declares, 'Kohana') === 0)
  126. {
  127. // Remove "Kohana_"
  128. $declares = substr($declares, 7);
  129. }
  130. if ($declares === $_class->name)
  131. {
  132. $methods[] = $_method->name;
  133. }
  134. }
  135. sort($methods);
  136. $classes[$_class->name] = $methods;
  137. }
  138. return $classes;
  139. }
  140. /**
  141. * Parse a comment to extract the description and the tags
  142. *
  143. * @param string the comment retreived using ReflectionClass->getDocComment()
  144. * @return array array(string $description, array $tags)
  145. */
  146. public static function parse($comment)
  147. {
  148. // Normalize all new lines to \n
  149. $comment = str_replace(array("\r\n", "\n"), "\n", $comment);
  150. // Remove the phpdoc open/close tags and split
  151. $comment = array_slice(explode("\n", $comment), 1, -1);
  152. // Tag content
  153. $tags = array();
  154. foreach ($comment as $i => $line)
  155. {
  156. // Remove all leading whitespace
  157. $line = preg_replace('/^\s*\* ?/m', '', $line);
  158. // Search this line for a tag
  159. if (preg_match('/^@(\S+)(?:\s*(.+))?$/', $line, $matches))
  160. {
  161. // This is a tag line
  162. unset($comment[$i]);
  163. $name = $matches[1];
  164. $text = isset($matches[2]) ? $matches[2] : '';
  165. switch ($name)
  166. {
  167. case 'license':
  168. if (strpos($text, '://') !== FALSE)
  169. {
  170. // Convert the lincense into a link
  171. $text = HTML::anchor($text);
  172. }
  173. break;
  174. case 'copyright':
  175. if (strpos($text, '(c)') !== FALSE)
  176. {
  177. // Convert the copyright sign
  178. $text = str_replace('(c)', '&copy;', $text);
  179. }
  180. break;
  181. case 'throws':
  182. if (preg_match('/^(\w+)\W(.*)$/',$text,$matches))
  183. {
  184. $text = HTML::anchor(Route::get('docs/api')->uri(array('class' => $matches[1])), $matches[1]).' '.$matches[2];
  185. }
  186. else
  187. {
  188. $text = HTML::anchor(Route::get('docs/api')->uri(array('class' => $text)), $text);
  189. }
  190. break;
  191. case 'uses':
  192. if (preg_match('/^([a-z_]+)::([a-z_]+)$/i', $text, $matches))
  193. {
  194. // Make a class#method API link
  195. $text = HTML::anchor(Route::get('docs/api')->uri(array('class' => $matches[1])).'#'.$matches[2], $text);
  196. }
  197. break;
  198. // Don't show @access lines, they are shown elsewhere
  199. case 'access':
  200. continue 2;
  201. }
  202. // Add the tag
  203. $tags[$name][] = $text;
  204. }
  205. else
  206. {
  207. // Overwrite the comment line
  208. $comment[$i] = (string) $line;
  209. }
  210. }
  211. // Concat the comment lines back to a block of text
  212. if ($comment = trim(implode("\n", $comment)))
  213. {
  214. // Parse the comment with Markdown
  215. $comment = Markdown($comment);
  216. }
  217. return array($comment, $tags);
  218. }
  219. /**
  220. * Get the source of a function
  221. *
  222. * @param string the filename
  223. * @param int start line?
  224. * @param int end line?
  225. */
  226. public static function source($file, $start, $end)
  227. {
  228. if ( ! $file)
  229. {
  230. return FALSE;
  231. }
  232. $file = file($file, FILE_IGNORE_NEW_LINES);
  233. $file = array_slice($file, $start - 1, $end - $start + 1);
  234. if (preg_match('/^(\s+)/', $file[0], $matches))
  235. {
  236. $padding = strlen($matches[1]);
  237. foreach ($file as & $line)
  238. {
  239. $line = substr($line, $padding);
  240. }
  241. }
  242. return implode("\n", $file);
  243. }
  244. /**
  245. * Test whether a class should be shown, based on the api_packages config option
  246. *
  247. * @param Kodoc_Class the class to test
  248. * @return bool whether this class should be shown
  249. */
  250. public static function show_class(Kodoc_Class $class)
  251. {
  252. $api_packages = Kohana::config('userguide.api_packages');
  253. // If api_packages is true, all packages should be shown
  254. if ($api_packages === TRUE)
  255. return TRUE;
  256. // Get the package tags for this class (as an array)
  257. $packages = Arr::get($class->tags,'package',Array('None'));
  258. $show_this = FALSE;
  259. // Loop through each package tag
  260. foreach ($packages as $package)
  261. {
  262. // If this package is in the allowed packages, set show this to true
  263. if (in_array($package,explode(',',$api_packages)))
  264. $show_this = TRUE;
  265. }
  266. return $show_this;
  267. }
  268. } // End Kodoc