bundle.php 10.6 KB
Newer Older
Taylor Otwell committed
1
<?php namespace Laravel; defined('DS') or die('No direct script access.');
2

Taylor Otwell committed
3
use Laravel\Routing\Router;
4 5
use FilesystemIterator as fIterator;

6 7 8 9 10 11 12
class Bundle {

	/**
	 * All of the application's bundles.
	 *
	 * @var array
	 */
13
	public static $bundles = array();
14 15 16 17 18 19

	/**
	 * A cache of the parsed bundle elements.
	 *
	 * @var array
	 */
20
	public static $elements = array();
21 22 23 24 25 26

	/**
	 * All of the bundles that have been started.
	 *
	 * @var array
	 */
27 28 29
	public static $started = array();

	/**
Taylor Otwell committed
30 31 32 33 34 35 36
	 * All of the bundles that have their routes files loaded.
	 *
	 * @var array
	 */
	public static $routed = array();

	/**
37
	 * Register the bundle for the application.
38
	 *
39 40
	 * @param  string  $bundle
	 * @param  array   $config
41 42
	 * @return void
	 */
43
	public static function register($bundle, $config = array())
44 45
	{
		$defaults = array('handles' => null, 'auto' => false);
Taylor Otwell committed
46

47 48 49 50
		// If the given configuration is actually a string, we will assume it is a
		// location and set the bundle name to match it. This is common for most
		// bundles who simply live in the root bundle directory.
		if (is_string($config))
51
		{
52 53 54
			$bundle = $config;

			$config = array('location' => $bundle);
55 56
		}

Taylor Otwell committed
57
		// If no location is set, we will set the location to match the name of
58 59 60 61 62 63
		// the bundle. This is for bundles who are installed to the root of
		// the bundle directory so a location was not set.
		if ( ! isset($config['location']))
		{
			$config['location'] = $bundle;
		}
64

65
		static::$bundles[$bundle] = array_merge($defaults, $config);
66 67 68 69

		// It is possible for the develoepr to specify auto-loader mappings
		// directly on the bundle registration. This provides a convenient
		// way to register mappings withuot a bootstrap.
70 71
		if (isset($config['autoloads']))
		{
72
			static::autoloads($bundle, $config);
73
		}
74 75 76
	}

	/**
77 78 79 80 81 82 83 84 85 86 87
	 * Load a bundle by running it's start-up script.
	 *
	 * If the bundle has already been started, no action will be taken.
	 *
	 * @param  string  $bundle
	 * @return void
	 */
	public static function start($bundle)
	{
		if (static::started($bundle)) return;

88
		if ( ! static::exists($bundle))
89 90 91 92
		{
			throw new \Exception("Bundle [$bundle] has not been installed.");
		}

Taylor Otwell committed
93 94 95
		// Each bundle may have a start script which is responsible for preparing
		// the bundle for use by the application. The start script may register
		// any classes the bundle uses with the auto-loader, etc.
96
		if (file_exists($path = static::path($bundle).'start'.EXT))
97
		{
98
			require $path;
99 100 101 102 103 104
		}

		// Each bundle may also have a "routes" file which is responsible for
		// registering the bundle's routes. This is kept separate from the
		// start script for reverse routing efficiency purposes.
		static::routes($bundle);
105

106
		Event::fire("laravel.started: {$bundle}");
107

108
		static::$started[] = strtolower($bundle);
109 110 111 112 113 114 115 116 117 118
	}

	/**
	 * Load the "routes" file for a given bundle.
	 *
	 * @param  string  $bundle
	 * @return void
	 */
	public static function routes($bundle)
	{
Taylor Otwell committed
119 120
		if (static::routed($bundle)) return;

Taylor Otwell committed
121 122
		$path = static::path($bundle).'routes'.EXT;

123 124 125
		// By setting the bundle property on the router the router knows what
		// value to replace the (:bundle) place-holder with when the bundle
		// routes are added, keeping the routes flexible.
Taylor Otwell committed
126
		Router::$bundle = static::option($bundle, 'handles');
127

Taylor Otwell committed
128
		if ( ! static::routed($bundle) and file_exists($path))
129
		{
Taylor Otwell committed
130 131
			static::$routed[] = $bundle;

132
			require $path;
133 134 135 136
		}
	}

	/**
137 138 139 140 141 142
	 * Register the auto-loading configuration for a bundle.
	 *
	 * @param  string  $bundle
	 * @param  array   $config
	 * @return void
	 */
143
	protected static function autoloads($bundle, $config)
144
	{
145
		$path = rtrim(Bundle::path($bundle), DS);
146

147
		foreach ($config['autoloads'] as $type => $mappings)
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
		{
			// When registering each type of mapping we'll replace the (:bundle)
			// place-holder with the path to the bundle's root directory, so
			// the developer may dryly register the mappings.
			$mappings = array_map(function($mapping) use ($path)
			{
				return str_replace('(:bundle)', $path, $mapping);

			}, $mappings);

			// Once the mappings are formatted, we will call the Autoloader
			// function matching the mapping type and pass in the array of
			// mappings so they can be registered and used.
			Autoloader::$type($mappings);
		}
	}

	/**
166 167 168 169 170 171 172 173 174 175 176
	 * Disable a bundle for the current request.
	 *
	 * @param  string  $bundle
	 * @return void
	 */
	public static function disable($bundle)
	{
		unset(static::$bundles[$bundle]);
	}

	/**
177
	 * Determine which bundle handles the given URI.
178
	 *
Taylor Otwell committed
179
	 * The default bundle is returned if no other bundle is assigned.
180
	 *
Phill Sparks committed
181
	 * @param  string  $uri
182
	 * @return string
183
	 */
184
	public static function handles($uri)
185
	{
186 187
		$uri = rtrim($uri, '/').'/';

188 189
		foreach (static::$bundles as $key => $value)
		{
190 191 192 193
			if (isset($value['handles']) and starts_with($uri, $value['handles'].'/'))
			{
				return $key;
			}
194
		}
195

196
		return DEFAULT_BUNDLE;
197 198 199 200 201 202 203 204 205 206
	}

	/**
	 * Deteremine if a bundle exists within the bundles directory.
	 *
	 * @param  string  $bundle
	 * @return bool
	 */
	public static function exists($bundle)
	{
207
		return $bundle == DEFAULT_BUNDLE or in_array(strtolower($bundle), static::names());
208 209 210 211 212 213 214 215 216 217 218 219 220 221
	}

	/**
	 * Determine if a given bundle has been started for the request.
	 *
	 * @param  string  $bundle
	 * @return void
	 */
	public static function started($bundle)
	{
		return in_array(strtolower($bundle), static::$started);
	}

	/**
Taylor Otwell committed
222 223 224 225 226 227 228 229 230 231 232
	 * Determine if a given bundle has its routes file loaded.
	 *
	 * @param  string  $bundle
	 * @return void
	 */
	public static function routed($bundle)
	{
		return in_array(strtolower($bundle), static::$routed);
	}

	/**
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
	 * Get the identifier prefix for the bundle.
	 *
	 * @param  string  $bundle
	 * @return string
	 */
	public static function prefix($bundle)
	{
		return ($bundle !== DEFAULT_BUNDLE) ? "{$bundle}::" : '';
	}

	/**
	 * Get the class prefix for a given bundle.
	 *
	 * @param  string  $bundle
	 * @return string
	 */
	public static function class_prefix($bundle)
	{
		return ($bundle !== DEFAULT_BUNDLE) ? Str::classify($bundle).'_' : '';
	}

	/**
	 * Return the root bundle path for a given bundle.
	 *
	 * <code>
	 *		// Returns the bundle path for the "admin" bundle
	 *		$path = Bundle::path('admin');
	 *
Taylor Otwell committed
261
	 *		// Returns the path('app') constant as the default bundle
262 263 264 265 266 267 268 269
	 *		$path = Bundle::path('application');
	 * </code>
	 *
	 * @param  string  $bundle
	 * @return string
	 */
	public static function path($bundle)
	{
270 271 272 273
		if (is_null($bundle) or $bundle === DEFAULT_BUNDLE)
		{
			return path('app');
		}
274
		elseif ($location = array_get(static::$bundles, $bundle.'.location'))
275
		{
276 277 278 279 280 281 282 283 284 285 286
			// If the bundle location starts with "path: ", we will assume that a raw
			// path has been specified and will simply return it. Otherwise, we'll
			// prepend the bundle directory path onto the location and return.
			if (starts_with($location, 'path: '))
			{
				return str_finish(substr($location, 6), DS);
			}
			else
			{
				return str_finish(path('bundle').$location, DS);
			}
287
		}
288 289 290 291 292 293 294 295 296 297
	}

	/**
	 * Return the root asset path for the given bundle.
	 *
	 * @param  string  $bundle
	 * @return string
	 */
	public static function assets($bundle)
	{
Taylor Otwell committed
298 299
		if (is_null($bundle)) return static::assets(DEFAULT_BUNDLE);

300
		return ($bundle != DEFAULT_BUNDLE) ? URL::base()."/bundles/{$bundle}/" : URL::base().'/';
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
	}

	/**
	 * Get the bundle name from a given identifier.
	 *
	 * <code>
	 *		// Returns "admin" as the bundle name for the identifier
	 *		$bundle = Bundle::name('admin::home.index');
	 * </code>
	 *
	 * @param  string  $identifier
	 * @return string
	 */
	public static function name($identifier)
	{
		list($bundle, $element) = static::parse($identifier);

		return $bundle;
	}

	/**
	 * Get the element name from a given identifier.
	 *
	 * <code>
	 *		// Returns "home.index" as the element name for the identifier
	 *		$bundle = Bundle::bundle('admin::home.index');
	 * </code>
	 *
	 * @param  string  $identifier
	 * @return string
	 */
	public static function element($identifier)
	{
		list($bundle, $element) = static::parse($identifier);

		return $element;
	}

	/**
	 * Reconstruct an identifier from a given bundle and element.
	 *
	 * <code>
	 *		// Returns "admin::home.index"
	 *		$identifier = Bundle::identifier('admin', 'home.index');
	 *
	 *		// Returns "home.index"
	 *		$identifier = Bundle::identifier('application', 'home.index');
	 * </code>
	 *
	 * @param  string  $bundle
	 * @param  string  $element
	 * @return string
	 */
	public static function identifier($bundle, $element)
	{
		return (is_null($bundle) or $bundle == DEFAULT_BUNDLE) ? $element : $bundle.'::'.$element;
	}

	/**
	 * Return the bundle name if it exists, else return the default bundle.
	 *
	 * @param  string  $bundle
	 * @return string
	 */
	public static function resolve($bundle)
	{
		return (static::exists($bundle)) ? $bundle : DEFAULT_BUNDLE;
	}

	/**
	 * Parse a element identifier and return the bundle name and element.
	 *
	 * <code>
	 *		// Returns array(null, 'admin.user')
	 *		$element = Bundle::parse('admin.user');
	 *
	 *		// Parses "admin::user" and returns array('admin', 'user')
	 *		$element = Bundle::parse('admin::user');
	 * </code>
	 *
	 * @param  string  $identifier
	 * @return array
	 */
	public static function parse($identifier)
	{
		// The parsed elements are cached so we don't have to reparse them on each
387 388
		// subsequent request for the parsed element. So if we've already parsed
		// the given element, we'll just return the cached copy as the value.
389 390 391 392 393 394 395 396 397 398 399
		if (isset(static::$elements[$identifier]))
		{
			return static::$elements[$identifier];
		}

		if (strpos($identifier, '::') !== false)
		{
			$element = explode('::', strtolower($identifier));
		}
		// If no bundle is in the identifier, we will insert the default bundle
		// since classes like Config and Lang organize their items by bundle.
400
		// The application folder essentially behaves as a default bundle.
401 402 403 404 405 406 407 408 409
		else
		{
			$element = array(DEFAULT_BUNDLE, strtolower($identifier));
		}

		return static::$elements[$identifier] = $element;
	}

	/**
410 411 412
	 * Get the information for a given bundle.
	 *
	 * @param  string  $bundle
413
	 * @return object
414 415 416
	 */
	public static function get($bundle)
	{
417
		return array_get(static::$bundles, $bundle);
418 419 420
	}

	/**
Taylor Otwell committed
421 422 423 424
	 * Get an option for a given bundle.
	 *
	 * @param  string  $bundle
	 * @param  string  $option
425
	 * @param  mixed   $default
Taylor Otwell committed
426 427
	 * @return mixed
	 */
428
	public static function option($bundle, $option, $default = null)
Taylor Otwell committed
429 430 431
	{
		$bundle = static::get($bundle);

432 433 434 435 436 437
		if (is_null($bundle))
		{
			return value($default);
		}

		return array_get($bundle, $option, $default);
Taylor Otwell committed
438 439 440
	}

	/**
Taylor Otwell committed
441
	 * Get all of the installed bundles for the application.
442 443 444 445 446
	 *
	 * @return array
	 */
	public static function all()
	{
Taylor Otwell committed
447 448 449 450 451 452 453 454 455 456
		return static::$bundles;
	}

	/**
	 * Get all of the installed bundle names.
	 *
	 * @return array
	 */
	public static function names()
	{
457
		return array_keys(static::$bundles);
458 459 460
	}

}