PageRenderTime 109ms CodeModel.GetById 19ms RepoModel.GetById 2ms app.codeStats 0ms

/yii/framework/base/CModule.php

https://github.com/joshuaswarren/weatherhub
PHP | 501 lines | 237 code | 35 blank | 229 comment | 38 complexity | b941af33228567daad627baf6b604304 MD5 | raw file
  1. <?php
  2. /**
  3. * CModule class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright Copyright &copy; 2008-2011 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CModule is the base class for module and application classes.
  12. *
  13. * CModule mainly manages application components and sub-modules.
  14. *
  15. * @author Qiang Xue <qiang.xue@gmail.com>
  16. * @version $Id: CModule.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  17. * @package system.base
  18. * @since 1.0.4
  19. */
  20. abstract class CModule extends CComponent
  21. {
  22. /**
  23. * @var array the IDs of the application components that should be preloaded.
  24. */
  25. public $preload=array();
  26. /**
  27. * @var array the behaviors that should be attached to the module.
  28. * The behaviors will be attached to the module when {@link init} is called.
  29. * Please refer to {@link CModel::behaviors} on how to specify the value of this property.
  30. */
  31. public $behaviors=array();
  32. private $_id;
  33. private $_parentModule;
  34. private $_basePath;
  35. private $_modulePath;
  36. private $_params;
  37. private $_modules=array();
  38. private $_moduleConfig=array();
  39. private $_components=array();
  40. private $_componentConfig=array();
  41. /**
  42. * Constructor.
  43. * @param string $id the ID of this module
  44. * @param CModule $parent the parent module (if any)
  45. * @param mixed $config the module configuration. It can be either an array or
  46. * the path of a PHP file returning the configuration array.
  47. */
  48. public function __construct($id,$parent,$config=null)
  49. {
  50. $this->_id=$id;
  51. $this->_parentModule=$parent;
  52. // set basePath at early as possible to avoid trouble
  53. if(is_string($config))
  54. $config=require($config);
  55. if(isset($config['basePath']))
  56. {
  57. $this->setBasePath($config['basePath']);
  58. unset($config['basePath']);
  59. }
  60. Yii::setPathOfAlias($id,$this->getBasePath());
  61. $this->preinit();
  62. $this->configure($config);
  63. $this->attachBehaviors($this->behaviors);
  64. $this->preloadComponents();
  65. $this->init();
  66. }
  67. /**
  68. * Getter magic method.
  69. * This method is overridden to support accessing application components
  70. * like reading module properties.
  71. * @param string $name application component or property name
  72. * @return mixed the named property value
  73. */
  74. public function __get($name)
  75. {
  76. if($this->hasComponent($name))
  77. return $this->getComponent($name);
  78. else
  79. return parent::__get($name);
  80. }
  81. /**
  82. * Checks if a property value is null.
  83. * This method overrides the parent implementation by checking
  84. * if the named application component is loaded.
  85. * @param string $name the property name or the event name
  86. * @return boolean whether the property value is null
  87. */
  88. public function __isset($name)
  89. {
  90. if($this->hasComponent($name))
  91. return $this->getComponent($name)!==null;
  92. else
  93. return parent::__isset($name);
  94. }
  95. /**
  96. * Returns the module ID.
  97. * @return string the module ID.
  98. */
  99. public function getId()
  100. {
  101. return $this->_id;
  102. }
  103. /**
  104. * Sets the module ID.
  105. * @param string $id the module ID
  106. */
  107. public function setId($id)
  108. {
  109. $this->_id=$id;
  110. }
  111. /**
  112. * Returns the root directory of the module.
  113. * @return string the root directory of the module. Defaults to the directory containing the module class.
  114. */
  115. public function getBasePath()
  116. {
  117. if($this->_basePath===null)
  118. {
  119. $class=new ReflectionClass(get_class($this));
  120. $this->_basePath=dirname($class->getFileName());
  121. }
  122. return $this->_basePath;
  123. }
  124. /**
  125. * Sets the root directory of the module.
  126. * This method can only be invoked at the beginning of the constructor.
  127. * @param string $path the root directory of the module.
  128. * @throws CException if the directory does not exist.
  129. */
  130. public function setBasePath($path)
  131. {
  132. if(($this->_basePath=realpath($path))===false || !is_dir($this->_basePath))
  133. throw new CException(Yii::t('yii','Base path "{path}" is not a valid directory.',
  134. array('{path}'=>$path)));
  135. }
  136. /**
  137. * Returns user-defined parameters.
  138. * @return CAttributeCollection the list of user-defined parameters
  139. */
  140. public function getParams()
  141. {
  142. if($this->_params!==null)
  143. return $this->_params;
  144. else
  145. {
  146. $this->_params=new CAttributeCollection;
  147. $this->_params->caseSensitive=true;
  148. return $this->_params;
  149. }
  150. }
  151. /**
  152. * Sets user-defined parameters.
  153. * @param array $value user-defined parameters. This should be in name-value pairs.
  154. */
  155. public function setParams($value)
  156. {
  157. $params=$this->getParams();
  158. foreach($value as $k=>$v)
  159. $params->add($k,$v);
  160. }
  161. /**
  162. * Returns the directory that contains the application modules.
  163. * @return string the directory that contains the application modules. Defaults to the 'modules' subdirectory of {@link basePath}.
  164. */
  165. public function getModulePath()
  166. {
  167. if($this->_modulePath!==null)
  168. return $this->_modulePath;
  169. else
  170. return $this->_modulePath=$this->getBasePath().DIRECTORY_SEPARATOR.'modules';
  171. }
  172. /**
  173. * Sets the directory that contains the application modules.
  174. * @param string $value the directory that contains the application modules.
  175. * @throws CException if the directory is invalid
  176. */
  177. public function setModulePath($value)
  178. {
  179. if(($this->_modulePath=realpath($value))===false || !is_dir($this->_modulePath))
  180. throw new CException(Yii::t('yii','The module path "{path}" is not a valid directory.',
  181. array('{path}'=>$value)));
  182. }
  183. /**
  184. * Sets the aliases that are used in the module.
  185. * @param array $aliases list of aliases to be imported
  186. */
  187. public function setImport($aliases)
  188. {
  189. foreach($aliases as $alias)
  190. Yii::import($alias);
  191. }
  192. /**
  193. * Defines the root aliases.
  194. * @param array $mappings list of aliases to be defined. The array keys are root aliases,
  195. * while the array values are paths or aliases corresponding to the root aliases.
  196. * For example,
  197. * <pre>
  198. * array(
  199. * 'models'=>'application.models', // an existing alias
  200. * 'extensions'=>'application.extensions', // an existing alias
  201. * 'backend'=>dirname(__FILE__).'/../backend', // a directory
  202. * )
  203. * </pre>
  204. * @since 1.0.5
  205. */
  206. public function setAliases($mappings)
  207. {
  208. foreach($mappings as $name=>$alias)
  209. {
  210. if(($path=Yii::getPathOfAlias($alias))!==false)
  211. Yii::setPathOfAlias($name,$path);
  212. else
  213. Yii::setPathOfAlias($name,$alias);
  214. }
  215. }
  216. /**
  217. * Returns the parent module.
  218. * @return CModule the parent module. Null if this module does not have a parent.
  219. */
  220. public function getParentModule()
  221. {
  222. return $this->_parentModule;
  223. }
  224. /**
  225. * Retrieves the named application module.
  226. * The module has to be declared in {@link modules}. A new instance will be created
  227. * when calling this method with the given ID for the first time.
  228. * @param string $id application module ID (case-sensitive)
  229. * @return CModule the module instance, null if the module is disabled or does not exist.
  230. */
  231. public function getModule($id)
  232. {
  233. if(isset($this->_modules[$id]) || array_key_exists($id,$this->_modules))
  234. return $this->_modules[$id];
  235. else if(isset($this->_moduleConfig[$id]))
  236. {
  237. $config=$this->_moduleConfig[$id];
  238. if(!isset($config['enabled']) || $config['enabled'])
  239. {
  240. Yii::trace("Loading \"$id\" module",'system.base.CModule');
  241. $class=$config['class'];
  242. unset($config['class'], $config['enabled']);
  243. if($this===Yii::app())
  244. $module=Yii::createComponent($class,$id,null,$config);
  245. else
  246. $module=Yii::createComponent($class,$this->getId().'/'.$id,$this,$config);
  247. return $this->_modules[$id]=$module;
  248. }
  249. }
  250. }
  251. /**
  252. * Returns a value indicating whether the specified module is installed.
  253. * @param string $id the module ID
  254. * @return boolean whether the specified module is installed.
  255. * @since 1.1.2
  256. */
  257. public function hasModule($id)
  258. {
  259. return isset($this->_moduleConfig[$id]) || isset($this->_modules[$id]);
  260. }
  261. /**
  262. * Returns the configuration of the currently installed modules.
  263. * @return array the configuration of the currently installed modules (module ID => configuration)
  264. */
  265. public function getModules()
  266. {
  267. return $this->_moduleConfig;
  268. }
  269. /**
  270. * Configures the sub-modules of this module.
  271. *
  272. * Call this method to declare sub-modules and configure them with their initial property values.
  273. * The parameter should be an array of module configurations. Each array element represents a single module,
  274. * which can be either a string representing the module ID or an ID-configuration pair representing
  275. * a module with the specified ID and the initial property values.
  276. *
  277. * For example, the following array declares two modules:
  278. * <pre>
  279. * array(
  280. * 'admin', // a single module ID
  281. * 'payment'=>array( // ID-configuration pair
  282. * 'server'=>'paymentserver.com',
  283. * ),
  284. * )
  285. * </pre>
  286. *
  287. * By default, the module class is determined using the expression <code>ucfirst($moduleID).'Module'</code>.
  288. * And the class file is located under <code>modules/$moduleID</code>.
  289. * You may override this default by explicitly specifying the 'class' option in the configuration.
  290. *
  291. * You may also enable or disable a module by specifying the 'enabled' option in the configuration.
  292. *
  293. * @param array $modules module configurations.
  294. */
  295. public function setModules($modules)
  296. {
  297. foreach($modules as $id=>$module)
  298. {
  299. if(is_int($id))
  300. {
  301. $id=$module;
  302. $module=array();
  303. }
  304. if(!isset($module['class']))
  305. {
  306. Yii::setPathOfAlias($id,$this->getModulePath().DIRECTORY_SEPARATOR.$id);
  307. $module['class']=$id.'.'.ucfirst($id).'Module';
  308. }
  309. if(isset($this->_moduleConfig[$id]))
  310. $this->_moduleConfig[$id]=CMap::mergeArray($this->_moduleConfig[$id],$module);
  311. else
  312. $this->_moduleConfig[$id]=$module;
  313. }
  314. }
  315. /**
  316. * Checks whether the named component exists.
  317. * @param string $id application component ID
  318. * @return boolean whether the named application component exists (including both loaded and disabled.)
  319. */
  320. public function hasComponent($id)
  321. {
  322. return isset($this->_components[$id]) || isset($this->_componentConfig[$id]);
  323. }
  324. /**
  325. * Retrieves the named application component.
  326. * @param string $id application component ID (case-sensitive)
  327. * @param boolean $createIfNull whether to create the component if it doesn't exist yet. This parameter
  328. * has been available since version 1.0.6.
  329. * @return IApplicationComponent the application component instance, null if the application component is disabled or does not exist.
  330. * @see hasComponent
  331. */
  332. public function getComponent($id,$createIfNull=true)
  333. {
  334. if(isset($this->_components[$id]))
  335. return $this->_components[$id];
  336. else if(isset($this->_componentConfig[$id]) && $createIfNull)
  337. {
  338. $config=$this->_componentConfig[$id];
  339. if(!isset($config['enabled']) || $config['enabled'])
  340. {
  341. Yii::trace("Loading \"$id\" application component",'system.CModule');
  342. unset($config['enabled']);
  343. $component=Yii::createComponent($config);
  344. $component->init();
  345. return $this->_components[$id]=$component;
  346. }
  347. }
  348. }
  349. /**
  350. * Puts a component under the management of the module.
  351. * The component will be initialized by calling its {@link CApplicationComponent::init() init()}
  352. * method if it has not done so.
  353. * @param string $id component ID
  354. * @param IApplicationComponent $component the component to be added to the module.
  355. * If this parameter is null, it will unload the component from the module.
  356. */
  357. public function setComponent($id,$component)
  358. {
  359. if($component===null)
  360. unset($this->_components[$id]);
  361. else
  362. {
  363. $this->_components[$id]=$component;
  364. if(!$component->getIsInitialized())
  365. $component->init();
  366. }
  367. }
  368. /**
  369. * Returns the application components.
  370. * @param boolean $loadedOnly whether to return the loaded components only. If this is set false,
  371. * then all components specified in the configuration will be returned, whether they are loaded or not.
  372. * Loaded components will be returned as objects, while unloaded components as configuration arrays.
  373. * This parameter has been available since version 1.1.3.
  374. * @return array the application components (indexed by their IDs)
  375. */
  376. public function getComponents($loadedOnly=true)
  377. {
  378. if($loadedOnly)
  379. return $this->_components;
  380. else
  381. return array_merge($this->_componentConfig, $this->_components);
  382. }
  383. /**
  384. * Sets the application components.
  385. *
  386. * When a configuration is used to specify a component, it should consist of
  387. * the component's initial property values (name-value pairs). Additionally,
  388. * a component can be enabled (default) or disabled by specifying the 'enabled' value
  389. * in the configuration.
  390. *
  391. * If a configuration is specified with an ID that is the same as an existing
  392. * component or configuration, the existing one will be replaced silently.
  393. *
  394. * The following is the configuration for two components:
  395. * <pre>
  396. * array(
  397. * 'db'=>array(
  398. * 'class'=>'CDbConnection',
  399. * 'connectionString'=>'sqlite:path/to/file.db',
  400. * ),
  401. * 'cache'=>array(
  402. * 'class'=>'CDbCache',
  403. * 'connectionID'=>'db',
  404. * 'enabled'=>!YII_DEBUG, // enable caching in non-debug mode
  405. * ),
  406. * )
  407. * </pre>
  408. *
  409. * @param array $components application components(id=>component configuration or instances)
  410. * @param boolean $merge whether to merge the new component configuration with the existing one.
  411. * Defaults to true, meaning the previously registered component configuration of the same ID
  412. * will be merged with the new configuration. If false, the existing configuration will be replaced completely.
  413. */
  414. public function setComponents($components,$merge=true)
  415. {
  416. foreach($components as $id=>$component)
  417. {
  418. if($component instanceof IApplicationComponent)
  419. $this->setComponent($id,$component);
  420. else if(isset($this->_componentConfig[$id]) && $merge)
  421. $this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);
  422. else
  423. $this->_componentConfig[$id]=$component;
  424. }
  425. }
  426. /**
  427. * Configures the module with the specified configuration.
  428. * @param array $config the configuration array
  429. */
  430. public function configure($config)
  431. {
  432. if(is_array($config))
  433. {
  434. foreach($config as $key=>$value)
  435. $this->$key=$value;
  436. }
  437. }
  438. /**
  439. * Loads static application components.
  440. */
  441. protected function preloadComponents()
  442. {
  443. foreach($this->preload as $id)
  444. $this->getComponent($id);
  445. }
  446. /**
  447. * Preinitializes the module.
  448. * This method is called at the beginning of the module constructor.
  449. * You may override this method to do some customized preinitialization work.
  450. * Note that at this moment, the module is not configured yet.
  451. * @see init
  452. */
  453. protected function preinit()
  454. {
  455. }
  456. /**
  457. * Initializes the module.
  458. * This method is called at the end of the module constructor.
  459. * Note that at this moment, the module has been configured, the behaviors
  460. * have been attached and the application components have been registered.
  461. * @see preinit
  462. */
  463. protected function init()
  464. {
  465. }
  466. }