Module.php 18.1 KB
Newer Older
w  
Qiang Xue committed
1 2 3 4 5 6 7 8 9 10 11
<?php
/**
 * Module class file.
 *
 * @link http://www.yiiframework.com/
 * @copyright Copyright &copy; 2008-2012 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\base;

Qiang Xue committed
12 13
use yii\util\FileHelper;

w  
Qiang Xue committed
14 15 16
/**
 * Module is the base class for module and application classes.
 *
Qiang Xue committed
17
 * Module mainly manages application components and sub-modules that belongs to a module.
w  
Qiang Xue committed
18
 *
Qiang Xue committed
19 20
 * @property string $uniqueId An ID that uniquely identifies this module among all modules within
 * the current application.
Qiang Xue committed
21 22 23 24 25 26
 * @property string $basePath The root directory of the module. Defaults to the directory containing the module class.
 * @property array $modules The configuration of the currently installed modules (module ID => configuration).
 * @property array $components The application components (indexed by their IDs).
 * @property array $import List of aliases to be imported. This property is write-only.
 * @property array $aliases List of aliases to be defined. This property is write-only.
 *
w  
Qiang Xue committed
27 28 29
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
Qiang Xue committed
30
abstract class Module extends Component
w  
Qiang Xue committed
31
{
m  
Qiang Xue committed
32 33 34 35
	/**
	 * @var array custom module parameters (name => value).
	 */
	public $params = array();
w  
Qiang Xue committed
36
	/**
Qiang Xue committed
37
	 * @var array the IDs of the application components that should be preloaded when this module is created.
w  
Qiang Xue committed
38 39
	 */
	public $preload = array();
Qiang Xue committed
40 41 42 43 44 45 46 47
	/**
	 * @var string an ID that uniquely identifies this module among other modules which have the same [[parent]].
	 */
	public $id;
	/**
	 * @var Module the parent module of this module. Null if this module does not have a parent.
	 */
	public $module;
Qiang Xue committed
48 49 50 51 52 53
	/**
	 * @var mixed the layout that should be applied for views within this module. This refers to a view name
	 * relative to [[layoutPath]]. If this is not set, it means the layout value of the [[module|parent module]]
	 * will be taken. If this is false, layout will be disabled within this module.
	 */
	public $layout;
Qiang Xue committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
	/**
	 * @var array mapping from controller ID to controller configurations.
	 * Each name-value pair specifies the configuration of a single controller.
	 * A controller configuration can be either a string or an array.
	 * If the former, the string should be the class name or path alias of the controller.
	 * If the latter, the array must contain a 'class' element which specifies
	 * the controller's class name or path alias, and the rest of the name-value pairs
	 * in the array are used to initialize the corresponding controller properties. For example,
	 *
	 * ~~~
	 * array(
	 *   'account' => '@application/controllers/UserController',
	 *   'article' => array(
	 *      'class' => '@application/controllers/PostController',
	 *      'pageTitle' => 'something new',
	 *   ),
	 * )
	 * ~~~
	 */
	public $controllers = array();
	/**
	 * @return string the default route of this module. Defaults to 'default'.
	 * The route may consist of child module ID, controller ID, and/or action ID.
	 * For example, `help`, `post/create`, `admin/post/create`.
	 * If action ID is not given, it will take the default value as specified in
	 * [[Controller::defaultAction]].
	 */
	public $defaultRoute = 'default';
	/**
	 * @var string the root directory of the module.
	 */
	protected $_basePath;
Qiang Xue committed
86 87 88 89 90 91 92 93
	/**
	 * @var string the root directory that contains view files.
	 */
	protected $_viewPath;
	/**
	 * @var string the root directory that contains layout view files.
	 */
	protected $_layoutPath;
Qiang Xue committed
94 95 96 97 98 99 100 101 102 103 104 105
	/**
	 * @var string the directory containing controller classes in the module.
	 */
	protected $_controllerPath;
	/**
	 * @var array child modules of this module
	 */
	protected $_modules = array();
	/**
	 * @var array application components of this module
	 */
	protected $_components = array();
w  
Qiang Xue committed
106 107 108 109

	/**
	 * Constructor.
	 * @param string $id the ID of this module
Qiang Xue committed
110
	 * @param Module $parent the parent module (if any)
w  
Qiang Xue committed
111
	 */
Qiang Xue committed
112
	public function __construct($id, $parent = null)
w  
Qiang Xue committed
113
	{
Qiang Xue committed
114 115
		$this->id = $id;
		$this->module = $parent;
w  
Qiang Xue committed
116 117 118 119 120 121 122 123 124 125 126
	}

	/**
	 * Getter magic method.
	 * This method is overridden to support accessing application components
	 * like reading module properties.
	 * @param string $name application component or property name
	 * @return mixed the named property value
	 */
	public function __get($name)
	{
w  
Qiang Xue committed
127
		if ($this->hasComponent($name)) {
w  
Qiang Xue committed
128
			return $this->getComponent($name);
Qiang Xue committed
129
		} else {
w  
Qiang Xue committed
130
			return parent::__get($name);
w  
Qiang Xue committed
131
		}
w  
Qiang Xue committed
132 133 134 135 136 137 138 139 140 141 142
	}

	/**
	 * Checks if a property value is null.
	 * This method overrides the parent implementation by checking
	 * if the named application component is loaded.
	 * @param string $name the property name or the event name
	 * @return boolean whether the property value is null
	 */
	public function __isset($name)
	{
w  
Qiang Xue committed
143
		if ($this->hasComponent($name)) {
w  
Qiang Xue committed
144
			return $this->getComponent($name) !== null;
Qiang Xue committed
145
		} else {
w  
Qiang Xue committed
146
			return parent::__isset($name);
w  
Qiang Xue committed
147 148 149 150
		}
	}

	/**
Qiang Xue committed
151 152
	 * Initializes the module.
	 * This method is called after the module is created and initialized with property values
.  
Qiang Xue committed
153 154
	 * given in configuration. The default implement will create a path alias using the module [[id]]
	 * and then call [[preloadComponents()]] to load components that are declared in [[preload]].
w  
Qiang Xue committed
155
	 */
Qiang Xue committed
156
	public function init()
w  
Qiang Xue committed
157
	{
Qiang Xue committed
158
		\Yii::setAlias('@' . $this->id, $this->getBasePath());
Qiang Xue committed
159
		$this->preloadComponents();
w  
Qiang Xue committed
160 161 162
	}

	/**
Qiang Xue committed
163 164
	 * Returns an ID that uniquely identifies this module among all modules within the current application.
	 * @return string the unique ID of the module.
w  
Qiang Xue committed
165
	 */
Qiang Xue committed
166
	public function getUniqueId()
w  
Qiang Xue committed
167
	{
Qiang Xue committed
168 169 170 171 172
		if ($this->module && !$this->module instanceof Application) {
			return $this->module->getUniqueId() . "/{$this->id}";
		} else {
			return $this->id;
		}
w  
Qiang Xue committed
173 174 175 176
	}

	/**
	 * Returns the root directory of the module.
Qiang Xue committed
177 178
	 * It defaults to the directory containing the module class file.
	 * @return string the root directory of the module.
w  
Qiang Xue committed
179 180 181
	 */
	public function getBasePath()
	{
m  
Qiang Xue committed
182
		if ($this->_basePath === null) {
Qiang Xue committed
183
			$class = new \ReflectionClass($this);
w  
Qiang Xue committed
184 185 186 187 188 189 190 191
			$this->_basePath = dirname($class->getFileName());
		}
		return $this->_basePath;
	}

	/**
	 * Sets the root directory of the module.
	 * This method can only be invoked at the beginning of the constructor.
Qiang Xue committed
192
	 * @param string $path the root directory of the module. This can be either a directory name or a path alias.
m  
Qiang Xue committed
193
	 * @throws Exception if the directory does not exist.
w  
Qiang Xue committed
194 195 196
	 */
	public function setBasePath($path)
	{
Qiang Xue committed
197
		$this->_basePath = FileHelper::ensureDirectory($path);
w  
Qiang Xue committed
198 199
	}

Qiang Xue committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
	/**
	 * Returns the directory that contains the controller classes.
	 * Defaults to "[[basePath]]/controllers".
	 * @return string the directory that contains the controller classes.
	 */
	public function getControllerPath()
	{
		if ($this->_controllerPath !== null) {
			return $this->_controllerPath;
		} else {
			return $this->_controllerPath = $this->getBasePath() . DIRECTORY_SEPARATOR . 'controllers';
		}
	}

	/**
	 * Sets the directory that contains the controller classes.
	 * @param string $path the directory that contains the controller classes.
	 * This can be either a directory name or a path alias.
	 * @throws Exception if the directory is invalid
	 */
	public function setControllerPath($path)
	{
Qiang Xue committed
222
		$this->_controllerPath = FileHelper::ensureDirectory($path);
Qiang Xue committed
223 224
	}

Qiang Xue committed
225 226 227 228 229 230 231 232 233 234 235 236 237 238
	/**
	 * @return string the root directory of view files. Defaults to 'moduleDir/views' where
	 * moduleDir is the directory containing the module class.
	 */
	public function getViewPath()
	{
		if ($this->_viewPath !== null) {
			return $this->_viewPath;
		} else {
			return $this->_viewPath = $this->getBasePath() . DIRECTORY_SEPARATOR . 'views';
		}
	}

	/**
Qiang Xue committed
239
	 * Sets the directory that contains the view files.
Qiang Xue committed
240
	 * @param string $path the root directory of view files.
Qiang Xue committed
241
	 * @throws Exception if the directory is invalid
Qiang Xue committed
242 243 244
	 */
	public function setViewPath($path)
	{
Qiang Xue committed
245
		$this->_viewPath = FileHelper::ensureDirectory($path);
Qiang Xue committed
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
	}

	/**
	 * @return string the root directory of layout files. Defaults to 'moduleDir/views/layouts' where
	 * moduleDir is the directory containing the module class.
	 */
	public function getLayoutPath()
	{
		if ($this->_layoutPath !== null) {
			return $this->_layoutPath;
		} else {
			return $this->_layoutPath = $this->getViewPath() . DIRECTORY_SEPARATOR . 'layouts';
		}
	}

	/**
Qiang Xue committed
262
	 * Sets the directory that contains the layout files.
Qiang Xue committed
263
	 * @param string $path the root directory of layout files.
Qiang Xue committed
264
	 * @throws Exception if the directory is invalid
Qiang Xue committed
265 266 267
	 */
	public function setLayoutPath($path)
	{
Qiang Xue committed
268
		$this->_layoutPath = FileHelper::ensureDirectory($path);
Qiang Xue committed
269 270
	}

w  
Qiang Xue committed
271
	/**
m  
Qiang Xue committed
272
	 * Imports the specified path aliases.
Qiang Xue committed
273 274
	 * This method is provided so that you can import a set of path aliases when configuring a module.
	 * The path aliases will be imported by calling [[\Yii::import()]].
m  
Qiang Xue committed
275
	 * @param array $aliases list of path aliases to be imported
w  
Qiang Xue committed
276 277 278
	 */
	public function setImport($aliases)
	{
m  
Qiang Xue committed
279 280 281
		foreach ($aliases as $alias) {
			\Yii::import($alias);
		}
w  
Qiang Xue committed
282 283 284
	}

	/**
w  
Qiang Xue committed
285
	 * Defines path aliases.
Qiang Xue committed
286 287
	 * This method calls [[\Yii::setAlias()]] to register the path aliases.
	 * This method is provided so that you can define path aliases when configuring a module.
w  
Qiang Xue committed
288
	 * @param array $aliases list of path aliases to be defined. The array keys are alias names
Qiang Xue committed
289
	 * (must start with '@') and the array values are the corresponding paths or aliases.
w  
Qiang Xue committed
290
	 * For example,
w  
Qiang Xue committed
291 292
	 *
	 * ~~~
w  
Qiang Xue committed
293
	 * array(
Qiang Xue committed
294
	 *	'@models' => '@app/models', // an existing alias
Qiang Xue committed
295
	 *	'@backend' => __DIR__ . '/../backend',  // a directory
w  
Qiang Xue committed
296
	 * )
w  
Qiang Xue committed
297
	 * ~~~
w  
Qiang Xue committed
298
	 */
w  
Qiang Xue committed
299
	public function setAliases($aliases)
w  
Qiang Xue committed
300
	{
w  
Qiang Xue committed
301 302
		foreach ($aliases as $name => $alias) {
			\Yii::setAlias($name, $alias);
w  
Qiang Xue committed
303 304 305 306
		}
	}

	/**
Qiang Xue committed
307 308 309 310
	 * Checks whether the named module exists.
	 * @param string $id module ID
	 * @return boolean whether the named module exists. Both loaded and unloaded modules
	 * are considered.
w  
Qiang Xue committed
311
	 */
Qiang Xue committed
312
	public function hasModule($id)
w  
Qiang Xue committed
313
	{
Qiang Xue committed
314 315 316 317 318 319
		return isset($this->_modules[$id]);
	}

	/**
	 * Retrieves the named module.
	 * @param string $id module ID (case-sensitive)
320
	 * @param boolean $load whether to load the module if it is not yet loaded.
Qiang Xue committed
321 322 323 324
	 * @return Module|null the module instance, null if the module
	 * does not exist.
	 * @see hasModule()
	 */
325
	public function getModule($id, $load = true)
Qiang Xue committed
326 327 328 329
	{
		if (isset($this->_modules[$id])) {
			if ($this->_modules[$id] instanceof Module) {
				return $this->_modules[$id];
330
			} elseif ($load) {
Qiang Xue committed
331 332
				\Yii::trace("Loading \"$id\" module", __CLASS__);
				return $this->_modules[$id] = \Yii::createObject($this->_modules[$id], $id, $this);
w  
Qiang Xue committed
333 334
			}
		}
Qiang Xue committed
335
		return null;
w  
Qiang Xue committed
336 337 338
	}

	/**
Qiang Xue committed
339 340 341 342 343 344 345 346 347
	 * Adds a sub-module to this module.
	 * @param string $id module ID
	 * @param Module|array|null $module the sub-module to be added to this module. This can
	 * be one of the followings:
	 *
	 * - a [[Module]] object
	 * - a configuration array: when [[getModule()]] is called initially, the array
	 *   will be used to instantiate the sub-module
	 * - null: the named sub-module will be removed from this module
w  
Qiang Xue committed
348
	 */
Qiang Xue committed
349
	public function setModule($id, $module)
w  
Qiang Xue committed
350
	{
Qiang Xue committed
351 352 353 354 355
		if ($module === null) {
			unset($this->_modules[$id]);
		} else {
			$this->_modules[$id] = $module;
		}
w  
Qiang Xue committed
356 357 358
	}

	/**
Qiang Xue committed
359 360 361 362 363
	 * Returns the sub-modules in this module.
	 * @param boolean $loadedOnly whether to return the loaded sub-modules only. If this is set false,
	 * then all sub-modules registered in this module will be returned, whether they are loaded or not.
	 * Loaded modules will be returned as objects, while unloaded modules as configuration arrays.
	 * @return array the modules (indexed by their IDs)
w  
Qiang Xue committed
364
	 */
Qiang Xue committed
365
	public function getModules($loadedOnly = false)
w  
Qiang Xue committed
366
	{
Qiang Xue committed
367 368 369 370 371 372 373 374 375 376 377
		if ($loadedOnly) {
			$modules = array();
			foreach ($this->_modules as $module) {
				if ($module instanceof Module) {
					$modules[] = $module;
				}
			}
			return $modules;
		} else {
			return $this->_modules;
		}
w  
Qiang Xue committed
378 379 380
	}

	/**
Qiang Xue committed
381
	 * Registers sub-modules in the current module.
w  
Qiang Xue committed
382
	 *
Qiang Xue committed
383 384 385 386
	 * Each sub-module should be specified as a name-value pair, where
	 * name refers to the ID of the module and value the module or a configuration
	 * array that can be used to create the module. In the latter case, [[\Yii::createObject()]]
	 * will be used to create the module.
w  
Qiang Xue committed
387
	 *
Qiang Xue committed
388
	 * If a new sub-module has the same ID as an existing one, the existing one will be overwritten silently.
w  
Qiang Xue committed
389
	 *
Qiang Xue committed
390
	 * The following is an example for registering two sub-modules:
w  
Qiang Xue committed
391
	 *
Qiang Xue committed
392 393 394 395 396 397 398 399 400 401 402
	 * ~~~
	 * array(
	 *     'comment' => array(
	 *         'class' => 'app\modules\CommentModule',
	 *         'connectionID' => 'db',
	 *     ),
	 *     'booking' => array(
	 *         'class' => 'app\modules\BookingModule',
	 *     ),
	 * )
	 * ~~~
w  
Qiang Xue committed
403
	 *
Qiang Xue committed
404
	 * @param array $modules modules (id => module configuration or instances)
w  
Qiang Xue committed
405 406 407
	 */
	public function setModules($modules)
	{
Qiang Xue committed
408 409
		foreach ($modules as $id => $module) {
			$this->_modules[$id] = $module;
w  
Qiang Xue committed
410 411
		}
	}
412

w  
Qiang Xue committed
413 414 415
	/**
	 * Checks whether the named component exists.
	 * @param string $id application component ID
Qiang Xue committed
416 417
	 * @return boolean whether the named application component exists. Both loaded and unloaded components
	 * are considered.
w  
Qiang Xue committed
418 419 420
	 */
	public function hasComponent($id)
	{
Qiang Xue committed
421
		return isset($this->_components[$id]);
w  
Qiang Xue committed
422 423 424 425 426
	}

	/**
	 * Retrieves the named application component.
	 * @param string $id application component ID (case-sensitive)
427
	 * @param boolean $load whether to load the component if it is not yet loaded.
Qiang Xue committed
428 429 430
	 * @return ApplicationComponent|null the application component instance, null if the application component
	 * does not exist.
	 * @see hasComponent()
w  
Qiang Xue committed
431
	 */
432
	public function getComponent($id, $load = true)
w  
Qiang Xue committed
433
	{
Qiang Xue committed
434
		if (isset($this->_components[$id])) {
Qiang Xue committed
435 436
			if ($this->_components[$id] instanceof ApplicationComponent) {
				return $this->_components[$id];
437
			} elseif ($load) {
Qiang Xue committed
438 439
				\Yii::trace("Loading \"$id\" application component", __CLASS__);
				return $this->_components[$id] = \Yii::createObject($this->_components[$id]);
w  
Qiang Xue committed
440 441
			}
		}
Qiang Xue committed
442
		return null;
w  
Qiang Xue committed
443 444 445
	}

	/**
Qiang Xue committed
446
	 * Registers an application component in this module.
w  
Qiang Xue committed
447
	 * @param string $id component ID
Qiang Xue committed
448 449 450 451 452 453 454
	 * @param ApplicationComponent|array|null $component the component to be added to the module. This can
	 * be one of the followings:
	 *
	 * - an [[ApplicationComponent]] object
	 * - a configuration array: when [[getComponent()]] is called initially for this component, the array
	 *   will be used to instantiate the component
	 * - null: the named component will be removed from the module
w  
Qiang Xue committed
455 456 457
	 */
	public function setComponent($id, $component)
	{
Qiang Xue committed
458
		if ($component === null) {
w  
Qiang Xue committed
459
			unset($this->_components[$id]);
Qiang Xue committed
460
		} else {
w  
Qiang Xue committed
461 462 463 464 465 466 467 468 469 470 471
			$this->_components[$id] = $component;
		}
	}

	/**
	 * Returns the application components.
	 * @param boolean $loadedOnly whether to return the loaded components only. If this is set false,
	 * then all components specified in the configuration will be returned, whether they are loaded or not.
	 * Loaded components will be returned as objects, while unloaded components as configuration arrays.
	 * @return array the application components (indexed by their IDs)
	 */
Qiang Xue committed
472
	public function getComponents($loadedOnly = false)
w  
Qiang Xue committed
473
	{
Qiang Xue committed
474
		if ($loadedOnly) {
Qiang Xue committed
475 476 477 478 479 480 481
			$components = array();
			foreach ($this->_components as $component) {
				if ($component instanceof ApplicationComponent) {
					$components[] = $component;
				}
			}
			return $components;
Qiang Xue committed
482
		} else {
Qiang Xue committed
483
			return $this->_components;
Qiang Xue committed
484
		}
w  
Qiang Xue committed
485 486 487
	}

	/**
Qiang Xue committed
488
	 * Registers a set of application components in this module.
w  
Qiang Xue committed
489
	 *
Qiang Xue committed
490 491 492 493
	 * Each application component should be specified as a name-value pair, where
	 * name refers to the ID of the component and value the component or a configuration
	 * array that can be used to create the component. In the latter case, [[\Yii::createObject()]]
	 * will be used to create the component.
w  
Qiang Xue committed
494
	 *
Qiang Xue committed
495
	 * If a new component has the same ID as an existing one, the existing one will be overwritten silently.
w  
Qiang Xue committed
496
	 *
Qiang Xue committed
497 498 499
	 * The following is an example for setting two components:
	 *
	 * ~~~
w  
Qiang Xue committed
500
	 * array(
Qiang Xue committed
501 502 503 504 505 506 507 508
	 *     'db' => array(
	 *         'class' => 'yii\db\dao\Connection',
	 *         'dsn' => 'sqlite:path/to/file.db',
	 *     ),
	 *     'cache' => array(
	 *         'class' => 'yii\caching\DbCache',
	 *         'connectionID' => 'db',
	 *     ),
w  
Qiang Xue committed
509
	 * )
Qiang Xue committed
510
	 * ~~~
w  
Qiang Xue committed
511
	 *
Qiang Xue committed
512
	 * @param array $components application components (id => component configuration or instance)
w  
Qiang Xue committed
513
	 */
Qiang Xue committed
514
	public function setComponents($components)
w  
Qiang Xue committed
515
	{
Qiang Xue committed
516 517
		foreach ($components as $id => $component) {
			$this->_components[$id] = $component;
w  
Qiang Xue committed
518 519 520 521
		}
	}

	/**
Qiang Xue committed
522
	 * Loads application components that are declared in [[preload]].
w  
Qiang Xue committed
523
	 */
w  
Qiang Xue committed
524
	public function preloadComponents()
w  
Qiang Xue committed
525
	{
Qiang Xue committed
526
		foreach ($this->preload as $id) {
w  
Qiang Xue committed
527
			$this->getComponent($id);
Qiang Xue committed
528
		}
w  
Qiang Xue committed
529
	}
Qiang Xue committed
530 531

	/**
Qiang Xue committed
532 533
	 * Creates a controller instance based on the given route.
	 * This method tries to parse the given route (e.g. `post/create`) using the following algorithm:
Qiang Xue committed
534 535 536 537 538
	 *
	 * 1. Get the first segment in route
	 * 2. If the segment matches
	 *    - an ID in [[controllers]], create a controller instance using the corresponding configuration,
	 *      and return the controller with the rest part of the route;
Qiang Xue committed
539
	 *    - an ID in [[modules]], call the [[createController()]] method of the corresponding module.
Qiang Xue committed
540 541 542 543
	 *    - a controller class under [[controllerPath]], create the controller instance, and return it
	 *      with the rest part of the route;
	 *
	 * @param string $route the route which may consist module ID, controller ID and/or action ID (e.g. `post/create`)
Qiang Xue committed
544
	 * @return array|boolean the array of controller instance and action ID. False if the route cannot be resolved.
Qiang Xue committed
545
	 */
Qiang Xue committed
546
	public function createController($route)
Qiang Xue committed
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
	{
		if (($route = trim($route, '/')) === '') {
			$route = $this->defaultRoute;
		}

		if (($pos = strpos($route, '/')) !== false) {
			$id = substr($route, 0, $pos);
			$route = (string)substr($route, $pos + 1);
		} else {
			$id = $route;
			$route = '';
		}

		// Controller IDs must start with a lower-case letter and consist of word characters only
		if (!preg_match('/^[a-z][a-zA-Z0-9_]*$/', $id)) {
Qiang Xue committed
562
			return false;
Qiang Xue committed
563 564 565
		}

		if (isset($this->controllers[$id])) {
Qiang Xue committed
566 567 568 569
			return array(
				\Yii::createObject($this->controllers[$id], $id, $this),
				$route,
			);
Qiang Xue committed
570 571
		}

Qiang Xue committed
572 573 574 575 576 577 578
		if (($module = $this->getModule($id)) !== null) {
			$result = $module->createController($route);
			if ($result !== false) {
				return $result;
			}
		}

Qiang Xue committed
579 580 581 582 583 584 585
		$className = ucfirst($id) . 'Controller';
		$classFile = $this->getControllerPath() . DIRECTORY_SEPARATOR . $className . '.php';
		if (is_file($classFile)) {
			if (!class_exists($className, false)) {
				require($classFile);
			}
			if (class_exists($className, false) && is_subclass_of($className, '\yii\base\Controller')) {
Qiang Xue committed
586
				return array(
Qiang Xue committed
587
					new $className($id, $this),
Qiang Xue committed
588 589
					$route,
				);
Qiang Xue committed
590 591 592
			}
		}

Qiang Xue committed
593
		return false;
Qiang Xue committed
594
	}
w  
Qiang Xue committed
595
}