1 | <?php |
||
2 | /** |
||
3 | * @link https://www.yiiframework.com/ |
||
4 | * @copyright Copyright (c) 2008 Yii Software LLC |
||
5 | * @license https://www.yiiframework.com/license/ |
||
6 | */ |
||
7 | |||
8 | namespace yii\console; |
||
9 | |||
10 | use Yii; |
||
11 | use yii\base\InvalidRouteException; |
||
12 | |||
13 | // define STDIN, STDOUT and STDERR if the PHP SAPI did not define them (e.g. creating console application in web env) |
||
14 | // https://www.php.net/manual/en/features.commandline.io-streams.php |
||
15 | 1 | defined('STDIN') or define('STDIN', fopen('php://stdin', 'r')); |
|
16 | 1 | defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w')); |
|
17 | 1 | defined('STDERR') or define('STDERR', fopen('php://stderr', 'w')); |
|
18 | |||
19 | /** |
||
20 | * Application represents a console application. |
||
21 | * |
||
22 | * Application extends from [[\yii\base\Application]] by providing functionalities that are |
||
23 | * specific to console requests. In particular, it deals with console requests |
||
24 | * through a command-based approach: |
||
25 | * |
||
26 | * - A console application consists of one or several possible user commands; |
||
27 | * - Each user command is implemented as a class extending [[\yii\console\Controller]]; |
||
28 | * - User specifies which command to run on the command line; |
||
29 | * - The command processes the user request with the specified parameters. |
||
30 | * |
||
31 | * The command classes should be under the namespace specified by [[controllerNamespace]]. |
||
32 | * Their naming should follow the same naming convention as controllers. For example, the `help` command |
||
33 | * is implemented using the `HelpController` class. |
||
34 | * |
||
35 | * To run the console application, enter the following on the command line: |
||
36 | * |
||
37 | * ``` |
||
38 | * yii <route> [--param1=value1 --param2 ...] |
||
39 | * ``` |
||
40 | * |
||
41 | * where `<route>` refers to a controller route in the form of `ModuleID/ControllerID/ActionID` |
||
42 | * (e.g. `sitemap/create`), and `param1`, `param2` refers to a set of named parameters that |
||
43 | * will be used to initialize the controller action (e.g. `--since=0` specifies a `since` parameter |
||
44 | * whose value is 0 and a corresponding `$since` parameter is passed to the action method). |
||
45 | * |
||
46 | * A `help` command is provided by default, which lists available commands and shows their usage. |
||
47 | * To use this command, simply type: |
||
48 | * |
||
49 | * ``` |
||
50 | * yii help |
||
51 | * ``` |
||
52 | * |
||
53 | * @property-read ErrorHandler $errorHandler The error handler application component. |
||
54 | * @property-read Request $request The request component. |
||
55 | * @property-read Response $response The response component. |
||
56 | * |
||
57 | * @author Qiang Xue <[email protected]> |
||
58 | * @since 2.0 |
||
59 | */ |
||
60 | class Application extends \yii\base\Application |
||
61 | { |
||
62 | /** |
||
63 | * The option name for specifying the application configuration file path. |
||
64 | */ |
||
65 | const OPTION_APPCONFIG = 'appconfig'; |
||
66 | |||
67 | /** |
||
68 | * @var string the default route of this application. Defaults to 'help', |
||
69 | * meaning the `help` command. |
||
70 | */ |
||
71 | public $defaultRoute = 'help'; |
||
72 | /** |
||
73 | * @var bool whether to enable the commands provided by the core framework. |
||
74 | * Defaults to true. |
||
75 | */ |
||
76 | public $enableCoreCommands = true; |
||
77 | /** |
||
78 | * @var Controller the currently active controller instance |
||
79 | */ |
||
80 | public $controller; |
||
81 | |||
82 | |||
83 | /** |
||
84 | * {@inheritdoc} |
||
85 | */ |
||
86 | 4066 | public function __construct($config = []) |
|
87 | { |
||
88 | 4066 | $config = $this->loadConfig($config); |
|
89 | 4066 | parent::__construct($config); |
|
90 | } |
||
91 | |||
92 | /** |
||
93 | * Loads the configuration. |
||
94 | * This method will check if the command line option [[OPTION_APPCONFIG]] is specified. |
||
95 | * If so, the corresponding file will be loaded as the application configuration. |
||
96 | * Otherwise, the configuration provided as the parameter will be returned back. |
||
97 | * @param array $config the configuration provided in the constructor. |
||
98 | * @return array the actual configuration to be used by the application. |
||
99 | */ |
||
100 | 4066 | protected function loadConfig($config) |
|
101 | { |
||
102 | 4066 | if (!empty($_SERVER['argv'])) { |
|
103 | 4066 | $option = '--' . self::OPTION_APPCONFIG . '='; |
|
104 | 4066 | foreach ($_SERVER['argv'] as $param) { |
|
105 | 4066 | if (strpos($param, $option) !== false) { |
|
106 | $path = substr($param, strlen($option)); |
||
107 | if (!empty($path) && is_file($file = Yii::getAlias($path))) { |
||
108 | return require $file; |
||
109 | } |
||
110 | |||
111 | exit("The configuration file does not exist: $path\n"); |
||
112 | } |
||
113 | } |
||
114 | } |
||
115 | |||
116 | 4066 | return $config; |
|
117 | } |
||
118 | |||
119 | /** |
||
120 | * Initialize the application. |
||
121 | */ |
||
122 | 4066 | public function init() |
|
123 | { |
||
124 | 4066 | parent::init(); |
|
125 | 4066 | if ($this->enableCoreCommands) { |
|
126 | 4048 | foreach ($this->coreCommands() as $id => $command) { |
|
127 | 4048 | if (!isset($this->controllerMap[$id])) { |
|
128 | 4048 | $this->controllerMap[$id] = $command; |
|
129 | } |
||
130 | } |
||
131 | } |
||
132 | // ensure we have the 'help' command so that we can list the available commands |
||
133 | 4066 | if (!isset($this->controllerMap['help'])) { |
|
134 | 24 | $this->controllerMap['help'] = 'yii\console\controllers\HelpController'; |
|
135 | } |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Handles the specified request. |
||
140 | * @param Request $request the request to be handled |
||
141 | * @return Response the resulting response |
||
142 | */ |
||
143 | 1 | public function handleRequest($request) |
|
144 | { |
||
145 | 1 | list($route, $params) = $request->resolve(); |
|
146 | 1 | $this->requestedRoute = $route; |
|
147 | 1 | $result = $this->runAction($route, $params); |
|
148 | 1 | if ($result instanceof Response) { |
|
149 | 1 | return $result; |
|
150 | } |
||
151 | |||
152 | 1 | $response = $this->getResponse(); |
|
153 | 1 | $response->exitStatus = $result; |
|
154 | |||
155 | 1 | return $response; |
|
156 | } |
||
157 | |||
158 | /** |
||
159 | * Runs a controller action specified by a route. |
||
160 | * This method parses the specified route and creates the corresponding child module(s), controller and action |
||
161 | * instances. It then calls [[Controller::runAction()]] to run the action with the given parameters. |
||
162 | * If the route is empty, the method will use [[defaultRoute]]. |
||
163 | * |
||
164 | * For example, to run `public function actionTest($a, $b)` assuming that the controller has options the following |
||
165 | * code should be used: |
||
166 | * |
||
167 | * ```php |
||
168 | * \Yii::$app->runAction('controller/test', ['option' => 'value', $a, $b]); |
||
169 | * ``` |
||
170 | * |
||
171 | * @param string $route the route that specifies the action. |
||
172 | * @param array $params the parameters to be passed to the action |
||
173 | * @return int|Response|null the result of the action. This can be either an exit code or Response object. |
||
174 | * Exit code 0 means normal, and other values mean abnormal. Exit code of `null` is treated as `0` as well. |
||
175 | * @throws Exception if the route is invalid |
||
176 | */ |
||
177 | 9 | public function runAction($route, $params = []) |
|
178 | { |
||
179 | try { |
||
180 | 9 | $res = parent::runAction($route, $params); |
|
181 | 9 | return is_object($res) ? $res : (int) $res; |
|
182 | } catch (InvalidRouteException $e) { |
||
183 | throw new UnknownCommandException($route, $this, 0, $e); |
||
184 | } |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Returns the configuration of the built-in commands. |
||
189 | * @return array the configuration of the built-in commands. |
||
190 | */ |
||
191 | 4048 | public function coreCommands() |
|
192 | { |
||
193 | 4048 | return [ |
|
194 | 4048 | 'asset' => 'yii\console\controllers\AssetController', |
|
195 | 4048 | 'cache' => 'yii\console\controllers\CacheController', |
|
196 | 4048 | 'fixture' => 'yii\console\controllers\FixtureController', |
|
197 | 4048 | 'help' => 'yii\console\controllers\HelpController', |
|
198 | 4048 | 'message' => 'yii\console\controllers\MessageController', |
|
199 | 4048 | 'migrate' => 'yii\console\controllers\MigrateController', |
|
200 | 4048 | 'serve' => 'yii\console\controllers\ServeController', |
|
201 | 4048 | ]; |
|
202 | } |
||
203 | |||
204 | /** |
||
205 | * Returns the error handler component. |
||
206 | * @return ErrorHandler the error handler application component. |
||
207 | */ |
||
208 | public function getErrorHandler() |
||
209 | { |
||
210 | return $this->get('errorHandler'); |
||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
Loading history...
|
|||
211 | } |
||
212 | |||
213 | /** |
||
214 | * Returns the request component. |
||
215 | * @return Request the request component. |
||
216 | */ |
||
217 | 110 | public function getRequest() |
|
218 | { |
||
219 | 110 | return $this->get('request'); |
|
0 ignored issues
–
show
|
|||
220 | } |
||
221 | |||
222 | /** |
||
223 | * Returns the response component. |
||
224 | * @return Response the response component. |
||
225 | */ |
||
226 | 3 | public function getResponse() |
|
227 | { |
||
228 | 3 | return $this->get('response'); |
|
0 ignored issues
–
show
|
|||
229 | } |
||
230 | |||
231 | /** |
||
232 | * {@inheritdoc} |
||
233 | */ |
||
234 | 4066 | public function coreComponents() |
|
235 | { |
||
236 | 4066 | return array_merge(parent::coreComponents(), [ |
|
237 | 4066 | 'request' => ['class' => 'yii\console\Request'], |
|
238 | 4066 | 'response' => ['class' => 'yii\console\Response'], |
|
239 | 4066 | 'errorHandler' => ['class' => 'yii\console\ErrorHandler'], |
|
240 | 4066 | ]); |
|
241 | } |
||
242 | } |
||
243 |