DbConfigTask.php 9.2 KB

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