/rocket_sled.class.php

https://github.com/iaindooley/RocketSled · PHP · 215 lines · 168 code · 36 blank · 11 comment · 22 complexity · edde976bb916d8b6a17ccf45e8cfc6df MD5 · raw file

  1. <?php
  2. require_once('runnable.interface.php');
  3. class RocketSled
  4. {
  5. private static $scan = NULL;
  6. private static $instance = NULL;
  7. private static $runnable = NULL;
  8. private static $autoload = NULL;
  9. private static $packages = NULL;
  10. private function __construct()
  11. {
  12. self::$runnable = self::defaultRunnable();
  13. self::$autoload = self::defaultAutoload();
  14. self::$scan = array(__DIR__.'/../');
  15. spl_autoload_register(self::$autoload);
  16. }
  17. public static function run()
  18. {
  19. self::instance();
  20. $runnable = self::$runnable;
  21. $runnable_object = $runnable();
  22. $runnable_object->run();
  23. }
  24. public static function defaultRunnable()
  25. {
  26. return function()
  27. {
  28. global $argv;
  29. /**
  30. * Get the class to run whether we're on the command line or in
  31. * the browser
  32. */
  33. if(isset($argv))
  34. $runnable_class = isset($argv[1]) ? $argv[1]:require_once('runnable.default.php');
  35. else
  36. $runnable_class = isset($_GET['r']) ? $_GET['r']:require_once('runnable.default.php');
  37. //Make sure no-one's trying to haxor us by running a class that's not runnable
  38. $refl = new ReflectionClass($runnable_class);
  39. if(!$refl->implementsInterface('RocketSled\\Runnable'))
  40. die('Running a class that does not implement interface Runnable is not allowed');
  41. $runnable = new $runnable_class();
  42. return $runnable;
  43. };
  44. }
  45. public static function defaultAutoload()
  46. {
  47. return function($class)
  48. {
  49. $ret = FALSE;
  50. $namespaced = explode('\\',$class);
  51. if(count($namespaced) > 1)
  52. {
  53. $class_part = strtolower(preg_replace('/^_/','',preg_replace('/([A-Z])/','_\1',array_pop($namespaced)))).'.class.php';
  54. foreach(RocketSled::scan() as $dir)
  55. {
  56. $fname = $dir.'/'.implode('/',$namespaced).'/'.$class_part;
  57. if(file_exists($fname))
  58. {
  59. require_once($fname);
  60. $ret = $fname;
  61. }
  62. }
  63. }
  64. else
  65. {
  66. $classes = RocketSled::filteredPackages(function($fname) use ($class,&$ret)
  67. {
  68. $ending = '.class.php';
  69. if(RocketSled::endsWith($fname,$ending))
  70. {
  71. if(str_replace(' ','',ucwords(str_replace('_',' ',str_replace($ending,'',basename($fname))))) === $class)
  72. {
  73. require_once($fname);
  74. $ret = $fname;
  75. }
  76. }
  77. });
  78. }
  79. return $ret;
  80. };
  81. }
  82. public static function instance()
  83. {
  84. if(self::$instance === NULL)
  85. self::$instance = new RocketSled();
  86. return self::$instance;
  87. }
  88. /**
  89. * Pass in an array of directories to scan
  90. */
  91. public static function scan($dirs = NULL)
  92. {
  93. self::instance();
  94. if($dirs !== NULL)
  95. {
  96. self::$scan = array_filter(array_unique($dirs),function($path)
  97. {
  98. return realpath($path);
  99. });
  100. }
  101. else
  102. return self::$scan;
  103. }
  104. public static function autoload(Closure $autoload = NULL)
  105. {
  106. self::instance();
  107. if($autoload !== NULL)
  108. {
  109. if(self::$autoload !== NULL)
  110. spl_autoload_unregister(self::$autoload);
  111. self::$autoload = $autoload;
  112. spl_autoload_register(self::$autoload);
  113. }
  114. else
  115. return self::$autoload;
  116. }
  117. public static function runnable(Closure $runnable = NULL)
  118. {
  119. self::instance();
  120. if($runnable !== NULL)
  121. self::$runnable = $runnable;
  122. else
  123. return self::$runnable;
  124. }
  125. public static function filteredPackages($callback)
  126. {
  127. return array_filter(self::packages(),$callback);
  128. }
  129. private static function packages()
  130. {
  131. if(self::$packages === NULL)
  132. {
  133. self::$packages = array();
  134. foreach(self::$scan as $dir)
  135. {
  136. $list = self::directoryList($dir);
  137. if(is_array($list) && count($list))
  138. self::$packages = array_merge(self::$packages,$list);
  139. }
  140. }
  141. return self::$packages;
  142. }
  143. /**
  144. * Courtesy of donovan dot pp at gmail dot com on http://au2.php.net/scandir
  145. */
  146. private static function directoryList($dir)
  147. {
  148. $path = '';
  149. $stack[] = $dir;
  150. while ($stack)
  151. {
  152. $thisdir = array_pop($stack);
  153. if($dircont = scandir($thisdir))
  154. {
  155. $i=0;
  156. while(isset($dircont[$i]))
  157. {
  158. if($dircont[$i] !== '.' && $dircont[$i] !== '..')
  159. {
  160. $current_file = "{$thisdir}/{$dircont[$i]}";
  161. if (is_file($current_file))
  162. $path[] = "{$thisdir}/{$dircont[$i]}";
  163. else if(is_dir($current_file))
  164. {
  165. $path[] = "{$thisdir}/{$dircont[$i]}";
  166. $stack[] = $current_file;
  167. }
  168. }
  169. $i++;
  170. }
  171. }
  172. }
  173. return $path;
  174. }
  175. public static function endsWith($str,$test)
  176. {
  177. return (substr($str, -strlen($test)) == $test);
  178. }
  179. }