* @link http://www.yiiframework.com/ * @copyright 2008-2013 Yii Software LLC * @license http://www.yiiframework.com/license/ */ /** * CModule is the base class for module and application classes. * * CModule mainly manages application components and sub-modules. * * @property string $id The module ID. * @property string $basePath The root directory of the module. Defaults to the directory containing the module class. * @property CAttributeCollection $params The list of user-defined parameters. * @property string $modulePath The directory that contains the application modules. Defaults to the 'modules' subdirectory of {@link basePath}. * @property CModule $parentModule The parent module. Null if this module does not have a parent. * @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. * @property array $aliases List of aliases to be defined. The array keys are root aliases, * while the array values are paths or aliases corresponding to the root aliases. * For example, *
* array( * 'models'=>'application.models', // an existing alias * 'extensions'=>'application.extensions', // an existing alias * 'backend'=>dirname(__FILE__).'/../backend', // a directory * ) *. * * @author Qiang Xue
* array( * 'models'=>'application.models', // an existing alias * 'extensions'=>'application.extensions', // an existing alias * 'backend'=>dirname(__FILE__).'/../backend', // a directory * ) **/ public function setAliases($mappings) { foreach($mappings as $name=>$alias) { if(($path=Yii::getPathOfAlias($alias))!==false) Yii::setPathOfAlias($name,$path); else Yii::setPathOfAlias($name,$alias); } } /** * Returns the parent module. * @return CModule the parent module. Null if this module does not have a parent. */ public function getParentModule() { return $this->_parentModule; } /** * Retrieves the named application module. * The module has to be declared in {@link modules}. A new instance will be created * when calling this method with the given ID for the first time. * @param string $id application module ID (case-sensitive) * @return CModule the module instance, null if the module is disabled or does not exist. */ public function getModule($id) { if(isset($this->_modules[$id]) || array_key_exists($id,$this->_modules)) return $this->_modules[$id]; elseif(isset($this->_moduleConfig[$id])) { $config=$this->_moduleConfig[$id]; if(!isset($config['enabled']) || $config['enabled']) { Yii::trace("Loading \"$id\" module",'system.base.CModule'); $class=$config['class']; unset($config['class'], $config['enabled']); if($this===Yii::app()) $module=Yii::createComponent($class,$id,null,$config); else $module=Yii::createComponent($class,$this->getId().'/'.$id,$this,$config); return $this->_modules[$id]=$module; } } } /** * Returns a value indicating whether the specified module is installed. * @param string $id the module ID * @return boolean whether the specified module is installed. * @since 1.1.2 */ public function hasModule($id) { return isset($this->_moduleConfig[$id]) || isset($this->_modules[$id]); } /** * Returns the configuration of the currently installed modules. * @return array the configuration of the currently installed modules (module ID => configuration) */ public function getModules() { return $this->_moduleConfig; } /** * Configures the sub-modules of this module. * * Call this method to declare sub-modules and configure them with their initial property values. * The parameter should be an array of module configurations. Each array element represents a single module, * which can be either a string representing the module ID or an ID-configuration pair representing * a module with the specified ID and the initial property values. * * For example, the following array declares two modules: *
* array( * 'admin', // a single module ID * 'payment'=>array( // ID-configuration pair * 'server'=>'paymentserver.com', * ), * ) ** * By default, the module class is determined using the expression
ucfirst($moduleID).'Module'
.
* And the class file is located under modules/$moduleID
.
* You may override this default by explicitly specifying the 'class' option in the configuration.
*
* You may also enable or disable a module by specifying the 'enabled' option in the configuration.
*
* @param array $modules module configurations.
*/
public function setModules($modules)
{
foreach($modules as $id=>$module)
{
if(is_int($id))
{
$id=$module;
$module=array();
}
if(!isset($module['class']))
{
Yii::setPathOfAlias($id,$this->getModulePath().DIRECTORY_SEPARATOR.$id);
$module['class']=$id.'.'.ucfirst($id).'Module';
}
if(isset($this->_moduleConfig[$id]))
$this->_moduleConfig[$id]=CMap::mergeArray($this->_moduleConfig[$id],$module);
else
$this->_moduleConfig[$id]=$module;
}
}
/**
* Checks whether the named component exists.
* @param string $id application component ID
* @return boolean whether the named application component exists (including both loaded and disabled.)
*/
public function hasComponent($id)
{
return isset($this->_components[$id]) || isset($this->_componentConfig[$id]);
}
/**
* Retrieves the named application component.
* @param string $id application component ID (case-sensitive)
* @param boolean $createIfNull whether to create the component if it doesn't exist yet.
* @return IApplicationComponent the application component instance, null if the application component is disabled or does not exist.
* @see hasComponent
*/
public function getComponent($id,$createIfNull=true)
{
if(isset($this->_components[$id]))
return $this->_components[$id];
elseif(isset($this->_componentConfig[$id]) && $createIfNull)
{
$config=$this->_componentConfig[$id];
if(!isset($config['enabled']) || $config['enabled'])
{
Yii::trace("Loading \"$id\" application component",'system.CModule');
unset($config['enabled']);
$component=Yii::createComponent($config);
$component->init();
return $this->_components[$id]=$component;
}
}
}
/**
* Puts a component under the management of the module.
* The component will be initialized by calling its {@link CApplicationComponent::init() init()}
* method if it has not done so.
* @param string $id component ID
* @param array|IApplicationComponent $component application component
* (either configuration array or instance). If this parameter is null,
* component will be unloaded from the module.
* @param boolean $merge whether to merge the new component configuration
* with the existing one. Defaults to true, meaning the previously registered
* component configuration with the same ID will be merged with the new configuration.
* If set to false, the existing configuration will be replaced completely.
* This parameter is available since 1.1.13.
*/
public function setComponent($id,$component,$merge=true)
{
if($component===null)
{
unset($this->_components[$id]);
return;
}
elseif($component instanceof IApplicationComponent)
{
$this->_components[$id]=$component;
if(!$component->getIsInitialized())
$component->init();
return;
}
elseif(isset($this->_components[$id]))
{
if(isset($component['class']) && get_class($this->_components[$id])!==$component['class'])
{
unset($this->_components[$id]);
$this->_componentConfig[$id]=$component; //we should ignore merge here
return;
}
foreach($component as $key=>$value)
{
if($key!=='class')
$this->_components[$id]->$key=$value;
}
}
elseif(isset($this->_componentConfig[$id]['class'],$component['class'])
&& $this->_componentConfig[$id]['class']!==$component['class'])
{
$this->_componentConfig[$id]=$component; //we should ignore merge here
return;
}
if(isset($this->_componentConfig[$id]) && $merge)
$this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);
else
$this->_componentConfig[$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.
* This parameter has been available since version 1.1.3.
* @return array the application components (indexed by their IDs)
*/
public function getComponents($loadedOnly=true)
{
if($loadedOnly)
return $this->_components;
else
return array_merge($this->_componentConfig, $this->_components);
}
/**
* Sets the application components.
*
* When a configuration is used to specify a component, it should consist of
* the component's initial property values (name-value pairs). Additionally,
* a component can be enabled (default) or disabled by specifying the 'enabled' value
* in the configuration.
*
* If a configuration is specified with an ID that is the same as an existing
* component or configuration, the existing one will be replaced silently.
*
* The following is the configuration for two components:
* * array( * 'db'=>array( * 'class'=>'CDbConnection', * 'connectionString'=>'sqlite:path/to/file.db', * ), * 'cache'=>array( * 'class'=>'CDbCache', * 'connectionID'=>'db', * 'enabled'=>!YII_DEBUG, // enable caching in non-debug mode * ), * ) ** * @param array $components application components(id=>component configuration or instances) * @param boolean $merge whether to merge the new component configuration with the existing one. * Defaults to true, meaning the previously registered component configuration of the same ID * will be merged with the new configuration. If false, the existing configuration will be replaced completely. */ public function setComponents($components,$merge=true) { foreach($components as $id=>$component) $this->setComponent($id,$component,$merge); } /** * Configures the module with the specified configuration. * @param array $config the configuration array */ public function configure($config) { if(is_array($config)) { foreach($config as $key=>$value) $this->$key=$value; } } /** * Loads static application components. */ protected function preloadComponents() { foreach($this->preload as $id) $this->getComponent($id); } /** * Preinitializes the module. * This method is called at the beginning of the module constructor. * You may override this method to do some customized preinitialization work. * Note that at this moment, the module is not configured yet. * @see init */ protected function preinit() { } /** * Initializes the module. * This method is called at the end of the module constructor. * Note that at this moment, the module has been configured, the behaviors * have been attached and the application components have been registered. * @see preinit */ protected function init() { } }