bundle.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <?php namespace Laravel; defined('DS') or die('No direct script access.');
  2. use FilesystemIterator as fIterator;
  3. class Bundle {
  4. /**
  5. * All of the application's bundles.
  6. *
  7. * @var array
  8. */
  9. public static $bundles = array();
  10. /**
  11. * A cache of the parsed bundle elements.
  12. *
  13. * @var array
  14. */
  15. public static $elements = array();
  16. /**
  17. * All of the bundles that have been started.
  18. *
  19. * @var array
  20. */
  21. public static $started = array();
  22. /**
  23. * All of the bundles that have their routes files loaded.
  24. *
  25. * @var array
  26. */
  27. public static $routed = array();
  28. /**
  29. * Detect all of the installed bundles from disk.
  30. *
  31. * @param string $path
  32. * @return array
  33. */
  34. public static function detect($path)
  35. {
  36. return static::search($path);
  37. }
  38. /**
  39. * Detect all of the installed bundles from disk.
  40. *
  41. * @param string $path
  42. * @return array
  43. */
  44. protected static function search($path)
  45. {
  46. $bundles = array();
  47. $items = new fIterator($path);
  48. foreach ($items as $item)
  49. {
  50. // If the item is a directory, we'll search for a bundle.info file.
  51. // If one exists, we will add it to the bundle array. We will set
  52. // the location automatically since we know it.
  53. if ($item->isDir())
  54. {
  55. $path = $item->getRealPath().DS.'bundle.php';
  56. // If we found a file, we'll require in the array it contains
  57. // and add it to the directory. The info array will contain
  58. // basic info like the bundle name and any URIs it may
  59. // handle incoming requests for.
  60. if (file_exists($path))
  61. {
  62. $info = require $path;
  63. $info['location'] = dirname($path).DS;
  64. $bundles[$info['name']] = $info;
  65. continue;
  66. }
  67. // If a bundle.info file doesn't exist within a directory,
  68. // we'll recurse into the directory to keep searching in
  69. // the bundle directory for nested bundles.
  70. else
  71. {
  72. $recurse = static::detect($item->getRealPath());
  73. $bundles = array_merge($bundles, $recurse);
  74. }
  75. }
  76. }
  77. return $bundles;
  78. }
  79. /**
  80. * Register a bundle for the application.
  81. *
  82. * @param array $config
  83. * @return void
  84. */
  85. public static function register($config)
  86. {
  87. $defaults = array('handles' => null, 'auto' => false);
  88. // If a handles clause has been specified, we will cap it with a trailing
  89. // slash so the bundle is not extra greedy with its routes. Otherwise a
  90. // bundle that handles "s" would handle all routes beginning with "s".
  91. if (isset($config['handles']))
  92. {
  93. $config['handles'] = str_finish($config['handles'], '/');
  94. }
  95. static::$bundles[$config['name']] = array_merge($defaults, $config);
  96. }
  97. /**
  98. * Disable a bundle for the current request.
  99. *
  100. * @param string $bundle
  101. * @return void
  102. */
  103. public static function disable($bundle)
  104. {
  105. unset(static::$bundles[$bundle]);
  106. }
  107. /**
  108. * Load a bundle by running it's start-up script.
  109. *
  110. * If the bundle has already been started, no action will be taken.
  111. *
  112. * @param string $bundle
  113. * @return void
  114. */
  115. public static function start($bundle)
  116. {
  117. if (static::started($bundle)) return;
  118. if ( ! static::exists($bundle))
  119. {
  120. throw new \Exception("Bundle [$bundle] has not been installed.");
  121. }
  122. // Each bundle may have a "start" script which is responsible for preparing
  123. // the bundle for use by the application. The start script may register any
  124. // classes the bundle uses with the auto-loader, or perhaps will start any
  125. // dependent bundles so that they are available.
  126. if (file_exists($path = static::path($bundle).'start'.EXT))
  127. {
  128. require $path;
  129. }
  130. // Each bundle may also have a "routes" file which is responsible for
  131. // registering the bundle's routes. This is kept separate from the
  132. // start script for reverse routing efficiency purposes.
  133. static::routes($bundle);
  134. Event::fire("started: {$bundle}");
  135. static::$started[] = strtolower($bundle);
  136. }
  137. /**
  138. * Load the "routes" file for a given bundle.
  139. *
  140. * @param string $bundle
  141. * @return void
  142. */
  143. public static function routes($bundle)
  144. {
  145. $path = static::path($bundle).'routes'.EXT;
  146. if ( ! static::routed($bundle) and file_exists($path))
  147. {
  148. require $path;
  149. }
  150. static::$routed[] = $bundle;
  151. }
  152. /**
  153. * Determine which bundle handles the given URI.
  154. *
  155. * If no bundle is assigned to handle the URI, the default bundle is returned.
  156. *
  157. * @param string $uri
  158. * @return string
  159. */
  160. public static function handles($uri)
  161. {
  162. $uri = rtrim($uri, '/').'/';
  163. foreach (static::$bundles as $key => $value)
  164. {
  165. if (starts_with($uri, $value['handles'])) return $key;
  166. }
  167. return DEFAULT_BUNDLE;
  168. }
  169. /**
  170. * Deteremine if a bundle exists within the bundles directory.
  171. *
  172. * @param string $bundle
  173. * @return bool
  174. */
  175. public static function exists($bundle)
  176. {
  177. return $bundle == DEFAULT_BUNDLE or in_array(strtolower($bundle), static::names());
  178. }
  179. /**
  180. * Determine if a given bundle has been started for the request.
  181. *
  182. * @param string $bundle
  183. * @return void
  184. */
  185. public static function started($bundle)
  186. {
  187. return in_array(strtolower($bundle), static::$started);
  188. }
  189. /**
  190. * Determine if a given bundle has its routes file loaded.
  191. *
  192. * @param string $bundle
  193. * @return void
  194. */
  195. public static function routed($bundle)
  196. {
  197. return in_array(strtolower($bundle), static::$routed);
  198. }
  199. /**
  200. * Get the identifier prefix for the bundle.
  201. *
  202. * @param string $bundle
  203. * @return string
  204. */
  205. public static function prefix($bundle)
  206. {
  207. return ($bundle !== DEFAULT_BUNDLE) ? "{$bundle}::" : '';
  208. }
  209. /**
  210. * Get the class prefix for a given bundle.
  211. *
  212. * @param string $bundle
  213. * @return string
  214. */
  215. public static function class_prefix($bundle)
  216. {
  217. return ($bundle !== DEFAULT_BUNDLE) ? Str::classify($bundle).'_' : '';
  218. }
  219. /**
  220. * Return the root bundle path for a given bundle.
  221. *
  222. * <code>
  223. * // Returns the bundle path for the "admin" bundle
  224. * $path = Bundle::path('admin');
  225. *
  226. * // Returns the path('app') constant as the default bundle
  227. * $path = Bundle::path('application');
  228. * </code>
  229. *
  230. * @param string $bundle
  231. * @return string
  232. */
  233. public static function path($bundle)
  234. {
  235. return ($bundle == DEFAULT_BUNDLE) ? path('app') : static::$bundles[$bundle]['location'];
  236. }
  237. /**
  238. * Return the root asset path for the given bundle.
  239. *
  240. * @param string $bundle
  241. * @return string
  242. */
  243. public static function assets($bundle)
  244. {
  245. return ($bundle != DEFAULT_BUNDLE) ? URL::base()."/bundles/{$bundle}/" : URL::base().'/';
  246. }
  247. /**
  248. * Get the bundle name from a given identifier.
  249. *
  250. * <code>
  251. * // Returns "admin" as the bundle name for the identifier
  252. * $bundle = Bundle::name('admin::home.index');
  253. * </code>
  254. *
  255. * @param string $identifier
  256. * @return string
  257. */
  258. public static function name($identifier)
  259. {
  260. list($bundle, $element) = static::parse($identifier);
  261. return $bundle;
  262. }
  263. /**
  264. * Get the element name from a given identifier.
  265. *
  266. * <code>
  267. * // Returns "home.index" as the element name for the identifier
  268. * $bundle = Bundle::bundle('admin::home.index');
  269. * </code>
  270. *
  271. * @param string $identifier
  272. * @return string
  273. */
  274. public static function element($identifier)
  275. {
  276. list($bundle, $element) = static::parse($identifier);
  277. return $element;
  278. }
  279. /**
  280. * Reconstruct an identifier from a given bundle and element.
  281. *
  282. * <code>
  283. * // Returns "admin::home.index"
  284. * $identifier = Bundle::identifier('admin', 'home.index');
  285. *
  286. * // Returns "home.index"
  287. * $identifier = Bundle::identifier('application', 'home.index');
  288. * </code>
  289. *
  290. * @param string $bundle
  291. * @param string $element
  292. * @return string
  293. */
  294. public static function identifier($bundle, $element)
  295. {
  296. return (is_null($bundle) or $bundle == DEFAULT_BUNDLE) ? $element : $bundle.'::'.$element;
  297. }
  298. /**
  299. * Return the bundle name if it exists, else return the default bundle.
  300. *
  301. * @param string $bundle
  302. * @return string
  303. */
  304. public static function resolve($bundle)
  305. {
  306. return (static::exists($bundle)) ? $bundle : DEFAULT_BUNDLE;
  307. }
  308. /**
  309. * Parse a element identifier and return the bundle name and element.
  310. *
  311. * <code>
  312. * // Returns array(null, 'admin.user')
  313. * $element = Bundle::parse('admin.user');
  314. *
  315. * // Parses "admin::user" and returns array('admin', 'user')
  316. * $element = Bundle::parse('admin::user');
  317. * </code>
  318. *
  319. * @param string $identifier
  320. * @return array
  321. */
  322. public static function parse($identifier)
  323. {
  324. // The parsed elements are cached so we don't have to reparse them on each
  325. // subsequent request for the parsed element. So, if we've already parsed
  326. // the given element, we'll just return the cached copy.
  327. if (isset(static::$elements[$identifier]))
  328. {
  329. return static::$elements[$identifier];
  330. }
  331. if (strpos($identifier, '::') !== false)
  332. {
  333. $element = explode('::', strtolower($identifier));
  334. }
  335. // If no bundle is in the identifier, we will insert the default bundle
  336. // since classes like Config and Lang organize their items by bundle.
  337. // The "application" folder essentially behaves as a bundle.
  338. else
  339. {
  340. $element = array(DEFAULT_BUNDLE, strtolower($identifier));
  341. }
  342. return static::$elements[$identifier] = $element;
  343. }
  344. /**
  345. * Get the information for a given bundle.
  346. *
  347. * @param string $bundle
  348. * @return object
  349. */
  350. public static function get($bundle)
  351. {
  352. return (object) array_get(static::$bundles, $bundle);
  353. }
  354. /**
  355. * Get all of the installed bundles for the application.
  356. *
  357. * @return array
  358. */
  359. public static function all()
  360. {
  361. return static::$bundles;
  362. }
  363. /**
  364. * Get all of the installed bundle names.
  365. *
  366. * @return array
  367. */
  368. public static function names()
  369. {
  370. return array_keys(static::$bundles);
  371. }
  372. }