DbConfigTask.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. <?php
  2. /**
  3. * The DbConfig Task handles creating and updating the database.php
  4. *
  5. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7. *
  8. * Licensed under The MIT License
  9. * For full copyright and license information, please see the LICENSE.txt
  10. * Redistributions of files must retain the above copyright notice.
  11. *
  12. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  13. * @link http://cakephp.org CakePHP(tm) Project
  14. * @since CakePHP(tm) v 1.2
  15. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  16. */
  17. App::uses('AppShell', 'Console/Command');
  18. /**
  19. * Task class for creating and updating the database configuration file.
  20. *
  21. * @package Cake.Console.Command.Task
  22. */
  23. class DbConfigTask extends AppShell {
  24. /**
  25. * path to CONFIG directory
  26. *
  27. * @var string
  28. */
  29. public $path = null;
  30. /**
  31. * Default configuration settings to use
  32. *
  33. * @var array
  34. */
  35. protected $_defaultConfig = array(
  36. 'name' => 'default',
  37. 'datasource' => 'Database/Mysql',
  38. 'persistent' => 'false',
  39. 'host' => 'localhost',
  40. 'login' => 'root',
  41. 'password' => 'password',
  42. 'database' => 'project_name',
  43. 'schema' => null,
  44. 'prefix' => null,
  45. 'encoding' => null,
  46. 'port' => null
  47. );
  48. /**
  49. * String name of the database config class name.
  50. * Used for testing.
  51. *
  52. * @var string
  53. */
  54. public $databaseClassName = 'DATABASE_CONFIG';
  55. /**
  56. * initialization callback
  57. *
  58. * @return void
  59. */
  60. public function initialize() {
  61. $this->path = APP . 'Config' . DS;
  62. }
  63. /**
  64. * Execution method always used for tasks
  65. *
  66. * @return void
  67. */
  68. public function execute() {
  69. if (empty($this->args)) {
  70. $this->_interactive();
  71. return $this->_stop();
  72. }
  73. }
  74. /**
  75. * Interactive interface
  76. *
  77. * @return void
  78. */
  79. protected function _interactive() {
  80. $this->hr();
  81. $this->out(__d('cake_console', 'Database Configuration:'));
  82. $this->hr();
  83. $done = false;
  84. $dbConfigs = array();
  85. while (!$done) {
  86. $name = '';
  87. while (!$name) {
  88. $name = $this->in(__d('cake_console', "Name:"), null, 'default');
  89. if (preg_match('/[^a-z0-9_]/i', $name)) {
  90. $name = '';
  91. $this->out(__d('cake_console', 'The name may only contain unaccented latin characters, numbers or underscores'));
  92. } elseif (preg_match('/^[^a-z_]/i', $name)) {
  93. $name = '';
  94. $this->out(__d('cake_console', 'The name must start with an unaccented latin character or an underscore'));
  95. }
  96. }
  97. $datasource = $this->in(__d('cake_console', 'Datasource:'), array('Mysql', 'Postgres', 'Sqlite', 'Sqlserver'), 'Mysql');
  98. $persistent = $this->in(__d('cake_console', 'Persistent Connection?'), array('y', 'n'), 'n');
  99. if (strtolower($persistent) === 'n') {
  100. $persistent = 'false';
  101. } else {
  102. $persistent = 'true';
  103. }
  104. $host = '';
  105. while (!$host) {
  106. $host = $this->in(__d('cake_console', 'Database Host:'), null, 'localhost');
  107. }
  108. $port = '';
  109. while (!$port) {
  110. $port = $this->in(__d('cake_console', 'Port?'), null, 'n');
  111. }
  112. if (strtolower($port) === 'n') {
  113. $port = null;
  114. }
  115. $login = '';
  116. while (!$login) {
  117. $login = $this->in(__d('cake_console', 'User:'), null, 'root');
  118. }
  119. $password = '';
  120. $blankPassword = false;
  121. while (!$password && !$blankPassword) {
  122. $password = $this->in(__d('cake_console', 'Password:'));
  123. if (!$password) {
  124. $blank = $this->in(__d('cake_console', 'The password you supplied was empty. Use an empty password?'), array('y', 'n'), 'n');
  125. if ($blank === 'y') {
  126. $blankPassword = true;
  127. }
  128. }
  129. }
  130. $database = '';
  131. while (!$database) {
  132. $database = $this->in(__d('cake_console', 'Database Name:'), null, 'cake');
  133. }
  134. $prefix = '';
  135. while (!$prefix) {
  136. $prefix = $this->in(__d('cake_console', 'Table Prefix?'), null, 'n');
  137. }
  138. if (strtolower($prefix) === 'n') {
  139. $prefix = null;
  140. }
  141. $encoding = '';
  142. while (!$encoding) {
  143. $encoding = $this->in(__d('cake_console', 'Table encoding?'), null, 'n');
  144. }
  145. if (strtolower($encoding) === 'n') {
  146. $encoding = null;
  147. }
  148. $schema = '';
  149. if ($datasource === 'postgres') {
  150. while (!$schema) {
  151. $schema = $this->in(__d('cake_console', 'Table schema?'), null, 'n');
  152. }
  153. }
  154. if (strtolower($schema) === 'n') {
  155. $schema = null;
  156. }
  157. $config = compact('name', 'datasource', 'persistent', 'host', 'login', 'password', 'database', 'prefix', 'encoding', 'port', 'schema');
  158. while (!$this->_verify($config)) {
  159. $this->_interactive();
  160. }
  161. $dbConfigs[] = $config;
  162. $doneYet = $this->in(__d('cake_console', 'Do you wish to add another database configuration?'), null, 'n');
  163. if (strtolower($doneYet === 'n')) {
  164. $done = true;
  165. }
  166. }
  167. $this->bake($dbConfigs);
  168. config('database');
  169. return true;
  170. }
  171. /**
  172. * Output verification message and bake if it looks good
  173. *
  174. * @param array $config
  175. * @return boolean True if user says it looks good, false otherwise
  176. */
  177. protected function _verify($config) {
  178. $config = array_merge($this->_defaultConfig, $config);
  179. extract($config);
  180. $this->out();
  181. $this->hr();
  182. $this->out(__d('cake_console', 'The following database configuration will be created:'));
  183. $this->hr();
  184. $this->out(__d('cake_console', "Name: %s", $name));
  185. $this->out(__d('cake_console', "Datasource: %s", $datasource));
  186. $this->out(__d('cake_console', "Persistent: %s", $persistent));
  187. $this->out(__d('cake_console', "Host: %s", $host));
  188. if ($port) {
  189. $this->out(__d('cake_console', "Port: %s", $port));
  190. }
  191. $this->out(__d('cake_console', "User: %s", $login));
  192. $this->out(__d('cake_console', "Pass: %s", str_repeat('*', strlen($password))));
  193. $this->out(__d('cake_console', "Database: %s", $database));
  194. if ($prefix) {
  195. $this->out(__d('cake_console', "Table prefix: %s", $prefix));
  196. }
  197. if ($schema) {
  198. $this->out(__d('cake_console', "Schema: %s", $schema));
  199. }
  200. if ($encoding) {
  201. $this->out(__d('cake_console', "Encoding: %s", $encoding));
  202. }
  203. $this->hr();
  204. $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y');
  205. if (strtolower($looksGood) === 'y') {
  206. return $config;
  207. }
  208. return false;
  209. }
  210. /**
  211. * Assembles and writes database.php
  212. *
  213. * @param array $configs Configuration settings to use
  214. * @return boolean Success
  215. */
  216. public function bake($configs) {
  217. if (!is_dir($this->path)) {
  218. $this->err(__d('cake_console', '%s not found', $this->path));
  219. return false;
  220. }
  221. $filename = $this->path . 'database.php';
  222. $oldConfigs = array();
  223. if (file_exists($filename)) {
  224. config('database');
  225. $db = new $this->databaseClassName;
  226. $temp = get_class_vars(get_class($db));
  227. foreach ($temp as $configName => $info) {
  228. $info = array_merge($this->_defaultConfig, $info);
  229. if (!isset($info['schema'])) {
  230. $info['schema'] = null;
  231. }
  232. if (!isset($info['encoding'])) {
  233. $info['encoding'] = null;
  234. }
  235. if (!isset($info['port'])) {
  236. $info['port'] = null;
  237. }
  238. $info['persistent'] = var_export((bool)$info['persistent'], true);
  239. $oldConfigs[] = array(
  240. 'name' => $configName,
  241. 'datasource' => $info['datasource'],
  242. 'persistent' => $info['persistent'],
  243. 'host' => $info['host'],
  244. 'port' => $info['port'],
  245. 'login' => $info['login'],
  246. 'password' => $info['password'],
  247. 'database' => $info['database'],
  248. 'prefix' => $info['prefix'],
  249. 'schema' => $info['schema'],
  250. 'encoding' => $info['encoding']
  251. );
  252. }
  253. }
  254. foreach ($oldConfigs as $key => $oldConfig) {
  255. foreach ($configs as $config) {
  256. if ($oldConfig['name'] == $config['name']) {
  257. unset($oldConfigs[$key]);
  258. }
  259. }
  260. }
  261. $configs = array_merge($oldConfigs, $configs);
  262. $out = "<?php\n";
  263. $out .= "class DATABASE_CONFIG {\n\n";
  264. foreach ($configs as $config) {
  265. $config = array_merge($this->_defaultConfig, $config);
  266. extract($config);
  267. if (strpos($datasource, 'Database/') === false) {
  268. $datasource = "Database/{$datasource}";
  269. }
  270. $out .= "\tpublic \${$name} = array(\n";
  271. $out .= "\t\t'datasource' => '{$datasource}',\n";
  272. $out .= "\t\t'persistent' => {$persistent},\n";
  273. $out .= "\t\t'host' => '{$host}',\n";
  274. if ($port) {
  275. $out .= "\t\t'port' => {$port},\n";
  276. }
  277. $out .= "\t\t'login' => '{$login}',\n";
  278. $out .= "\t\t'password' => '{$password}',\n";
  279. $out .= "\t\t'database' => '{$database}',\n";
  280. if ($schema) {
  281. $out .= "\t\t'schema' => '{$schema}',\n";
  282. }
  283. if ($prefix) {
  284. $out .= "\t\t'prefix' => '{$prefix}',\n";
  285. }
  286. if ($encoding) {
  287. $out .= "\t\t'encoding' => '{$encoding}'\n";
  288. }
  289. $out .= "\t);\n";
  290. }
  291. $out .= "}\n";
  292. $filename = $this->path . 'database.php';
  293. return $this->createFile($filename, $out);
  294. }
  295. /**
  296. * Get a user specified Connection name
  297. *
  298. * @return void
  299. */
  300. public function getConfig() {
  301. App::uses('ConnectionManager', 'Model');
  302. $configs = ConnectionManager::enumConnectionObjects();
  303. $useDbConfig = key($configs);
  304. if (!is_array($configs) || empty($configs)) {
  305. return $this->execute();
  306. }
  307. $connections = array_keys($configs);
  308. if (count($connections) > 1) {
  309. $useDbConfig = $this->in(__d('cake_console', 'Use Database Config') . ':', $connections, $useDbConfig);
  310. }
  311. return $useDbConfig;
  312. }
  313. /**
  314. * Gets the option parser instance and configures it.
  315. *
  316. * @return ConsoleOptionParser
  317. */
  318. public function getOptionParser() {
  319. $parser = parent::getOptionParser();
  320. $parser->description(
  321. __d('cake_console', 'Bake new database configuration settings.')
  322. );
  323. return $parser;
  324. }
  325. }