autoloader.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <?php
  2. /**
  3. *
  4. *
  5. * @author Taddeus Kroes
  6. * @version 1.0
  7. * @date 13-07-2012
  8. */
  9. namespace Minimalistic;
  10. require_once 'base.php';
  11. /**
  12. * Object that to automatically load classes within a root directory.
  13. *
  14. * An Autoloader instance can register itself to the SPL autoload stack.
  15. *
  16. * @package Minimalistic
  17. */
  18. class Autoloader extends Base {
  19. /**
  20. * The root directory to look in.
  21. *
  22. * @var string
  23. */
  24. private $root_directory;
  25. /**
  26. * The namespace classes in the root directory are expected to be in.
  27. *
  28. * This namespace is removed from loaded class names.
  29. *
  30. * @var string
  31. * @todo implement this
  32. */
  33. private $root_namespace = '';
  34. /**
  35. * Whether to throw an exception when a class file does not exist.
  36. *
  37. * @var bool
  38. */
  39. private $throw_errors;
  40. /**
  41. * Create a new Autoloader instance.
  42. *
  43. * @param string $directory Root directory of the autoloader.
  44. * @param bool $throw Whether to throw an exception when a class file does not exist.
  45. */
  46. function __construct($directory, $throw=true) {
  47. $this->set_root_directory($directory);
  48. $this->set_throw_errors($throw);
  49. }
  50. /**
  51. * Set whether to throw an exception when a class file does not exist.
  52. *
  53. * @param bool $throw Whether to throw exceptions.
  54. */
  55. function set_throw_errors($throw) {
  56. $this->throw_errors = !!$throw;
  57. }
  58. /**
  59. * Whether an exception is thrown when a class file does not exist.
  60. *
  61. * @returns bool
  62. */
  63. function get_throw_errors() {
  64. return $this->throw_errors;
  65. }
  66. /**
  67. * Set the root directory from which classes are loaded.
  68. *
  69. * @param string $directory The new root directory.
  70. */
  71. function set_root_directory($directory) {
  72. $this->root_directory = self::path_with_slash($directory);
  73. }
  74. /**
  75. * Get the root directory from which classes are loaded.
  76. *
  77. * @returns string
  78. */
  79. function get_root_directory() {
  80. return $this->root_directory;
  81. }
  82. /**
  83. * Append a slash ('/') to the given directory name, if it is not already there.
  84. *
  85. * @param string $directory The directory to append a slash to.
  86. * @returns string
  87. */
  88. static function path_with_slash($directory) {
  89. return $directory[strlen($directory) - 1] == '/' ? $directory : $directory.'/';
  90. }
  91. /**
  92. * Convert a class name to a file name.
  93. *
  94. * Uppercase letters are converted to lowercase and prepended
  95. * by an underscore ('_').
  96. *
  97. * @param string $classname The class name to convert.
  98. * @returns string
  99. */
  100. static function classname_to_filename($classname) {
  101. return strtolower(preg_replace('/(?<=.)([A-Z])/', '_\\1', $classname));
  102. }
  103. /**
  104. * Create the path to a class file.
  105. *
  106. * Any namespace prepended to the class name is split on '\', the
  107. * namespace levels are used to indicate directory names.
  108. *
  109. * @param string $classname The name of the class to create the file path of.
  110. */
  111. function create_path($classname) {
  112. $namespaces = array_filter(explode('\\', $classname));
  113. $dirs = array_map('self::classname_to_filename', $namespaces);
  114. $path = $this->root_directory;
  115. if( count($dirs) > 1 )
  116. $path .= implode('/', array_slice($dirs, 0, count($dirs) - 1)).'/';
  117. $path .= end($dirs).'.php';
  118. return strtolower($path);
  119. }
  120. /**
  121. * Load a class.
  122. *
  123. * Any namespace prepended to the class name is split on '\', the
  124. * namespace levels are used to indicate directory names.
  125. *
  126. * @param string $classname The name of the class to load, including pepended namespace.
  127. * @param bool $throw Whether to throw an exception if the class file does not exist.
  128. * @returns bool
  129. * @throws FileNotFoundError If the class file does not exist.
  130. */
  131. function load_class($classname, $throw=true) {
  132. $path = $this->create_path($classname);
  133. if( !file_exists($path) ) {
  134. if( !$throw || !$this->throw_errors )
  135. return false;
  136. throw new FileNotFoundError($path);
  137. }
  138. require_once $path;
  139. return true;
  140. }
  141. /**
  142. * Register the autoloader object to the SPL autoload stack.
  143. *
  144. * @param bool $prepend Whether to prepend the autoloader function to
  145. * the stack, instead of appending it.
  146. */
  147. function register($prepend=false) {
  148. spl_autoload_register(array($this, 'load_class'), true, $prepend);
  149. }
  150. }
  151. ?>