params['dry-run']) { $this->out('Dry-run mode enabled!', 1, Shell::QUIET); } } function all() { foreach($this->OptionParser->subcommands() as $command) { $name = $command->name(); if ($name === 'all') { continue; } $this->out('Running ' . $name); $this->$name(); } } /** * Update helpers. * * - Converts helpers usage to new format. * * @return void */ function helpers() { $this->_paths = array_diff(App::path('views'), App::core('views')); if (!empty($this->params['plugin'])) { $this->_paths = array(App::pluginPath($this->params['plugin']) . 'views' . DS); } $patterns = array(); $helpers = App::objects('helper'); $plugins = App::objects('plugin'); $pluginHelpers = array(); foreach ($plugins as $plugin) { $pluginHelpers = array_merge( $pluginHelpers, App::objects('helper', App::pluginPath($plugin) . DS . 'views' . DS . 'helpers' . DS, false) ); } $helpers = array_merge($pluginHelpers, $helpers); foreach ($helpers as $helper) { $oldHelper = strtolower(substr($helper, 0, 1)).substr($helper, 1); $patterns[] = array( "\${$oldHelper} to \$this->{$helper}", "/\\\${$oldHelper}->/", "\\\$this->{$helper}->" ); } $this->_filesRegexpUpdate($patterns); } /** * Update i18n. * * - Removes extra true param. * - Add the echo to __*() calls that didn't need them before. * * @return void */ function i18n() { $this->_paths = array( APP ); if (!empty($this->params['plugin'])) { $this->_paths = array(App::pluginPath($this->params['plugin'])); } $patterns = array( array( '_filesRegexpUpdate($patterns); } /** * Upgrade the removed basics functions. * * - a(*) -> array(*) * - e(*) -> echo * * - ife(*, *, *) -> empty(*) ? * : * * - a(*) -> array(*) * - r(*, *, *) -> str_replace(*, *, *) * - up(*) -> strtoupper(*) * - low(*, *, *) -> strtolower(*) * - getMicrotime() -> microtime(true) * * @return void */ public function basics() { $this->_paths = array( APP ); if (!empty($this->params['plugin'])) { $this->_paths = array(App::pluginPath($this->params['plugin'])); } $patterns = array( array( 'a(*) -> array(*)', '/\ba\((.*)\)/', 'array(\1)' ), array( 'e(*) -> echo *', '/\be\((.*)\)/', 'echo \1' ), array( 'ife(*, *, *) -> empty(*) ? * : *', '/ife\((.*), (.*), (.*)\)/', 'empty(\1) ? \2 : \3' ), array( 'r(*, *, *) -> str_replace(*, *, *)', '/\br\(/', 'str_replace(' ), array( 'up(*) -> strtoupper(*)', '/\bup\(/', 'strtoupper(' ), array( 'low(*) -> strtolower(*)', '/\blow\(/', 'strtolower(' ), array( 'getMicrotime() -> microtime(true)', '/getMicrotime\(\)/', 'microtime(true)' ), ); $this->_filesRegexpUpdate($patterns); } /** * Update the properties moved to CakeRequest. * * @return void */ public function request() { $views = array_diff(App::path('views'), App::core('views')); $controllers = array_diff(App::path('controllers'), App::core('controllers'), array(APP)); $components = array_diff(App::path('components'), App::core('components')); $this->_paths = array_merge($views, $controllers, $components); if (!empty($this->params['plugin'])) { $pluginPath = App::pluginPath($this->params['plugin']); $this->_paths = array( $pluginPath . 'controllers' . DS, $pluginPath . 'controllers' . DS . 'components' .DS, $pluginPath . 'views' . DS, ); } $patterns = array( array( '$this->data -> $this->request->data', '/(\$this->data\b(?!\())/', '$this->request->data' ), array( '$this->params -> $this->request->params', '/(\$this->params\b(?!\())/', '$this->request->params' ), array( '$this->webroot -> $this->request->webroot', '/(\$this->webroot\b(?!\())/', '$this->request->webroot' ), array( '$this->base -> $this->request->base', '/(\$this->base\b(?!\())/', '$this->request->base' ), array( '$this->here -> $this->request->here', '/(\$this->here\b(?!\())/', '$this->request->here' ), array( '$this->action -> $this->request->action', '/(\$this->action\b(?!\())/', '$this->request->action' ), ); $this->_filesRegexpUpdate($patterns); } /** * Update Configure::read() calls with no params. * * @return void */ public function configure() { $this->_paths = array( APP ); if (!empty($this->params['plugin'])) { $this->_paths = array(App::pluginPath($this->params['plugin'])); } $patterns = array( array( "Configure::read() -> Configure::read('debug')", '/Configure::read\(\)/', 'Configure::read(\'debug\')' ), ); $this->_filesRegexpUpdate($patterns); } /** * Updates files based on regular expressions. * * @param array $patterns Array of search and replacement patterns. * @return void */ protected function _filesRegexpUpdate($patterns) { $this->_findFiles($this->params['ext']); foreach ($this->_files as $file) { $this->out('Updating ' . $file . '...', 1, Shell::VERBOSE); $this->_updateFile($file, $patterns); } } /** * Searches the paths and finds files based on extension. * * @param string $extensions * @return void */ protected function _findFiles($extensions = '') { foreach ($this->_paths as $path) { if (!is_dir($path)) { continue; } $files = array(); $Iterator = new RegexIterator( new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)), '/^.+\.(' . $extensions . ')$/i', RegexIterator::MATCH ); foreach ($Iterator as $file) { if ($file->isFile()) { $files[] = $file->getPathname(); } } $this->_files = array_merge($this->_files, $files); } } /** * Update a single file. * * @param string $file The file to update * @param array $patterns The replacement patterns to run. * @return void */ protected function _updateFile($file, $patterns) { $contents = file_get_contents($file); foreach ($patterns as $pattern) { $this->out(' * Updating ' . $pattern[0], 1, Shell::VERBOSE); $contents = preg_replace($pattern[1], $pattern[2], $contents); } $this->out('Done updating ' . $file, 1); if (!$this->params['dry-run']) { file_put_contents($file, $contents); } } /** * get the option parser * * @return ConsoleOptionParser */ function getOptionParser() { $subcommandParser = array( 'options' => array( 'plugin' => array( 'short' => 'p', 'help' => __('The plugin to update. Only the specified plugin will be updated.' )), 'ext' => array( 'short' => 'e', 'help' => __('The extension(s) to search. A pipe delimited list, or a preg_match compatible subpattern'), 'default' => 'php|ctp|thtml|inc|tpl' ), 'dry-run'=> array( 'short' => 'd', 'help' => __('Dry run the update, no files will actually be modified.'), 'boolean' => true ) ) ); return parent::getOptionParser() ->description("A shell to help automate upgrading from CakePHP 1.3 to 2.0. \n" . "Be sure to have a backup of your application before running these commands.") ->addSubcommand('all', array( 'help' => 'Run all upgrade commands.', 'parser' => $subcommandParser )) ->addSubcommand('i18n', array( 'help' => 'Update the i18n translation method calls.', 'parser' => $subcommandParser )) ->addSubcommand('helpers', array( 'help' => 'Update calls to helpers.', 'parser' => $subcommandParser )) ->addSubcommand('basics', array( 'help' => 'Update removed basics functions to PHP native functions.', 'parser' => $subcommandParser )) ->addSubcommand('request', array( 'help' => 'Update removed request access, and replace with $this->request.', 'parser' => $subcommandParser )) ->addSubcommand('configure', array( 'help' => "Update Configure::read() to Configure::read('debug')", 'parser' => $subcommandParser )); } }