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

10 11
namespace yii\base;

Qiang Xue committed
12
use yii\base\InvalidCallException;
.  
Qiang Xue committed
13

w  
Qiang Xue committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
/**
 * Application is the base class for all application classes.
 *
 * An application serves as the global context that the user request
 * is being processed. It manages a set of application components that
 * provide specific functionalities to the whole application.
 *
 * The core application components provided by Application are the following:
 * <ul>
 * <li>{@link getErrorHandler errorHandler}: handles PHP errors and
 *   uncaught exceptions. This application component is dynamically loaded when needed.</li>
 * <li>{@link getSecurityManager securityManager}: provides security-related
 *   services, such as hashing, encryption. This application component is dynamically
 *   loaded when needed.</li>
 * <li>{@link getStatePersister statePersister}: provides global state
 *   persistence method. This application component is dynamically loaded when needed.</li>
 * <li>{@link getCache cache}: provides caching feature. This application component is
 *   disabled by default.</li>
 * <li>{@link getMessages messages}: provides the message source for translating
 *   application messages. This application component is dynamically loaded when needed.</li>
 * <li>{@link getCoreMessages coreMessages}: provides the message source for translating
 *   Yii framework messages. This application component is dynamically loaded when needed.</li>
 * </ul>
 *
 * Application will undergo the following lifecycles when processing a user request:
 * <ol>
 * <li>load application configuration;</li>
 * <li>set up class autoloader and error handling;</li>
 * <li>load static application components;</li>
43
 * <li>{@link beforeRequest}: preprocess the user request; `beforeRequest` event raised.</li>
w  
Qiang Xue committed
44
 * <li>{@link processRequest}: process the user request;</li>
45
 * <li>{@link afterRequest}: postprocess the user request; `afterRequest` event raised.</li>
w  
Qiang Xue committed
46 47 48 49 50 51 52 53 54
 * </ol>
 *
 * Starting from lifecycle 3, if a PHP error or an uncaught exception occurs,
 * the application will switch to its error handling logic and jump to step 6 afterwards.
 *
 * @property string $basePath Returns the root path of the application.
 * @property CCache $cache Returns the cache component.
 * @property CPhpMessageSource $coreMessages Returns the core message translations.
 * @property CDateFormatter $dateFormatter Returns the locale-dependent date formatter.
Qiang Xue committed
55
 * @property \yii\db\Connection $db Returns the database connection component.
w  
Qiang Xue committed
56 57 58 59 60 61 62 63 64 65 66 67 68
 * @property CErrorHandler $errorHandler Returns the error handler component.
 * @property string $extensionPath Returns the root directory that holds all third-party extensions.
 * @property string $id Returns the unique identifier for the application.
 * @property string $language Returns the language that the user is using and the application should be targeted to.
 * @property CLocale $locale Returns the locale instance.
 * @property string $localeDataPath Returns the directory that contains the locale data.
 * @property CMessageSource $messages Returns the application message translations component.
 * @property CNumberFormatter $numberFormatter The locale-dependent number formatter.
 * @property CHttpRequest $request Returns the request component.
 * @property string $runtimePath Returns the directory that stores runtime files.
 * @property CSecurityManager $securityManager Returns the security manager component.
 * @property CStatePersister $statePersister Returns the state persister component.
 * @property string $timeZone Returns the time zone used by this application.
69
 * @property UrlManager $urlManager Returns the URL manager component.
w  
Qiang Xue committed
70 71
 * @property string $baseUrl Returns the relative URL for the application
 * @property string $homeUrl the homepage URL
w  
Qiang Xue committed
72 73 74
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
w  
Qiang Xue committed
75
 */
Qiang Xue committed
76
class Application extends Module
w  
Qiang Xue committed
77 78 79 80 81
{
	/**
	 * @var string the application name. Defaults to 'My Application'.
	 */
	public $name = 'My Application';
Qiang Xue committed
82 83 84 85
	/**
	 * @var string the version of this application. Defaults to '1.0'.
	 */
	public $version = '1.0';
w  
Qiang Xue committed
86 87 88 89 90 91 92
	/**
	 * @var string the charset currently used for the application. Defaults to 'UTF-8'.
	 */
	public $charset = 'UTF-8';
	/**
	 * @var string the language that the application is written in. This mainly refers to
	 * the language that the messages and view files are in. Defaults to 'en_us' (US English).
.  
Qiang Xue committed
93
	 * @see language
w  
Qiang Xue committed
94 95
	 */
	public $sourceLanguage = 'en_us';
Qiang Xue committed
96 97 98 99 100
	/**
	 * @var array IDs of application components that need to be loaded when the application starts.
	 * The default value is `array('errorHandler')`, which loads the [[errorHandler]] component
	 * to ensure errors and exceptions can be handled nicely.
	 */
Qiang Xue committed
101
	public $preload = array('errorHandler');
Qiang Xue committed
102 103 104 105
	/**
	 * @var Controller the currently active controller instance
	 */
	public $controller;
Qiang Xue committed
106 107 108 109 110
	/**
	 * @var mixed the layout that should be applied for views in this application. Defaults to 'main'.
	 * If this is false, layout will be disabled.
	 */
	public $layout = 'main';
w  
Qiang Xue committed
111

Qiang Xue committed
112
	// todo
Qiang Xue committed
113 114
	public $localeDataPath = '@yii/i18n/data';

w  
Qiang Xue committed
115 116 117 118 119 120
	private $_runtimePath;
	private $_ended = false;
	private $_language;

	/**
	 * Constructor.
Qiang Xue committed
121
	 * @param string $id the ID of this application. The ID should uniquely identify the application from others.
Qiang Xue committed
122 123
	 * @param string $basePath the base path of this application. This should point to
	 * the directory containing all application logic, template and data.
Qiang Xue committed
124
	 * @param array $config name-value pairs that will be used to initialize the object properties
w  
Qiang Xue committed
125
	 */
Qiang Xue committed
126
	public function __construct($id, $basePath, $config = array())
w  
Qiang Xue committed
127
	{
Qiang Xue committed
128
		\Yii::$application = $this;
Qiang Xue committed
129
		$this->id = $id;
.  
Qiang Xue committed
130
		$this->setBasePath($basePath);
Qiang Xue committed
131
		$this->registerDefaultAliases();
w  
Qiang Xue committed
132
		$this->registerCoreComponents();
133
		parent::__construct($id, $this, $config);
.  
Qiang Xue committed
134
	}
w  
Qiang Xue committed
135

.  
Qiang Xue committed
136
	/**
Qiang Xue committed
137 138
	 * Initializes the application by loading components declared in [[preload]].
	 * If you override this method, make sure the parent implementation is invoked.
.  
Qiang Xue committed
139 140 141
	 */
	public function init()
	{
w  
Qiang Xue committed
142 143 144 145 146
		$this->preloadComponents();
	}

	/**
	 * Terminates the application.
.  
Qiang Xue committed
147
	 * This method replaces PHP's exit() function by calling [[afterRequest()]] before exiting.
w  
Qiang Xue committed
148
	 * @param integer $status exit status (value 0 means normal exit while other values mean abnormal exit).
.  
Qiang Xue committed
149
	 * @param boolean $exit whether to exit the current request.
w  
Qiang Xue committed
150 151 152 153
	 * It defaults to true, meaning the PHP's exit() function will be called at the end of this method.
	 */
	public function end($status = 0, $exit = true)
	{
.  
Qiang Xue committed
154 155 156
		if (!$this->_ended) {
			$this->_ended = true;
			$this->afterRequest();
Qiang Xue committed
157 158
		}
		if ($exit) {
w  
Qiang Xue committed
159
			exit($status);
Qiang Xue committed
160
		}
w  
Qiang Xue committed
161 162
	}

Qiang Xue committed
163 164 165 166 167 168 169 170 171 172 173 174 175
	/**
	 * Runs the application.
	 * This is the main entrance of an application.
	 * @return integer the exit status (0 means normal, non-zero values mean abnormal)
	 */
	public function run()
	{
		$this->beforeRequest();
		$status = $this->processRequest();
		$this->afterRequest();
		return $status;
	}

w  
Qiang Xue committed
176
	/**
.  
Qiang Xue committed
177
	 * Raises the [[beforeRequest]] event right BEFORE the application processes the request.
w  
Qiang Xue committed
178
	 */
.  
Qiang Xue committed
179
	public function beforeRequest()
w  
Qiang Xue committed
180
	{
.  
Qiang Xue committed
181
		$this->trigger('beforeRequest');
w  
Qiang Xue committed
182 183
	}

Qiang Xue committed
184
	/**
Qiang Xue committed
185
	 * Raises the [[afterRequest]] event right AFTER the application processes the request.
Qiang Xue committed
186
	 */
Qiang Xue committed
187
	public function afterRequest()
Qiang Xue committed
188
	{
Qiang Xue committed
189
		$this->trigger('afterRequest');
Qiang Xue committed
190 191
	}

w  
Qiang Xue committed
192
	/**
Qiang Xue committed
193
	 * Processes the request.
Qiang Xue committed
194
	 * Child classes should override this method with actual request processing logic.
Qiang Xue committed
195
	 * @return integer the exit status of the controller action (0 means normal, non-zero values mean abnormal)
Qiang Xue committed
196 197 198 199 200 201 202 203 204 205 206
	 */
	public function processRequest()
	{
		return 0;
	}

	/**
	 * Runs a controller with the given route and parameters.
	 * @param string $route the route (e.g. `post/create`)
	 * @param array $params the parameters to be passed to the controller action
	 * @return integer the exit status (0 means normal, non-zero values mean abnormal)
Qiang Xue committed
207
	 * @throws BadRequestException if the route cannot be resolved into a controller
w  
Qiang Xue committed
208
	 */
Qiang Xue committed
209
	public function runController($route, $params = array())
w  
Qiang Xue committed
210
	{
Qiang Xue committed
211 212
		$result = $this->createController($route);
		if ($result === false) {
Qiang Xue committed
213
			throw new BadRequestException(\Yii::t('yii', 'Unable to resolve the request.'));
Qiang Xue committed
214
		}
Qiang Xue committed
215
		/** @var $controller Controller */
Qiang Xue committed
216
		list($controller, $action) = $result;
Qiang Xue committed
217
		$priorController = $this->controller;
Qiang Xue committed
218 219
		$this->controller = $controller;
		$status = $controller->run($action, $params);
Qiang Xue committed
220
		$this->controller = $priorController;
Qiang Xue committed
221
		return $status;
w  
Qiang Xue committed
222 223 224 225 226 227 228 229
	}

	/**
	 * Returns the directory that stores runtime files.
	 * @return string the directory that stores runtime files. Defaults to 'protected/runtime'.
	 */
	public function getRuntimePath()
	{
Qiang Xue committed
230
		if ($this->_runtimePath !== null) {
w  
Qiang Xue committed
231 232
			$this->setRuntimePath($this->getBasePath() . DIRECTORY_SEPARATOR . 'runtime');
		}
Qiang Xue committed
233
		return $this->_runtimePath;
w  
Qiang Xue committed
234 235 236 237 238
	}

	/**
	 * Sets the directory that stores runtime files.
	 * @param string $path the directory that stores runtime files.
Qiang Xue committed
239
	 * @throws InvalidCallException if the directory does not exist or is not writable
w  
Qiang Xue committed
240 241 242
	 */
	public function setRuntimePath($path)
	{
Qiang Xue committed
243 244
		$p = \Yii::getAlias($path);
		if ($p === false || !is_dir($p) || !is_writable($path)) {
Qiang Xue committed
245
			throw new InvalidCallException("Application runtime path \"$path\" is invalid. Please make sure it is a directory writable by the Web server process.");
Qiang Xue committed
246 247
		} else {
			$this->_runtimePath = $p;
Qiang Xue committed
248
		}
w  
Qiang Xue committed
249 250 251
	}

	/**
.  
Qiang Xue committed
252 253 254
	 * Returns the language that the end user is using.
	 * @return string the language that the user is using (e.g. 'en_US', 'zh_CN').
	 * Defaults to the value of [[sourceLanguage]].
w  
Qiang Xue committed
255 256 257 258 259 260 261
	 */
	public function getLanguage()
	{
		return $this->_language === null ? $this->sourceLanguage : $this->_language;
	}

	/**
.  
Qiang Xue committed
262 263 264 265
	 * Specifies which language the end user is using.
	 * This is the language that the application should use to display to end users.
	 * By default, [[language]] and [[sourceLanguage]] are the same.
	 * Do not set this property unless your application needs to support multiple languages.
w  
Qiang Xue committed
266
	 * @param string $language the user language (e.g. 'en_US', 'zh_CN').
Qiang Xue committed
267
	 * If it is null, the [[sourceLanguage]] will be used.
w  
Qiang Xue committed
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 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
	 */
	public function setLanguage($language)
	{
		$this->_language = $language;
	}

	/**
	 * Returns the time zone used by this application.
	 * This is a simple wrapper of PHP function date_default_timezone_get().
	 * @return string the time zone used by this application.
	 * @see http://php.net/manual/en/function.date-default-timezone-get.php
	 */
	public function getTimeZone()
	{
		return date_default_timezone_get();
	}

	/**
	 * Sets the time zone used by this application.
	 * This is a simple wrapper of PHP function date_default_timezone_set().
	 * @param string $value the time zone used by this application.
	 * @see http://php.net/manual/en/function.date-default-timezone-set.php
	 */
	public function setTimeZone($value)
	{
		date_default_timezone_set($value);
	}

	/**
	 * Returns the locale instance.
	 * @param string $localeID the locale ID (e.g. en_US). If null, the {@link getLanguage application language ID} will be used.
	 * @return CLocale the locale instance
	 */
	public function getLocale($localeID = null)
	{
		return CLocale::getInstance($localeID === null ? $this->getLanguage() : $localeID);
	}

	/**
	 * @return CNumberFormatter the locale-dependent number formatter.
	 * The current {@link getLocale application locale} will be used.
	 */
	public function getNumberFormatter()
	{
		return $this->getLocale()->getNumberFormatter();
	}

	/**
	 * Returns the locale-dependent date formatter.
	 * @return CDateFormatter the locale-dependent date formatter.
	 * The current {@link getLocale application locale} will be used.
	 */
	public function getDateFormatter()
	{
		return $this->getLocale()->getDateFormatter();
	}

	/**
	 * Returns the database connection component.
Qiang Xue committed
327
	 * @return \yii\db\Connection the database connection
w  
Qiang Xue committed
328 329 330 331 332 333 334 335
	 */
	public function getDb()
	{
		return $this->getComponent('db');
	}

	/**
	 * Returns the error handler component.
.  
Qiang Xue committed
336
	 * @return ErrorHandler the error handler application component.
w  
Qiang Xue committed
337 338 339 340 341 342
	 */
	public function getErrorHandler()
	{
		return $this->getComponent('errorHandler');
	}

Qiang Xue committed
343 344 345 346 347 348 349 350 351
	/**
	 * Returns the application theme.
	 * @return Theme the theme that this application is currently using.
	 */
	public function getTheme()
	{
		return $this->getComponent('theme');
	}

w  
Qiang Xue committed
352 353
	/**
	 * Returns the security manager component.
.  
Qiang Xue committed
354
	 * @return SecurityManager the security manager application component.
w  
Qiang Xue committed
355 356 357 358 359 360 361 362
	 */
	public function getSecurityManager()
	{
		return $this->getComponent('securityManager');
	}

	/**
	 * Returns the cache component.
.  
Qiang Xue committed
363
	 * @return \yii\caching\Cache the cache application component. Null if the component is not enabled.
w  
Qiang Xue committed
364 365 366 367 368 369 370 371
	 */
	public function getCache()
	{
		return $this->getComponent('cache');
	}

	/**
	 * Returns the core message translations component.
.  
Qiang Xue committed
372
	 * @return \yii\i18n\MessageSource the core message translations
w  
Qiang Xue committed
373 374 375 376 377 378 379 380
	 */
	public function getCoreMessages()
	{
		return $this->getComponent('coreMessages');
	}

	/**
	 * Returns the application message translations component.
.  
Qiang Xue committed
381
	 * @return \yii\i18n\MessageSource the application message translations
w  
Qiang Xue committed
382 383 384 385 386 387 388 389
	 */
	public function getMessages()
	{
		return $this->getComponent('messages');
	}

	/**
	 * Returns the request component.
.  
Qiang Xue committed
390
	 * @return Request the request component
w  
Qiang Xue committed
391 392 393 394 395 396
	 */
	public function getRequest()
	{
		return $this->getComponent('request');
	}

Qiang Xue committed
397 398 399 400 401 402 403 404 405 406
	/**
	 * Sets default path aliases.
	 */
	public function registerDefaultAliases()
	{
		\Yii::$aliases['@application'] = $this->getBasePath();
		\Yii::$aliases['@entry'] = dirname($_SERVER['SCRIPT_FILENAME']);
		\Yii::$aliases['@www'] = '';
	}

w  
Qiang Xue committed
407 408 409 410
	/**
	 * Registers the core application components.
	 * @see setComponents
	 */
.  
Qiang Xue committed
411
	public function registerCoreComponents()
w  
Qiang Xue committed
412
	{
.  
Qiang Xue committed
413 414 415 416 417 418 419 420
		$this->setComponents(array(
			'errorHandler' => array(
				'class' => 'yii\base\ErrorHandler',
			),
			'request' => array(
				'class' => 'yii\base\Request',
			),
			'response' => array(
Qiang Xue committed
421
				'class' => 'yii\base\Response',
.  
Qiang Xue committed
422 423 424 425
			),
			'format' => array(
				'class' => 'yii\base\Formatter',
			),
w  
Qiang Xue committed
426
			'coreMessages' => array(
.  
Qiang Xue committed
427
				'class' => 'yii\i18n\PhpMessageSource',
w  
Qiang Xue committed
428
				'language' => 'en_us',
Qiang Xue committed
429
				'basePath' => '@yii/messages',
w  
Qiang Xue committed
430 431
			),
			'messages' => array(
.  
Qiang Xue committed
432
				'class' => 'yii\i18n\PhpMessageSource',
w  
Qiang Xue committed
433 434
			),
			'securityManager' => array(
.  
Qiang Xue committed
435
				'class' => 'yii\base\SecurityManager',
w  
Qiang Xue committed
436
			),
437 438 439
			'urlManager' => array(
				'class' => 'yii\web\UrlManager',
			),
.  
Qiang Xue committed
440
		));
w  
Qiang Xue committed
441 442
	}
}