source: Dev/branches/cakephp/cake/console/libs/console.php @ 126

Last change on this file since 126 was 126, checked in by fpvanagthoven, 14 years ago

Cakephp branch.

File size: 10.8 KB
Line 
1<?php
2/**
3 * CakePHP Console Shell
4 *
5 * PHP versions 4 and 5
6 *
7 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8 * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
9 *
10 * Licensed under The MIT License
11 * Redistributions of files must retain the above copyright notice.
12 *
13 * @copyright     Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
14 * @link          http://cakephp.org CakePHP(tm) Project
15 * @package       cake
16 * @subpackage    cake.cake.console.libs
17 * @since         CakePHP(tm) v 1.2.0.5012
18 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
19 */
20
21/**
22 * @package       cake
23 * @subpackage    cake.cake.console.libs
24 */
25class ConsoleShell extends Shell {
26
27/**
28 * Available binding types
29 *
30 * @var array
31 * @access public
32 */
33        var $associations = array('hasOne', 'hasMany', 'belongsTo', 'hasAndBelongsToMany');
34
35/**
36 * Chars that describe invalid commands
37 *
38 * @var array
39 * @access public
40 */
41        var $badCommandChars = array('$', ';');
42
43/**
44 * Available models
45 *
46 * @var array
47 * @access public
48 */
49        var $models = array();
50
51/**
52 * Override intialize of the Shell
53 *
54 * @access public
55 */
56        function initialize() {
57                require_once CAKE . 'dispatcher.php';
58                $this->Dispatcher = new Dispatcher();
59                $this->models = App::objects('model');
60                App::import('Model', $this->models);
61
62                foreach ($this->models as $model) {
63                        $class = Inflector::camelize(str_replace('.php', '', $model));
64                        $this->models[$model] = $class;
65                        $this->{$class} =& new $class();
66                }
67                $this->out('Model classes:');
68                $this->out('--------------');
69
70                foreach ($this->models as $model) {
71                        $this->out(" - {$model}");
72                }
73                $this->_loadRoutes();
74        }
75
76/**
77 * Prints the help message
78 *
79 * @access public
80 */
81        function help() {
82                $out  = 'Console help:';
83                $out .= '-------------';
84                $out .= 'The interactive console is a tool for testing parts of your app before you';
85                $out .= 'write code.';
86                $out .= "\n";
87                $out .= 'Model testing:';
88                $out .= 'To test model results, use the name of your model without a leading $';
89                $out .= 'e.g. Foo->find("all")';
90                $out .= "\n";
91                $out .= 'To dynamically set associations, you can do the following:';
92                $out .= "\tModelA bind <association> ModelB";
93                $out .= "where the supported assocations are hasOne, hasMany, belongsTo, hasAndBelongsToMany";
94                $out .= "\n";
95                $out .= 'To dynamically remove associations, you can do the following:';
96                $out .= "\t ModelA unbind <association> ModelB";
97                $out .= "where the supported associations are the same as above";
98                $out .= "\n";
99                $out .= "To save a new field in a model, you can do the following:";
100                $out .= "\tModelA->save(array('foo' => 'bar', 'baz' => 0))";
101                $out .= "where you are passing a hash of data to be saved in the format";
102                $out .= "of field => value pairs";
103                $out .= "\n";
104                $out .= "To get column information for a model, use the following:";
105                $out .= "\tModelA columns";
106                $out .= "which returns a list of columns and their type";
107                $out .= "\n";
108                $out .= "\n";
109                $out .= 'Route testing:';
110                $out .= "\n";
111                $out .= 'To test URLs against your app\'s route configuration, type:';
112                $out .= "\n";
113                $out .= "\tRoute <url>";
114                $out .= "\n";
115                $out .= "where url is the path to your your action plus any query parameters,";
116                $out .= "minus the application's base path.  For example:";
117                $out .= "\n";
118                $out .= "\tRoute /posts/view/1";
119                $out .= "\n";
120                $out .= "will return something like the following:";
121                $out .= "\n";
122                $out .= "\tarray (";
123                $out .= "\t  [...]";
124                $out .= "\t  'controller' => 'posts',";
125                $out .= "\t  'action' => 'view',";
126                $out .= "\t  [...]";
127                $out .= "\t)";
128                $out .= "\n";
129                $out .= 'Alternatively, you can use simple array syntax to test reverse';
130                $out .= 'To reload your routes config (config/routes.php), do the following:';
131                $out .= "\n";
132                $out .= "\tRoutes reload";
133                $out .= "\n";
134                $out .= 'To show all connected routes, do the following:';
135                $out .= "\tRoutes show";
136                $this->out($out);
137        }
138
139/**
140 * Override main() to handle action
141 *
142 * @access public
143 */
144        function main($command = null) {
145                while (true) {
146                        if (empty($command)) {
147                                $command = trim($this->in(''));
148                        }
149
150                        switch ($command) {
151                                case 'help':
152                                        $this->help();
153                                break;
154                                case 'quit':
155                                case 'exit':
156                                        return true;
157                                break;
158                                case 'models':
159                                        $this->out('Model classes:');
160                                        $this->hr();
161                                        foreach ($this->models as $model) {
162                                                $this->out(" - {$model}");
163                                        }
164                                break;
165                                case (preg_match("/^(\w+) bind (\w+) (\w+)/", $command, $tmp) == true):
166                                        foreach ($tmp as $data) {
167                                                $data = strip_tags($data);
168                                                $data = str_replace($this->badCommandChars, "", $data);
169                                        }
170
171                                        $modelA = $tmp[1];
172                                        $association = $tmp[2];
173                                        $modelB = $tmp[3];
174
175                                        if ($this->_isValidModel($modelA) && $this->_isValidModel($modelB) && in_array($association, $this->associations)) {
176                                                $this->{$modelA}->bindModel(array($association => array($modelB => array('className' => $modelB))), false);
177                                                $this->out("Created $association association between $modelA and $modelB");
178                                        } else {
179                                                $this->out("Please verify you are using valid models and association types");
180                                        }
181                                break;
182                                case (preg_match("/^(\w+) unbind (\w+) (\w+)/", $command, $tmp) == true):
183                                        foreach ($tmp as $data) {
184                                                $data = strip_tags($data);
185                                                $data = str_replace($this->badCommandChars, "", $data);
186                                        }
187
188                                        $modelA = $tmp[1];
189                                        $association = $tmp[2];
190                                        $modelB = $tmp[3];
191
192                                        // Verify that there is actually an association to unbind
193                                        $currentAssociations = $this->{$modelA}->getAssociated();
194                                        $validCurrentAssociation = false;
195
196                                        foreach ($currentAssociations as $model => $currentAssociation) {
197                                                if ($model == $modelB && $association == $currentAssociation) {
198                                                        $validCurrentAssociation = true;
199                                                }
200                                        }
201
202                                        if ($this->_isValidModel($modelA) && $this->_isValidModel($modelB) && in_array($association, $this->associations) && $validCurrentAssociation) {
203                                                $this->{$modelA}->unbindModel(array($association => array($modelB)));
204                                                $this->out("Removed $association association between $modelA and $modelB");
205                                        } else {
206                                                $this->out("Please verify you are using valid models, valid current association, and valid association types");
207                                        }
208                                break;
209                                case (strpos($command, "->find") > 0):
210                                        // Remove any bad info
211                                        $command = strip_tags($command);
212                                        $command = str_replace($this->badCommandChars, "", $command);
213
214                                        // Do we have a valid model?
215                                        list($modelToCheck, $tmp) = explode('->', $command);
216
217                                        if ($this->_isValidModel($modelToCheck)) {
218                                                $findCommand = "\$data = \$this->$command;";
219                                                @eval($findCommand);
220
221                                                if (is_array($data)) {
222                                                        foreach ($data as $idx => $results) {
223                                                                if (is_numeric($idx)) { // findAll() output
224                                                                        foreach ($results as $modelName => $result) {
225                                                                                $this->out("$modelName");
226
227                                                                                foreach ($result as $field => $value) {
228                                                                                        if (is_array($value)) {
229                                                                                                foreach ($value as $field2 => $value2) {
230                                                                                                        $this->out("\t$field2: $value2");
231                                                                                                }
232
233                                                                                                $this->out();
234                                                                                        } else {
235                                                                                                $this->out("\t$field: $value");
236                                                                                        }
237                                                                                }
238                                                                        }
239                                                                } else { // find() output
240                                                                        $this->out($idx);
241
242                                                                        foreach ($results as $field => $value) {
243                                                                                if (is_array($value)) {
244                                                                                        foreach ($value as $field2 => $value2) {
245                                                                                                $this->out("\t$field2: $value2");
246                                                                                        }
247
248                                                                                        $this->out();
249                                                                                } else {
250                                                                                        $this->out("\t$field: $value");
251                                                                                }
252                                                                        }
253                                                                }
254                                                        }
255                                                } else {
256                                                        $this->out("\nNo result set found");
257                                                }
258                                        } else {
259                                                $this->out("$modelToCheck is not a valid model");
260                                        }
261
262                                break;
263                                case (strpos($command, '->save') > 0):
264                                        // Validate the model we're trying to save here
265                                        $command = strip_tags($command);
266                                        $command = str_replace($this->badCommandChars, "", $command);
267                                        list($modelToSave, $tmp) = explode("->", $command);
268
269                                        if ($this->_isValidModel($modelToSave)) {
270                                                // Extract the array of data we are trying to build
271                                                list($foo, $data) = explode("->save", $command);
272                                                $data = preg_replace('/^\(*(array)?\(*(.+?)\)*$/i', '\\2', $data);
273                                                $saveCommand = "\$this->{$modelToSave}->save(array('{$modelToSave}' => array({$data})));";
274                                                @eval($saveCommand);
275                                                $this->out('Saved record for ' . $modelToSave);
276                                        }
277                                break;
278                                case (preg_match("/^(\w+) columns/", $command, $tmp) == true):
279                                        $modelToCheck = strip_tags(str_replace($this->badCommandChars, "", $tmp[1]));
280
281                                        if ($this->_isValidModel($modelToCheck)) {
282                                                // Get the column info for this model
283                                                $fieldsCommand = "\$data = \$this->{$modelToCheck}->getColumnTypes();";
284                                                @eval($fieldsCommand);
285
286                                                if (is_array($data)) {
287                                                        foreach ($data as $field => $type) {
288                                                                $this->out("\t{$field}: {$type}");
289                                                        }
290                                                }
291                                        } else {
292                                                $this->out("Please verify that you selected a valid model");
293                                        }
294                                break;
295                                case (preg_match("/^routes\s+reload/i", $command, $tmp) == true):
296                                        $router =& Router::getInstance();
297                                        if (!$this->_loadRoutes()) {
298                                                $this->out("There was an error loading the routes config.  Please check that the file");
299                                                $this->out("exists and is free of parse errors.");
300                                                break;
301                                        }
302                                        $this->out("Routes configuration reloaded, " . count($router->routes) . " routes connected");
303                                break;
304                                case (preg_match("/^routes\s+show/i", $command, $tmp) == true):
305                                        $router =& Router::getInstance();
306                                        $this->out(implode("\n", Set::extract($router->routes, '{n}.0')));
307                                break;
308                                case (preg_match("/^route\s+(\(.*\))$/i", $command, $tmp) == true):
309                                        if ($url = eval('return array' . $tmp[1] . ';')) {
310                                                $this->out(Router::url($url));
311                                        }
312                                break;
313                                case (preg_match("/^route\s+(.*)/i", $command, $tmp) == true):
314                                        $this->out(var_export(Router::parse($tmp[1]), true));
315                                break;
316                                default:
317                                        $this->out("Invalid command\n");
318                                break;
319                        }
320                        $command = '';
321                }
322        }
323
324/**
325 * Tells if the specified model is included in the list of available models
326 *
327 * @param string $modelToCheck
328 * @return boolean true if is an available model, false otherwise
329 * @access protected
330 */
331        function _isValidModel($modelToCheck) {
332                return in_array($modelToCheck, $this->models);
333        }
334
335/**
336 * Reloads the routes configuration from config/routes.php, and compiles
337 * all routes found
338 *
339 * @return boolean True if config reload was a success, otherwise false
340 * @access protected
341 */
342        function _loadRoutes() {
343                $router =& Router::getInstance();
344
345                $router->reload();
346                extract($router->getNamedExpressions());
347
348                if (!@include(CONFIGS . 'routes.php')) {
349                        return false;
350                }
351                $router->parse('/');
352
353                foreach (array_keys($router->getNamedExpressions()) as $var) {
354                        unset(${$var});
355                }
356                for ($i = 0, $len = count($router->routes); $i < $len; $i++) {
357                        $router->routes[$i]->compile();
358                }
359                return true;
360        }
361}
Note: See TracBrowser for help on using the repository browser.