From bd70ac840f717b7419aef34e5bb1342b06d4c0b3 Mon Sep 17 00:00:00 2001
From: Qiang Xue <qiang.xue@gmail.com>
Date: Fri, 7 Feb 2014 21:58:24 -0500
Subject: [PATCH] Fixes #2054: Added support for using custom application configuration with the console command runner

---
 docs/guide/console.md             | 21 ++++++++++++++++-----
 framework/CHANGELOG.md            |  1 +
 framework/console/Application.php | 41 +++++++++++++++++++++++++++++++++++++++++
 framework/console/Request.php     |  4 +++-
 4 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/docs/guide/console.md b/docs/guide/console.md
index 9d3c2b7..2ebc638 100644
--- a/docs/guide/console.md
+++ b/docs/guide/console.md
@@ -58,16 +58,27 @@ exit($exitCode);
 ```
 
 This script is a part of your application so you're free to adjust it. The `YII_DEBUG` constant can be set `false` if you do
-not want to see stacktrace on error and want to improve overall performance. In both basic and advanced application
+not want to see stack trace on error and want to improve overall performance. In both basic and advanced application
 templates it is enabled to provide more developer-friendly environment.
 
 Configuration
 -------------
 
-As can be seen in the code above, console application uses its own config files named `console.php` so you need to
-configure database connection and the rest of the components you're going to use there in that file. If web and console
-application configs have a lot in common it's a good idea to move matching parts into their own config files as it was
-done in advanced application template.
+As can be seen in the code above, console application uses its own config files named `console.php`. In this file,
+you should specify how to configure various application components and properties.
+
+If your Web application and the console application share a lot of configurations, you may consider moving the common
+part into a separate file, and include this file in both of the application configurations, just as what is done
+in the "advanced" application template.
+
+Sometimes, you may want to run a console command using an application configuration that is different from the one
+specified in the entry script. For example, you may want to use the `yii migrate` command to upgrade your
+test databases which are configured in each individual test suite. To do so, simply specify the custom application configuration
+file via the `appconfig` option, like the following,
+
+```
+yii <route> --appconfig=path/to/config.php ...
+```
 
 
 Creating your own console commands
diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md
index 914b820..9abb20a 100644
--- a/framework/CHANGELOG.md
+++ b/framework/CHANGELOG.md
@@ -93,6 +93,7 @@ Yii Framework 2 Change Log
 - Enh #2008: `yii message/extract` is now able to save translation strings to database (kate-kate, samdark)
 - Enh #2043: Added support for custom request body parsers (danschmidt5189, cebe)
 - Enh #2051: Do not save null data into database when using RBAC (qiangxue)
+- Enh #2054: Added support for using custom application configuration with the console command runner (qiangxue)
 - Enh #2079:
 	- i18n now falls back to `en` from `en-US` if message translation isn't found (samdark)
 	- View now falls back to `en` from `en-US` if file not found (samdark)
diff --git a/framework/console/Application.php b/framework/console/Application.php
index c4b0f60..5ccd1fa 100644
--- a/framework/console/Application.php
+++ b/framework/console/Application.php
@@ -54,6 +54,11 @@ use yii\base\InvalidRouteException;
 class Application extends \yii\base\Application
 {
 	/**
+	 * The option name for specifying the application configuration file path.
+	 */
+	const OPTION_APPCONFIG = 'appconfig';
+
+	/**
 	 * @var string the default route of this application. Defaults to 'help',
 	 * meaning the `help` command.
 	 */
@@ -68,6 +73,42 @@ class Application extends \yii\base\Application
 	 */
 	public $controller;
 
+
+	/**
+	 * @inheritdoc
+	 */
+	public function __construct($config = [])
+	{
+		$config = $this->loadConfig($config);
+		parent::__construct($config);
+	}
+
+	/**
+	 * Loads the configuration.
+	 * This method will check if the command line option [[OPTION_APPCONFIG]] is specified.
+	 * If so, the corresponding file will be loaded as the application configuration.
+	 * Otherwise, the configuration provided as the parameter will be returned back.
+	 * @param array $config the configuration provided in the constructor.
+	 * @return array the actual configuration to be used by the application.
+	 */
+	protected function loadConfig($config)
+	{
+		if (!empty($_SERVER['argv'])) {
+			$option = '--' . self::OPTION_APPCONFIG . '=';
+			foreach ($_SERVER['argv'] as $param) {
+				if (strpos($param, $option) !== false) {
+					$path = substr($param, strlen($option));
+					if (!empty($path) && is_file($path)) {
+						return require($path);
+					} else {
+						die("The configuration file does not exist: $path\n");
+					}
+				}
+			}
+		}
+		return $config;
+	}
+
 	/**
 	 * Initialize the application.
 	 */
diff --git a/framework/console/Request.php b/framework/console/Request.php
index d4d3af0..e5aa9fd 100644
--- a/framework/console/Request.php
+++ b/framework/console/Request.php
@@ -66,7 +66,9 @@ class Request extends \yii\base\Request
 		foreach ($rawParams as $param) {
 			if (preg_match('/^--(\w+)(=(.*))?$/', $param, $matches)) {
 				$name = $matches[1];
-				$params[$name] = isset($matches[3]) ? $matches[3] : true;
+				if ($name !== Application::OPTION_APPCONFIG) {
+					$params[$name] = isset($matches[3]) ? $matches[3] : true;
+				}
 			} else {
 				$params[] = $param;
 			}
--
libgit2 0.27.1