1: <?php
  2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16: 
 17: 
 18: App::uses('AppShell', 'Console/Command');
 19: 
 20:  21:  22:  23:  24: 
 25: class DbConfigTask extends AppShell {
 26: 
 27:  28:  29:  30:  31: 
 32:     public $path = null;
 33: 
 34:  35:  36:  37:  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:  54:  55:  56:  57:  58: 
 59:     public $databaseClassName = 'DATABASE_CONFIG';
 60: 
 61:  62:  63:  64:  65: 
 66:     public function initialize() {
 67:         $this->path = APP . 'Config' . DS;
 68:     }
 69: 
 70:  71:  72:  73:  74: 
 75:     public function execute() {
 76:         if (empty($this->args)) {
 77:             $this->_interactive();
 78:             return $this->_stop();
 79:         }
 80:     }
 81: 
 82:  83:  84:  85:  86: 
 87:     protected function _interactive() {
 88:         $this->hr();
 89:         $this->out(__d('cake_console', 'Database Configuration:'));
 90:         $this->hr();
 91:         $done = false;
 92:         $dbConfigs = array();
 93: 
 94:         while (!$done) {
 95:             $name = '';
 96: 
 97:             while (!$name) {
 98:                 $name = $this->in(__d('cake_console', "Name:"), null, 'default');
 99:                 if (preg_match('/[^a-z0-9_]/i', $name)) {
100:                     $name = '';
101:                     $this->out(__d('cake_console', 'The name may only contain unaccented latin characters, numbers or underscores'));
102:                 } elseif (preg_match('/^[^a-z_]/i', $name)) {
103:                     $name = '';
104:                     $this->out(__d('cake_console', 'The name must start with an unaccented latin character or an underscore'));
105:                 }
106:             }
107: 
108:             $datasource = $this->in(__d('cake_console', 'Datasource:'), array('Mysql', 'Postgres', 'Sqlite', 'Sqlserver'), 'Mysql');
109: 
110:             $persistent = $this->in(__d('cake_console', 'Persistent Connection?'), array('y', 'n'), 'n');
111:             if (strtolower($persistent) === 'n') {
112:                 $persistent = 'false';
113:             } else {
114:                 $persistent = 'true';
115:             }
116: 
117:             $host = '';
118:             while (!$host) {
119:                 $host = $this->in(__d('cake_console', 'Database Host:'), null, 'localhost');
120:             }
121: 
122:             $port = '';
123:             while (!$port) {
124:                 $port = $this->in(__d('cake_console', 'Port?'), null, 'n');
125:             }
126: 
127:             if (strtolower($port) === 'n') {
128:                 $port = null;
129:             }
130: 
131:             $login = '';
132:             while (!$login) {
133:                 $login = $this->in(__d('cake_console', 'User:'), null, 'root');
134:             }
135:             $password = '';
136:             $blankPassword = false;
137: 
138:             while (!$password && !$blankPassword) {
139:                 $password = $this->in(__d('cake_console', 'Password:'));
140: 
141:                 if (!$password) {
142:                     $blank = $this->in(__d('cake_console', 'The password you supplied was empty. Use an empty password?'), array('y', 'n'), 'n');
143:                     if ($blank === 'y') {
144:                         $blankPassword = true;
145:                     }
146:                 }
147:             }
148: 
149:             $database = '';
150:             while (!$database) {
151:                 $database = $this->in(__d('cake_console', 'Database Name:'), null, 'cake');
152:             }
153: 
154:             $prefix = '';
155:             while (!$prefix) {
156:                 $prefix = $this->in(__d('cake_console', 'Table Prefix?'), null, 'n');
157:             }
158:             if (strtolower($prefix) === 'n') {
159:                 $prefix = null;
160:             }
161: 
162:             $encoding = '';
163:             while (!$encoding) {
164:                 $encoding = $this->in(__d('cake_console', 'Table encoding?'), null, 'n');
165:             }
166:             if (strtolower($encoding) === 'n') {
167:                 $encoding = null;
168:             }
169: 
170:             $schema = '';
171:             if ($datasource === 'postgres') {
172:                 while (!$schema) {
173:                     $schema = $this->in(__d('cake_console', 'Table schema?'), null, 'n');
174:                 }
175:             }
176:             if (strtolower($schema) === 'n') {
177:                 $schema = null;
178:             }
179: 
180:             $config = compact('name', 'datasource', 'persistent', 'host', 'login', 'password', 'database', 'prefix', 'encoding', 'port', 'schema');
181: 
182:             while (!$this->_verify($config)) {
183:                 $this->_interactive();
184:             }
185: 
186:             $dbConfigs[] = $config;
187:             $doneYet = $this->in(__d('cake_console', 'Do you wish to add another database configuration?'), null, 'n');
188: 
189:             if (strtolower($doneYet === 'n')) {
190:                 $done = true;
191:             }
192:         }
193: 
194:         $this->bake($dbConfigs);
195:         config('database');
196:         return true;
197:     }
198: 
199: 200: 201: 202: 203: 204: 
205:     protected function _verify($config) {
206:         $config += $this->_defaultConfig;
207:         extract($config);
208:         $this->out();
209:         $this->hr();
210:         $this->out(__d('cake_console', 'The following database configuration will be created:'));
211:         $this->hr();
212:         $this->out(__d('cake_console', "Name:         %s", $name));
213:         $this->out(__d('cake_console', "Datasource:   %s", $datasource));
214:         $this->out(__d('cake_console', "Persistent:   %s", $persistent));
215:         $this->out(__d('cake_console', "Host:         %s", $host));
216: 
217:         if ($port) {
218:             $this->out(__d('cake_console', "Port:         %s", $port));
219:         }
220: 
221:         $this->out(__d('cake_console', "User:         %s", $login));
222:         $this->out(__d('cake_console', "Pass:         %s", str_repeat('*', strlen($password))));
223:         $this->out(__d('cake_console', "Database:     %s", $database));
224: 
225:         if ($prefix) {
226:             $this->out(__d('cake_console', "Table prefix: %s", $prefix));
227:         }
228: 
229:         if ($schema) {
230:             $this->out(__d('cake_console', "Schema:       %s", $schema));
231:         }
232: 
233:         if ($encoding) {
234:             $this->out(__d('cake_console', "Encoding:     %s", $encoding));
235:         }
236: 
237:         $this->hr();
238:         $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y');
239: 
240:         if (strtolower($looksGood) === 'y') {
241:             return $config;
242:         }
243:         return false;
244:     }
245: 
246: 247: 248: 249: 250: 251: 
252:     public function bake($configs) {
253:         if (!is_dir($this->path)) {
254:             $this->err(__d('cake_console', '%s not found', $this->path));
255:             return false;
256:         }
257: 
258:         $filename = $this->path . 'database.php';
259:         $oldConfigs = array();
260: 
261:         if (file_exists($filename)) {
262:             config('database');
263:             $db = new $this->databaseClassName;
264:             $temp = get_class_vars(get_class($db));
265: 
266:             foreach ($temp as $configName => $info) {
267:                 $info += $this->_defaultConfig;
268: 
269:                 if (!isset($info['schema'])) {
270:                     $info['schema'] = null;
271:                 }
272:                 if (!isset($info['encoding'])) {
273:                     $info['encoding'] = null;
274:                 }
275:                 if (!isset($info['port'])) {
276:                     $info['port'] = null;
277:                 }
278: 
279:                 $info['persistent'] = var_export((bool)$info['persistent'], true);
280: 
281:                 $oldConfigs[] = array(
282:                     'name' => $configName,
283:                     'datasource' => $info['datasource'],
284:                     'persistent' => $info['persistent'],
285:                     'host' => $info['host'],
286:                     'port' => $info['port'],
287:                     'login' => $info['login'],
288:                     'password' => $info['password'],
289:                     'database' => $info['database'],
290:                     'prefix' => $info['prefix'],
291:                     'schema' => $info['schema'],
292:                     'encoding' => $info['encoding']
293:                 );
294:             }
295:         }
296: 
297:         foreach ($oldConfigs as $key => $oldConfig) {
298:             foreach ($configs as $config) {
299:                 if ($oldConfig['name'] === $config['name']) {
300:                     unset($oldConfigs[$key]);
301:                 }
302:             }
303:         }
304: 
305:         $configs = array_merge($oldConfigs, $configs);
306:         $out = "<?php\n";
307:         $out .= "class DATABASE_CONFIG {\n\n";
308: 
309:         foreach ($configs as $config) {
310:             $config += $this->_defaultConfig;
311:             extract($config);
312: 
313:             if (strpos($datasource, 'Database/') === false) {
314:                 $datasource = "Database/{$datasource}";
315:             }
316:             $out .= "\tpublic \${$name} = array(\n";
317:             $out .= "\t\t'datasource' => '{$datasource}',\n";
318:             $out .= "\t\t'persistent' => {$persistent},\n";
319:             $out .= "\t\t'host' => '{$host}',\n";
320: 
321:             if ($port) {
322:                 $out .= "\t\t'port' => {$port},\n";
323:             }
324: 
325:             $out .= "\t\t'login' => '{$login}',\n";
326:             $out .= "\t\t'password' => '{$password}',\n";
327:             $out .= "\t\t'database' => '{$database}',\n";
328: 
329:             if ($schema) {
330:                 $out .= "\t\t'schema' => '{$schema}',\n";
331:             }
332: 
333:             if ($prefix) {
334:                 $out .= "\t\t'prefix' => '{$prefix}',\n";
335:             }
336: 
337:             if ($encoding) {
338:                 $out .= "\t\t'encoding' => '{$encoding}'\n";
339:             }
340: 
341:             $out .= "\t);\n";
342:         }
343: 
344:         $out .= "}\n";
345:         $filename = $this->path . 'database.php';
346:         return $this->createFile($filename, $out);
347:     }
348: 
349: 350: 351: 352: 353: 
354:     public function getConfig() {
355:         App::uses('ConnectionManager', 'Model');
356:         $configs = ConnectionManager::enumConnectionObjects();
357: 
358:         $useDbConfig = key($configs);
359:         if (!is_array($configs) || empty($configs)) {
360:             return $this->execute();
361:         }
362:         $connections = array_keys($configs);
363: 
364:         if (count($connections) > 1) {
365:             $useDbConfig = $this->in(__d('cake_console', 'Use Database Config') . ':', $connections, $useDbConfig);
366:         }
367:         return $useDbConfig;
368:     }
369: 
370: 371: 372: 373: 374: 
375:     public function getOptionParser() {
376:         $parser = parent::getOptionParser();
377: 
378:         $parser->description(
379:             __d('cake_console', 'Bake new database configuration settings.')
380:         );
381: 
382:         return $parser;
383:     }
384: 
385: }
386: