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

namespace yii\console;

Qiang Xue committed
12
use yii\base\Exception;
Qiang Xue committed
13
use yii\util\ReflectionHelper;
Qiang Xue committed
14

Alexander Makarov committed
15
/**
Qiang Xue committed
16
 * Application represents a console application.
Alexander Makarov committed
17
 *
Qiang Xue committed
18
 * Application extends from [[yii\base\Application]] by providing functionalities that are
Alexander Makarov committed
19 20 21
 * specific to console requests. In particular, it deals with console requests
 * through a command-based approach:
 *
Qiang Xue committed
22
 * - A console application consists of one or several possible user commands;
Qiang Xue committed
23
 * - Each user command is implemented as a class extending [[\yii\console\Controller]];
Qiang Xue committed
24 25 26
 * - User specifies which command to run on the command line;
 * - The command processes the user request with the specified parameters.
 *
Qiang Xue committed
27 28 29
 * The command classes reside in the directory specified by [[controllerPath]].
 * Their naming should follow the same naming as controllers. For example, the `help` command
 * is implemented using the `HelpController` class.
Alexander Makarov committed
30 31 32
 *
 * To run the console application, enter the following on the command line:
 *
Qiang Xue committed
33
 * ~~~
Qiang Xue committed
34
 * yiic <route> [...options...]
Qiang Xue committed
35 36
 * ~~~
 *
Qiang Xue committed
37 38 39 40 41 42 43
 * where `<route>` refers to a controller route in the form of `ModuleID/ControllerID/ActionID`
 * (e.g. `sitemap/create`), and `options` refers to a set of named parameters that will be used
 * to initialize the command controller instance and the corresponding action (e.g. `--since=0`
 * specifies a `since` parameter whose value is 0).
 *
 * A `help` command is provided by default, which may list available commands and show their usage.
 * To use this command, simply type:
Qiang Xue committed
44 45
 *
 * ~~~
Qiang Xue committed
46
 * yiic help
Qiang Xue committed
47
 * ~~~
Alexander Makarov committed
48 49 50 51 52 53 54
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Application extends \yii\base\Application
{
	/**
Qiang Xue committed
55 56
	 * @var string the default route of this application. Defaults to 'help',
	 * meaning the `help` command.
Alexander Makarov committed
57
	 */
Qiang Xue committed
58
	public $defaultRoute = 'help';
Alexander Makarov committed
59
	/**
Qiang Xue committed
60 61
	 * @var boolean whether to enable the commands provided by the core framework.
	 * Defaults to true.
Alexander Makarov committed
62
	 */
Qiang Xue committed
63
	public $enableCoreCommands = true;
Alexander Makarov committed
64 65 66

	public function init()
	{
Qiang Xue committed
67 68 69 70 71 72 73 74 75
		parent::init();
		if ($this->enableCoreCommands) {
			foreach ($this->coreCommands() as $id => $command) {
				if (!isset($this->controllers[$id])) {
					$this->controllers[$id] = $command;
				}
			}
		}
		// ensure we have the 'help' command so that we can list the available commands
Qiang Xue committed
76
		if (!isset($this->controllers['help'])) {
Qiang Xue committed
77
			$this->controllers['help'] = 'yii\console\commands\HelpController';
Alexander Makarov committed
78 79 80 81
		}
	}

	/**
Qiang Xue committed
82 83 84 85
	 * Processes the request.
	 * The request is represented in terms of a controller route and action parameters.
	 * @return integer the exit status of the controller action (0 means normal, non-zero values mean abnormal)
	 * @throws Exception if the route cannot be resolved into a controller
Alexander Makarov committed
86
	 */
Qiang Xue committed
87
	public function processRequest()
Alexander Makarov committed
88
	{
Qiang Xue committed
89 90 91 92
		if (!isset($_SERVER['argv'])) {
			die('This script must be run from the command line.');
		}
		list($route, $params) = $this->resolveRequest($_SERVER['argv']);
Qiang Xue committed
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
		return $this->runController($route, $params);
	}

	/**
	 * 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)
	 * @throws Exception if the route cannot be resolved into a controller
	 */
	public function runController($route, $params = array())
	{
		$result = $this->createController($route);
		if ($result === false) {
			throw new Exception(\Yii::t('yii', 'Unable to resolve the request.'));
		}
		list($controller, $action) = $result;
		$priorController = $this->controller;
		$this->controller = $controller;
		$params = ReflectionHelper::initObjectWithParams($controller, $params);
		$status = $controller->run($action, $params);
		$this->controller = $priorController;
Qiang Xue committed
115
		return $status;
Alexander Makarov committed
116 117 118
	}

	/**
Qiang Xue committed
119 120 121
	 * Resolves the request.
	 * @param array $args the arguments passed via the command line
	 * @return array the controller route and the parameters for the controller action
Alexander Makarov committed
122
	 */
Qiang Xue committed
123
	protected function resolveRequest($args)
Alexander Makarov committed
124
	{
Qiang Xue committed
125
		array_shift($args);  // the 1st argument is the yiic script name
Alexander Makarov committed
126

Qiang Xue committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
		if (isset($args[0])) {
			$route = $args[0];
			array_shift($args);
		} else {
			$route = '';
		}

		$params = array();
		foreach ($args as $arg) {
			if (preg_match('/^--(\w+)(=(.*))?$/', $arg, $matches)) {
				$name = $matches[1];
				$params[$name] = isset($matches[3]) ? $matches[3] : true;
			} else {
				$params['args'][] = $arg;
			}
Alexander Makarov committed
142
		}
Qiang Xue committed
143 144

		return array($route, $params);
Alexander Makarov committed
145 146
	}

Qiang Xue committed
147
	public function coreCommands()
Alexander Makarov committed
148
	{
Qiang Xue committed
149 150 151 152 153 154 155
		return array(
			'message' => 'yii\console\commands\MessageController',
			'help' => 'yii\console\commands\HelpController',
			'migrate' => 'yii\console\commands\MigrateController',
			'shell' => 'yii\console\commands\ShellController',
			'app' => 'yii\console\commands\AppController',
		);
Alexander Makarov committed
156 157
	}
}