PageRenderTime 29ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/classes/kohana/kodoc/class.php

https://github.com/dyron/userguide-de
PHP | 238 lines | 122 code | 40 blank | 76 comment | 23 complexity | 54349b88d187b8d2d7c221eea483f1e7 MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Class documentation generator.
  4. *
  5. * @package Kohana/Userguide
  6. * @category Base
  7. * @author Kohana Team
  8. * @copyright (c) 2009 Kohana Team
  9. * @license http://kohanaphp.com/license
  10. */
  11. class Kohana_Kodoc_Class extends Kodoc {
  12. /**
  13. * @var ReflectionClass The ReflectionClass for this class
  14. */
  15. public $class;
  16. /**
  17. * @var string modifiers like abstract, final
  18. */
  19. public $modifiers;
  20. /**
  21. * @var string description of the class from the comment
  22. */
  23. public $description;
  24. /**
  25. * @var array array of tags, retrieved from the comment
  26. */
  27. public $tags = array();
  28. /**
  29. * @var array array of this classes constants
  30. */
  31. public $constants = array();
  32. /**
  33. * @var array Parent classes/interfaces of this class/interface
  34. */
  35. public $parents = array();
  36. /**
  37. * Loads a class and uses [reflection](http://php.net/reflection) to parse
  38. * the class. Reads the class modifiers, constants and comment. Parses the
  39. * comment to find the description and tags.
  40. *
  41. * @param string class name
  42. * @return void
  43. */
  44. public function __construct($class)
  45. {
  46. $this->class = new ReflectionClass($class);
  47. if ($modifiers = $this->class->getModifiers())
  48. {
  49. $this->modifiers = '<small>'.implode(' ', Reflection::getModifierNames($modifiers)).'</small> ';
  50. }
  51. if ($constants = $this->class->getConstants())
  52. {
  53. foreach ($constants as $name => $value)
  54. {
  55. $this->constants[$name] = Debug::vars($value);
  56. }
  57. }
  58. // If ReflectionClass::getParentClass() won't work if the class in
  59. // question is an interface
  60. if ($this->class->isInterface())
  61. {
  62. $this->parents = $this->class->getInterfaces();
  63. }
  64. else
  65. {
  66. $parent = $this->class;
  67. while ($parent = $parent->getParentClass())
  68. {
  69. $this->parents[] = $parent;
  70. }
  71. }
  72. $parents = $this->parents;
  73. array_unshift($parents, $this->class);
  74. foreach ($parents as $parent)
  75. {
  76. if ($comment = $parent->getDocComment())
  77. {
  78. // Found a description for this class
  79. break;
  80. }
  81. }
  82. list($this->description, $this->tags) = Kodoc::parse($comment);
  83. // If this class extends Kodoc_Missing, add a warning about possible
  84. // incomplete documentation
  85. foreach ($parents as $parent)
  86. {
  87. if ($parent->name == 'Kodoc_Missing')
  88. {
  89. $warning = "[!!] **This class, or a class parent, could not be
  90. found or loaded. This could be caused by a missing
  91. module or other dependancy. The documentation for
  92. class may not be complete!**";
  93. $this->description = Markdown($warning).$this->description;
  94. }
  95. }
  96. }
  97. /**
  98. * Gets a list of the class properties as [Kodoc_Property] objects.
  99. *
  100. * @return array
  101. */
  102. public function properties()
  103. {
  104. $props = $this->class->getProperties();
  105. $defaults = $this->class->getDefaultProperties();
  106. usort($props, array($this,'_prop_sort'));
  107. foreach ($props as $key => $property)
  108. {
  109. // Create Kodoc Properties for each property
  110. $props[$key] = new Kodoc_Property($this->class->name, $property->name, Arr::get($defaults, $property->name));
  111. }
  112. return $props;
  113. }
  114. protected function _prop_sort($a, $b)
  115. {
  116. // If one property is public, and the other is not, it goes on top
  117. if ($a->isPublic() AND ( ! $b->isPublic()))
  118. return -1;
  119. if ($b->isPublic() AND ( ! $a->isPublic()))
  120. return 1;
  121. // If one property is protected and the other is private, it goes on top
  122. if ($a->isProtected() AND $b->isPrivate())
  123. return -1;
  124. if ($b->isProtected() AND $a->isPrivate())
  125. return 1;
  126. // Otherwise just do alphabetical
  127. return strcmp($a->name, $b->name);
  128. }
  129. /**
  130. * Gets a list of the class properties as [Kodoc_Method] objects.
  131. *
  132. * @return array
  133. */
  134. public function methods()
  135. {
  136. $methods = $this->class->getMethods();
  137. usort($methods, array($this,'_method_sort'));
  138. foreach ($methods as $key => $method)
  139. {
  140. $methods[$key] = new Kodoc_Method($this->class->name, $method->name);
  141. }
  142. return $methods;
  143. }
  144. /**
  145. * Sort methods based on their visibility and declaring class based on:
  146. * - methods will be sorted public, protected, then private.
  147. * - methods that are declared by an ancestor will be after classes
  148. * declared by the current class
  149. * - lastly, they will be sorted alphabetically
  150. *
  151. */
  152. protected function _method_sort($a, $b)
  153. {
  154. // If one method is public, and the other is not, it goes on top
  155. if ($a->isPublic() AND ( ! $b->isPublic()))
  156. return -1;
  157. if ($b->isPublic() AND ( ! $a->isPublic()))
  158. return 1;
  159. // If one method is protected and the other is private, it goes on top
  160. if ($a->isProtected() AND $b->isPrivate())
  161. return -1;
  162. if ($b->isProtected() AND $a->isPrivate())
  163. return 1;
  164. // The methods have the same visibility, so check the declaring class depth:
  165. /*
  166. echo kohana::debug('a is '.$a->class.'::'.$a->name,'b is '.$b->class.'::'.$b->name,
  167. 'are the classes the same?', $a->class == $b->class,'if they are, the result is:',strcmp($a->name, $b->name),
  168. 'is a this class?', $a->name == $this->class->name,-1,
  169. 'is b this class?', $b->name == $this->class->name,1,
  170. 'otherwise, the result is:',strcmp($a->class, $b->class)
  171. );
  172. */
  173. // If both methods are defined in the same class, just compare the method names
  174. if ($a->class == $b->class)
  175. return strcmp($a->name, $b->name);
  176. // If one of them was declared by this class, it needs to be on top
  177. if ($a->name == $this->class->name)
  178. return -1;
  179. if ($b->name == $this->class->name)
  180. return 1;
  181. // Otherwise, get the parents of each methods declaring class, then compare which function has more "ancestors"
  182. $adepth = 0;
  183. $bdepth = 0;
  184. $parent = $a->getDeclaringClass();
  185. do
  186. {
  187. $adepth++;
  188. }
  189. while ($parent = $parent->getParentClass());
  190. $parent = $b->getDeclaringClass();
  191. do
  192. {
  193. $bdepth++;
  194. }
  195. while ($parent = $parent->getParentClass());
  196. return $bdepth - $adepth;
  197. }
  198. } // End Kodac_Class