/frameworks/solar/1.1.1/source/solar/Solar/Class.php

https://github.com/ggunlugu/ornekler · PHP · 283 lines · 119 code · 25 blank · 139 comment · 22 complexity · 713a72bbd467f617297aacec6eb71a80 MD5 · raw file

  1. <?php
  2. /**
  3. *
  4. * Static support methods for class information.
  5. *
  6. * @category Solar
  7. *
  8. * @package Solar
  9. *
  10. * @author Paul M. Jones <pmjones@solarphp.com>
  11. *
  12. * @license http://opensource.org/licenses/bsd-license.php BSD
  13. *
  14. * @version $Id: Class.php 4370 2010-02-11 15:41:19Z pmjones $
  15. *
  16. */
  17. class Solar_Class
  18. {
  19. /**
  20. *
  21. * Parent hierarchy for all classes.
  22. *
  23. * We keep track of this so configs, locale strings, etc. can be
  24. * inherited properly from parent classes, and so we don't need to
  25. * recalculate it on each request.
  26. *
  27. * @var array
  28. *
  29. */
  30. protected static $_parents = array();
  31. /**
  32. *
  33. * Loads a class or interface file from the include_path.
  34. *
  35. * Thanks to Robert Gonzalez for the report leading to this method.
  36. *
  37. * @param string $name A Solar (or other) class or interface name.
  38. *
  39. * @return void
  40. *
  41. * @todo Add localization for errors
  42. *
  43. */
  44. public static function autoload($name)
  45. {
  46. // did we ask for a non-blank name?
  47. if (trim($name) == '') {
  48. throw Solar::exception(
  49. 'Solar_Class',
  50. 'ERR_AUTOLOAD_EMPTY',
  51. 'No class or interface named for loading.',
  52. array('name' => $name)
  53. );
  54. }
  55. // pre-empt further searching for the named class or interface.
  56. // do not use autoload, because this method is registered with
  57. // spl_autoload already.
  58. $exists = class_exists($name, false)
  59. || interface_exists($name, false);
  60. if ($exists) {
  61. return;
  62. }
  63. // convert the class name to a file path
  64. $file = Solar_Class::nameToFile($name);
  65. // include the file and check for failure. we use Solar_File::load()
  66. // instead of require() so we can see the exception backtrace.
  67. Solar_File::load($file);
  68. // if the class or interface was not in the file, we have a problem.
  69. // do not use autoload, because this method is registered with
  70. // spl_autoload already.
  71. $exists = class_exists($name, false)
  72. || interface_exists($name, false);
  73. if (! $exists) {
  74. throw Solar::exception(
  75. 'Solar_Class',
  76. 'ERR_AUTOLOAD_FAILED',
  77. 'Class or interface does not exist in loaded file',
  78. array('name' => $name, 'file' => $file)
  79. );
  80. }
  81. }
  82. /**
  83. *
  84. * Converts a namespace-and-classname to a file path.
  85. *
  86. * Implements PSR-0 as defined by the PHP Project Interoperability Group.
  87. *
  88. * <http://groups.google.com/group/php-standards/web/final-proposal>
  89. *
  90. * @param string $spec The namespace-and-classname.
  91. *
  92. * @return string The converted file path.
  93. *
  94. */
  95. public static function nameToFile($spec)
  96. {
  97. // using namespaces? (look for last namespace separator)
  98. $pos = strrpos($spec, '\\');
  99. if ($pos === false) {
  100. // no namespace, class portion only
  101. $namespace = '';
  102. $class = $spec;
  103. } else {
  104. // pre-convert namespace portion to file path
  105. $namespace = substr($spec, 0, $pos);
  106. $namespace = str_replace('\\', DIRECTORY_SEPARATOR, $namespace)
  107. . DIRECTORY_SEPARATOR;
  108. // class portion
  109. $class = substr($spec, $pos + 1);
  110. }
  111. // convert class underscores, and done
  112. return $namespace
  113. . str_replace('_', DIRECTORY_SEPARATOR, $class)
  114. . '.php';
  115. }
  116. /**
  117. *
  118. * Returns an array of the parent classes for a given class.
  119. *
  120. * @param string|object $spec The class or object to find parents
  121. * for.
  122. *
  123. * @param bool $include_class If true, the class name is element 0,
  124. * the parent is element 1, the grandparent is element 2, etc.
  125. *
  126. * @return array
  127. *
  128. */
  129. public static function parents($spec, $include_class = false)
  130. {
  131. if (is_object($spec)) {
  132. $class = get_class($spec);
  133. } else {
  134. $class = $spec;
  135. }
  136. // do we need to load the parent stack?
  137. if (empty(Solar_Class::$_parents[$class])) {
  138. // use SPL class_parents(), which uses autoload by default. use
  139. // only the array values, not the keys, since that messes up BC.
  140. $parents = array_values(class_parents($class));
  141. Solar_Class::$_parents[$class] = array_reverse($parents);
  142. }
  143. // get the parent stack
  144. $stack = Solar_Class::$_parents[$class];
  145. // add the class itself?
  146. if ($include_class) {
  147. $stack[] = $class;
  148. }
  149. // done
  150. return $stack;
  151. }
  152. /**
  153. *
  154. * Returns the directory for a specific class, plus an optional
  155. * subdirectory path.
  156. *
  157. * @param string|object $spec The class or object to find parents
  158. * for.
  159. *
  160. * @param string $sub Append this subdirectory.
  161. *
  162. * @return string The class directory, with optional subdirectory.
  163. *
  164. */
  165. public static function dir($spec, $sub = null)
  166. {
  167. if (is_object($spec)) {
  168. $class = get_class($spec);
  169. } else {
  170. $class = $spec;
  171. }
  172. // convert the class to a base directory to stem from
  173. $base = str_replace('_', DIRECTORY_SEPARATOR, $class);
  174. // does the directory exist?
  175. $dir = Solar_Dir::exists($base);
  176. if (! $dir) {
  177. throw Solar::exception(
  178. 'Solar_Class',
  179. 'ERR_NO_DIR_FOR_CLASS',
  180. 'Directory does not exist',
  181. array('class' => $class, 'base' => $base)
  182. );
  183. } else {
  184. return Solar_Dir::fix($dir . DIRECTORY_SEPARATOR. $sub);
  185. }
  186. }
  187. /**
  188. *
  189. * Returns the path to a file under a specific class.
  190. *
  191. * @param string|object $spec The class or object to use as the base path.
  192. *
  193. * @param string $file Append this file path.
  194. *
  195. * @return string The path to the file under the class.
  196. *
  197. */
  198. public static function file($spec, $file)
  199. {
  200. $dir = Solar_Class::dir($spec);
  201. return Solar_File::exists($dir . $file);
  202. }
  203. /**
  204. *
  205. * Find the vendor name of a given class or object; this is effectively
  206. * the part of the class name that comes before the first underscore.
  207. *
  208. * @param mixed $spec An object, or a class name.
  209. *
  210. * @return string The vendor name of the class or object.
  211. *
  212. */
  213. public static function vendor($spec)
  214. {
  215. if (is_object($spec)) {
  216. $class = get_class($spec);
  217. } else {
  218. $class = $spec;
  219. }
  220. // find the first underscore
  221. $pos = strpos($class, '_');
  222. if ($pos !== false) {
  223. // return the part up to the first underscore
  224. return substr($class, 0, $pos);
  225. } else {
  226. // no underscores, must be an arch-class
  227. return $class;
  228. }
  229. }
  230. /**
  231. *
  232. * Find the vendors of a given class or object and its parents.
  233. *
  234. * @param mixed $spec An object, or a class name.
  235. *
  236. * @return array The vendor names of the class or object hierarchy.
  237. *
  238. */
  239. public static function vendors($spec)
  240. {
  241. // vendor listing
  242. $stack = array();
  243. // get the list of parents
  244. $parents = Solar_Class::parents($spec, true);
  245. // look through vendor names
  246. $old = null;
  247. foreach ($parents as $class) {
  248. $new = Solar_Class::vendor($class);
  249. if ($new != $old) {
  250. // not the same, add the current vendor name and suffix
  251. $stack[] = $new;
  252. }
  253. // retain old vendor for next loop
  254. $old = $new;
  255. }
  256. return $stack;
  257. }
  258. }