Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
13532 anikendra 1
<?php
2
/**
3
 * Upgrade Shell
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
 * @package       Cake.Console.Command
15
 * @since         CakePHP(tm) v 2.0
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18
 
19
App::uses('AppShell', 'Console/Command');
20
App::uses('Folder', 'Utility');
21
 
22
/**
23
 * A shell class to help developers upgrade applications to CakePHP 2.0
24
 *
25
 * @package       Cake.Console.Command
26
 */
27
class UpgradeShell extends AppShell {
28
 
29
/**
30
 * Files
31
 *
32
 * @var array
33
 */
34
	protected $_files = array();
35
 
36
/**
37
 * Paths
38
 *
39
 * @var array
40
 */
41
	protected $_paths = array();
42
 
43
/**
44
 * Map
45
 *
46
 * @var array
47
 */
48
	protected $_map = array(
49
		'Controller' => 'Controller',
50
		'Component' => 'Controller/Component',
51
		'Model' => 'Model',
52
		'Behavior' => 'Model/Behavior',
53
		'Datasource' => 'Model/Datasource',
54
		'Dbo' => 'Model/Datasource/Database',
55
		'View' => 'View',
56
		'Helper' => 'View/Helper',
57
		'Shell' => 'Console/Command',
58
		'Task' => 'Console/Command/Task',
59
		'Case' => 'Test/Case',
60
		'Fixture' => 'Test/Fixture',
61
		'Error' => 'Lib/Error',
62
	);
63
 
64
/**
65
 * Shell startup, prints info message about dry run.
66
 *
67
 * @return void
68
 */
69
	public function startup() {
70
		parent::startup();
71
		if ($this->params['dry-run']) {
72
			$this->out(__d('cake_console', '<warning>Dry-run mode enabled!</warning>'), 1, Shell::QUIET);
73
		}
74
		if ($this->params['git'] && !is_dir('.git')) {
75
			$this->out(__d('cake_console', '<warning>No git repository detected!</warning>'), 1, Shell::QUIET);
76
		}
77
	}
78
 
79
/**
80
 * Run all upgrade steps one at a time
81
 *
82
 * @return void
83
 */
84
	public function all() {
85
		foreach ($this->OptionParser->subcommands() as $command) {
86
			$name = $command->name();
87
			if ($name === 'all') {
88
				continue;
89
			}
90
			$this->out(__d('cake_console', 'Running %s', $name));
91
			$this->$name();
92
		}
93
	}
94
 
95
/**
96
 * Update tests.
97
 *
98
 * - Update tests class names to FooTest rather than FooTestCase.
99
 *
100
 * @return void
101
 */
102
	public function tests() {
103
		$this->_paths = array(APP . 'tests' . DS);
104
		if (!empty($this->params['plugin'])) {
105
			$this->_paths = array(App::pluginPath($this->params['plugin']) . 'tests' . DS);
106
		}
107
		$patterns = array(
108
			array(
109
				'*TestCase extends CakeTestCase to *Test extends CakeTestCase',
110
				'/([a-zA-Z]*Test)Case extends CakeTestCase/',
111
				'\1 extends CakeTestCase'
112
			),
113
		);
114
 
115
		$this->_filesRegexpUpdate($patterns);
116
	}
117
 
118
/**
119
 * Move files and folders to their new homes
120
 *
121
 * Moves folders containing files which cannot necessarily be auto-detected (libs and templates)
122
 * and then looks for all php files except vendors, and moves them to where Cake 2.0 expects
123
 * to find them.
124
 *
125
 * @return void
126
 */
127
	public function locations() {
128
		$cwd = getcwd();
129
 
130
		if (!empty($this->params['plugin'])) {
131
			chdir(App::pluginPath($this->params['plugin']));
132
		}
133
 
134
		if (is_dir('plugins')) {
135
			$Folder = new Folder('plugins');
136
			list($plugins) = $Folder->read();
137
			foreach ($plugins as $plugin) {
138
				chdir($cwd . DS . 'plugins' . DS . $plugin);
139
				$this->out(__d('cake_console', 'Upgrading locations for plugin %s', $plugin));
140
				$this->locations();
141
			}
142
			$this->_files = array();
143
			chdir($cwd);
144
			$this->out(__d('cake_console', 'Upgrading locations for app directory'));
145
		}
146
		$moves = array(
147
			'config' => 'Config',
148
			'Config' . DS . 'schema' => 'Config' . DS . 'Schema',
149
			'libs' => 'Lib',
150
			'tests' => 'Test',
151
			'views' => 'View',
152
			'models' => 'Model',
153
			'Model' . DS . 'behaviors' => 'Model' . DS . 'Behavior',
154
			'Model' . DS . 'datasources' => 'Model' . DS . 'Datasource',
155
			'Test' . DS . 'cases' => 'Test' . DS . 'Case',
156
			'Test' . DS . 'fixtures' => 'Test' . DS . 'Fixture',
157
			'vendors' . DS . 'shells' . DS . 'templates' => 'Console' . DS . 'Templates',
158
		);
159
		foreach ($moves as $old => $new) {
160
			if (is_dir($old)) {
161
				$this->out(__d('cake_console', 'Moving %s to %s', $old, $new));
162
				if (!$this->params['dry-run']) {
163
					if ($this->params['git']) {
164
						exec('git mv -f ' . escapeshellarg($old) . ' ' . escapeshellarg($old . '__'));
165
						exec('git mv -f ' . escapeshellarg($old . '__') . ' ' . escapeshellarg($new));
166
					} else {
167
						$Folder = new Folder($old);
168
						$Folder->move($new);
169
					}
170
				}
171
			}
172
		}
173
 
174
		$this->_moveViewFiles();
175
		$this->_moveAppClasses();
176
 
177
		$sourceDirs = array(
178
			'.' => array('recursive' => false),
179
			'Console',
180
			'controllers',
181
			'Controller',
182
			'Lib' => array('checkFolder' => false),
183
			'models',
184
			'Model',
185
			'tests',
186
			'Test' => array('regex' => '@class (\S*Test) extends CakeTestCase@'),
187
			'views',
188
			'View',
189
			'vendors/shells',
190
		);
191
 
192
		$defaultOptions = array(
193
			'recursive' => true,
194
			'checkFolder' => true,
195
			'regex' => '@class (\S*) .*(\s|\v)*{@i'
196
		);
197
		foreach ($sourceDirs as $dir => $options) {
198
			if (is_numeric($dir)) {
199
				$dir = $options;
200
				$options = array();
201
			}
202
			$options = array_merge($defaultOptions, $options);
203
			$this->_movePhpFiles($dir, $options);
204
		}
205
	}
206
 
207
/**
208
 * Update helpers.
209
 *
210
 * - Converts helpers usage to new format.
211
 *
212
 * @return void
213
 */
214
	public function helpers() {
215
		$this->_paths = array_diff(App::path('views'), App::core('views'));
216
 
217
		if (!empty($this->params['plugin'])) {
218
			$this->_paths = array(App::pluginPath($this->params['plugin']) . 'views' . DS);
219
		}
220
 
221
		$patterns = array();
222
		App::build(array(
223
			'View/Helper' => App::core('View/Helper'),
224
		), App::APPEND);
225
		$helpers = App::objects('helper');
226
		$plugins = App::objects('plugin');
227
		$pluginHelpers = array();
228
		foreach ($plugins as $plugin) {
229
			CakePlugin::load($plugin);
230
			$pluginHelpers = array_merge(
231
				$pluginHelpers,
232
				App::objects('helper', App::pluginPath($plugin) . DS . 'views' . DS . 'helpers' . DS, false)
233
			);
234
		}
235
		$helpers = array_merge($pluginHelpers, $helpers);
236
		foreach ($helpers as $helper) {
237
			$helper = preg_replace('/Helper$/', '', $helper);
238
			$oldHelper = $helper;
239
			$oldHelper{0} = strtolower($oldHelper{0});
240
			$patterns[] = array(
241
				"\${$oldHelper} to \$this->{$helper}",
242
				"/\\\${$oldHelper}->/",
243
				"\\\$this->{$helper}->"
244
			);
245
		}
246
 
247
		$this->_filesRegexpUpdate($patterns);
248
	}
249
 
250
/**
251
 * Update i18n.
252
 *
253
 * - Removes extra true param.
254
 * - Add the echo to __*() calls that didn't need them before.
255
 *
256
 * @return void
257
 */
258
	public function i18n() {
259
		$this->_paths = array(
260
			APP
261
		);
262
		if (!empty($this->params['plugin'])) {
263
			$this->_paths = array(App::pluginPath($this->params['plugin']));
264
		}
265
 
266
		$patterns = array(
267
			array(
268
				'<?php __*(*) to <?php echo __*(*)',
269
				'/<\?php\s*(__[a-z]*\(.*?\))/',
270
				'<?php echo \1'
271
			),
272
			array(
273
				'<?php __*(*, true) to <?php echo __*()',
274
				'/<\?php\s*(__[a-z]*\(.*?)(,\s*true)(\))/',
275
				'<?php echo \1\3'
276
			),
277
			array('__*(*, true) to __*(*)', '/(__[a-z]*\(.*?)(,\s*true)(\))/', '\1\3')
278
		);
279
 
280
		$this->_filesRegexpUpdate($patterns);
281
	}
282
 
283
/**
284
 * Upgrade the removed basics functions.
285
 *
286
 * - a(*) -> array(*)
287
 * - e(*) -> echo *
288
 * - ife(*, *, *) -> !empty(*) ? * : *
289
 * - a(*) -> array(*)
290
 * - r(*, *, *) -> str_replace(*, *, *)
291
 * - up(*) -> strtoupper(*)
292
 * - low(*, *, *) -> strtolower(*)
293
 * - getMicrotime() -> microtime(true)
294
 *
295
 * @return void
296
 */
297
	public function basics() {
298
		$this->_paths = array(
299
			APP
300
		);
301
		if (!empty($this->params['plugin'])) {
302
			$this->_paths = array(App::pluginPath($this->params['plugin']));
303
		}
304
		$patterns = array(
305
			array(
306
				'a(*) -> array(*)',
307
				'/\ba\((.*)\)/',
308
				'array(\1)'
309
			),
310
			array(
311
				'e(*) -> echo *',
312
				'/\be\((.*)\)/',
313
				'echo \1'
314
			),
315
			array(
316
				'ife(*, *, *) -> !empty(*) ? * : *',
317
				'/ife\((.*), (.*), (.*)\)/',
318
				'!empty(\1) ? \2 : \3'
319
			),
320
			array(
321
				'r(*, *, *) -> str_replace(*, *, *)',
322
				'/\br\(/',
323
				'str_replace('
324
			),
325
			array(
326
				'up(*) -> strtoupper(*)',
327
				'/\bup\(/',
328
				'strtoupper('
329
			),
330
			array(
331
				'low(*) -> strtolower(*)',
332
				'/\blow\(/',
333
				'strtolower('
334
			),
335
			array(
336
				'getMicrotime() -> microtime(true)',
337
				'/getMicrotime\(\)/',
338
				'microtime(true)'
339
			),
340
		);
341
		$this->_filesRegexpUpdate($patterns);
342
	}
343
 
344
/**
345
 * Update the properties moved to CakeRequest.
346
 *
347
 * @return void
348
 */
349
	public function request() {
350
		$views = array_diff(App::path('views'), App::core('views'));
351
		$controllers = array_diff(App::path('controllers'), App::core('controllers'), array(APP));
352
		$components = array_diff(App::path('components'), App::core('components'));
353
 
354
		$this->_paths = array_merge($views, $controllers, $components);
355
 
356
		if (!empty($this->params['plugin'])) {
357
			$pluginPath = App::pluginPath($this->params['plugin']);
358
			$this->_paths = array(
359
				$pluginPath . 'controllers' . DS,
360
				$pluginPath . 'controllers' . DS . 'components' . DS,
361
				$pluginPath . 'views' . DS,
362
			);
363
		}
364
		$patterns = array(
365
			array(
366
				'$this->data -> $this->request->data',
367
				'/(\$this->data\b(?!\())/',
368
				'$this->request->data'
369
			),
370
			array(
371
				'$this->params -> $this->request->params',
372
				'/(\$this->params\b(?!\())/',
373
				'$this->request->params'
374
			),
375
			array(
376
				'$this->webroot -> $this->request->webroot',
377
				'/(\$this->webroot\b(?!\())/',
378
				'$this->request->webroot'
379
			),
380
			array(
381
				'$this->base -> $this->request->base',
382
				'/(\$this->base\b(?!\())/',
383
				'$this->request->base'
384
			),
385
			array(
386
				'$this->here -> $this->request->here',
387
				'/(\$this->here\b(?!\())/',
388
				'$this->request->here'
389
			),
390
			array(
391
				'$this->action -> $this->request->action',
392
				'/(\$this->action\b(?!\())/',
393
				'$this->request->action'
394
			),
395
		);
396
		$this->_filesRegexpUpdate($patterns);
397
	}
398
 
399
/**
400
 * Update Configure::read() calls with no params.
401
 *
402
 * @return void
403
 */
404
	public function configure() {
405
		$this->_paths = array(
406
			APP
407
		);
408
		if (!empty($this->params['plugin'])) {
409
			$this->_paths = array(App::pluginPath($this->params['plugin']));
410
		}
411
		$patterns = array(
412
			array(
413
				"Configure::read() -> Configure::read('debug')",
414
				'/Configure::read\(\)/',
415
				'Configure::read(\'debug\')'
416
			),
417
		);
418
		$this->_filesRegexpUpdate($patterns);
419
	}
420
 
421
/**
422
 * constants
423
 *
424
 * @return void
425
 */
426
	public function constants() {
427
		$this->_paths = array(
428
			APP
429
		);
430
		if (!empty($this->params['plugin'])) {
431
			$this->_paths = array(App::pluginPath($this->params['plugin']));
432
		}
433
		$patterns = array(
434
			array(
435
				"LIBS -> CAKE",
436
				'/\bLIBS\b/',
437
				'CAKE'
438
			),
439
			array(
440
				"CONFIGS -> APP . 'Config' . DS",
441
				'/\bCONFIGS\b/',
442
				'APP . \'Config\' . DS'
443
			),
444
			array(
445
				"CONTROLLERS -> APP . 'Controller' . DS",
446
				'/\bCONTROLLERS\b/',
447
				'APP . \'Controller\' . DS'
448
			),
449
			array(
450
				"COMPONENTS -> APP . 'Controller' . DS . 'Component' . DS",
451
				'/\bCOMPONENTS\b/',
452
				'APP . \'Controller\' . DS . \'Component\''
453
			),
454
			array(
455
				"MODELS -> APP . 'Model' . DS",
456
				'/\bMODELS\b/',
457
				'APP . \'Model\' . DS'
458
			),
459
			array(
460
				"BEHAVIORS -> APP . 'Model' . DS . 'Behavior' . DS",
461
				'/\bBEHAVIORS\b/',
462
				'APP . \'Model\' . DS . \'Behavior\' . DS'
463
			),
464
			array(
465
				"VIEWS -> APP . 'View' . DS",
466
				'/\bVIEWS\b/',
467
				'APP . \'View\' . DS'
468
			),
469
			array(
470
				"HELPERS -> APP . 'View' . DS . 'Helper' . DS",
471
				'/\bHELPERS\b/',
472
				'APP . \'View\' . DS . \'Helper\' . DS'
473
			),
474
			array(
475
				"LAYOUTS -> APP . 'View' . DS . 'Layouts' . DS",
476
				'/\bLAYOUTS\b/',
477
				'APP . \'View\' . DS . \'Layouts\' . DS'
478
			),
479
			array(
480
				"ELEMENTS -> APP . 'View' . DS . 'Elements' . DS",
481
				'/\bELEMENTS\b/',
482
				'APP . \'View\' . DS . \'Elements\' . DS'
483
			),
484
			array(
485
				"CONSOLE_LIBS -> CAKE . 'Console' . DS",
486
				'/\bCONSOLE_LIBS\b/',
487
				'CAKE . \'Console\' . DS'
488
			),
489
			array(
490
				"CAKE_TESTS_LIB -> CAKE . 'TestSuite' . DS",
491
				'/\bCAKE_TESTS_LIB\b/',
492
				'CAKE . \'TestSuite\' . DS'
493
			),
494
			array(
495
				"CAKE_TESTS -> CAKE . 'Test' . DS",
496
				'/\bCAKE_TESTS\b/',
497
				'CAKE . \'Test\' . DS'
498
			)
499
		);
500
		$this->_filesRegexpUpdate($patterns);
501
	}
502
 
503
/**
504
 * Update components.
505
 *
506
 * - Make components that extend Object to extend Component.
507
 *
508
 * @return void
509
 */
510
	public function components() {
511
		$this->_paths = App::Path('Controller/Component');
512
		if (!empty($this->params['plugin'])) {
513
			$this->_paths = App::Path('Controller/Component', $this->params['plugin']);
514
		}
515
		$patterns = array(
516
			array(
517
				'*Component extends Object to *Component extends Component',
518
				'/([a-zA-Z]*Component extends) Object/',
519
				'\1 Component'
520
			),
521
		);
522
 
523
		$this->_filesRegexpUpdate($patterns);
524
	}
525
 
526
/**
527
 * Replace cakeError with built-in exceptions.
528
 * NOTE: this ignores calls where you've passed your own secondary parameters to cakeError().
529
 * @return void
530
 */
531
	public function exceptions() {
532
		$controllers = array_diff(App::path('controllers'), App::core('controllers'), array(APP));
533
		$components = array_diff(App::path('components'), App::core('components'));
534
 
535
		$this->_paths = array_merge($controllers, $components);
536
 
537
		if (!empty($this->params['plugin'])) {
538
			$pluginPath = App::pluginPath($this->params['plugin']);
539
			$this->_paths = array(
540
				$pluginPath . 'controllers' . DS,
541
				$pluginPath . 'controllers' . DS . 'components' . DS,
542
			);
543
		}
544
		$patterns = array(
545
			array(
546
				'$this->cakeError("error400") -> throw new BadRequestException()',
547
				'/(\$this->cakeError\(["\']error400["\']\));/',
548
				'throw new BadRequestException();'
549
			),
550
			array(
551
				'$this->cakeError("error404") -> throw new NotFoundException()',
552
				'/(\$this->cakeError\(["\']error404["\']\));/',
553
				'throw new NotFoundException();'
554
			),
555
			array(
556
				'$this->cakeError("error500") -> throw new InternalErrorException()',
557
				'/(\$this->cakeError\(["\']error500["\']\));/',
558
				'throw new InternalErrorException();'
559
			),
560
		);
561
		$this->_filesRegexpUpdate($patterns);
562
	}
563
 
564
/**
565
 * Move application views files to where they now should be
566
 *
567
 * Find all view files in the folder and determine where cake expects the file to be
568
 *
569
 * @return void
570
 */
571
	protected function _moveViewFiles() {
572
		if (!is_dir('View')) {
573
			return;
574
		}
575
 
576
		$dirs = scandir('View');
577
		foreach ($dirs as $old) {
578
			if (!is_dir('View' . DS . $old) || $old === '.' || $old === '..') {
579
				continue;
580
			}
581
 
582
			$new = 'View' . DS . Inflector::camelize($old);
583
			$old = 'View' . DS . $old;
584
			if ($new == $old) {
585
				continue;
586
			}
587
 
588
			$this->out(__d('cake_console', 'Moving %s to %s', $old, $new));
589
			if (!$this->params['dry-run']) {
590
				if ($this->params['git']) {
591
					exec('git mv -f ' . escapeshellarg($old) . ' ' . escapeshellarg($old . '__'));
592
					exec('git mv -f ' . escapeshellarg($old . '__') . ' ' . escapeshellarg($new));
593
				} else {
594
					$Folder = new Folder($old);
595
					$Folder->move($new);
596
				}
597
			}
598
		}
599
	}
600
 
601
/**
602
 * Move the AppController, and AppModel classes.
603
 *
604
 * @return void
605
 */
606
	protected function _moveAppClasses() {
607
		$files = array(
608
			APP . 'app_controller.php' => APP . 'Controller' . DS . 'AppController.php',
609
			APP . 'controllers' . DS . 'app_controller.php' => APP . 'Controller' . DS . 'AppController.php',
610
			APP . 'app_model.php' => APP . 'Model' . DS . 'AppModel.php',
611
			APP . 'models' . DS . 'app_model.php' => APP . 'Model' . DS . 'AppModel.php',
612
		);
613
		foreach ($files as $old => $new) {
614
			if (file_exists($old)) {
615
				$this->out(__d('cake_console', 'Moving %s to %s', $old, $new));
616
 
617
				if ($this->params['dry-run']) {
618
					continue;
619
				}
620
				if ($this->params['git']) {
621
					exec('git mv -f ' . escapeshellarg($old) . ' ' . escapeshellarg($old . '__'));
622
					exec('git mv -f ' . escapeshellarg($old . '__') . ' ' . escapeshellarg($new));
623
				} else {
624
					rename($old, $new);
625
				}
626
			}
627
		}
628
	}
629
 
630
/**
631
 * Move application php files to where they now should be
632
 *
633
 * Find all php files in the folder (honoring recursive) and determine where CakePHP expects the file to be
634
 * If the file is not exactly where CakePHP expects it - move it.
635
 *
636
 * @param string $path
637
 * @param array $options array(recursive, checkFolder)
638
 * @return void
639
 */
640
	protected function _movePhpFiles($path, $options) {
641
		if (!is_dir($path)) {
642
			return;
643
		}
644
 
645
		$paths = $this->_paths;
646
 
647
		$this->_paths = array($path);
648
		$this->_files = array();
649
		if ($options['recursive']) {
650
			$this->_findFiles('php');
651
		} else {
652
			$this->_files = scandir($path);
653
			foreach ($this->_files as $i => $file) {
654
				if (strlen($file) < 5 || substr($file, -4) !== '.php') {
655
					unset($this->_files[$i]);
656
				}
657
			}
658
		}
659
 
660
		$cwd = getcwd();
661
		foreach ($this->_files as &$file) {
662
			$file = $cwd . DS . $file;
663
 
664
			$contents = file_get_contents($file);
665
			preg_match($options['regex'], $contents, $match);
666
			if (!$match) {
667
				continue;
668
			}
669
 
670
			$class = $match[1];
671
 
672
			if (substr($class, 0, 3) === 'Dbo') {
673
				$type = 'Dbo';
674
			} else {
675
				preg_match('@([A-Z][^A-Z]*)$@', $class, $match);
676
				if ($match) {
677
					$type = $match[1];
678
				} else {
679
					$type = 'unknown';
680
				}
681
			}
682
 
683
			preg_match('@^.*[\\\/]plugins[\\\/](.*?)[\\\/]@', $file, $match);
684
			$base = $cwd . DS;
685
			$plugin = false;
686
			if ($match) {
687
				$base = $match[0];
688
				$plugin = $match[1];
689
			}
690
 
691
			if ($options['checkFolder'] && !empty($this->_map[$type])) {
692
				$folder = str_replace('/', DS, $this->_map[$type]);
693
				$new = $base . $folder . DS . $class . '.php';
694
			} else {
695
				$new = dirname($file) . DS . $class . '.php';
696
			}
697
 
698
			if ($file === $new) {
699
				continue;
700
			}
701
 
702
			$dir = dirname($new);
703
			if (!is_dir($dir)) {
704
				new Folder($dir, true);
705
			}
706
 
707
			$this->out(__d('cake_console', 'Moving %s to %s', $file, $new), 1, Shell::VERBOSE);
708
			if (!$this->params['dry-run']) {
709
				if ($this->params['git']) {
710
					exec('git mv -f ' . escapeshellarg($file) . ' ' . escapeshellarg($file . '__'));
711
					exec('git mv -f ' . escapeshellarg($file . '__') . ' ' . escapeshellarg($new));
712
				} else {
713
					rename($file, $new);
714
				}
715
			}
716
		}
717
 
718
		$this->_paths = $paths;
719
	}
720
 
721
/**
722
 * Updates files based on regular expressions.
723
 *
724
 * @param array $patterns Array of search and replacement patterns.
725
 * @return void
726
 */
727
	protected function _filesRegexpUpdate($patterns) {
728
		$this->_findFiles($this->params['ext']);
729
		foreach ($this->_files as $file) {
730
			$this->out(__d('cake_console', 'Updating %s...', $file), 1, Shell::VERBOSE);
731
			$this->_updateFile($file, $patterns);
732
		}
733
	}
734
 
735
/**
736
 * Searches the paths and finds files based on extension.
737
 *
738
 * @param string $extensions
739
 * @return void
740
 */
741
	protected function _findFiles($extensions = '') {
742
		$this->_files = array();
743
		foreach ($this->_paths as $path) {
744
			if (!is_dir($path)) {
745
				continue;
746
			}
747
			$Iterator = new RegexIterator(
748
				new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)),
749
				'/^.+\.(' . $extensions . ')$/i',
750
				RegexIterator::MATCH
751
			);
752
			foreach ($Iterator as $file) {
753
				if ($file->isFile()) {
754
					$this->_files[] = $file->getPathname();
755
				}
756
			}
757
		}
758
	}
759
 
760
/**
761
 * Update a single file.
762
 *
763
 * @param string $file The file to update
764
 * @param array $patterns The replacement patterns to run.
765
 * @return void
766
 */
767
	protected function _updateFile($file, $patterns) {
768
		$contents = file_get_contents($file);
769
 
770
		foreach ($patterns as $pattern) {
771
			$this->out(__d('cake_console', ' * Updating %s', $pattern[0]), 1, Shell::VERBOSE);
772
			$contents = preg_replace($pattern[1], $pattern[2], $contents);
773
		}
774
 
775
		$this->out(__d('cake_console', 'Done updating %s', $file), 1);
776
		if (!$this->params['dry-run']) {
777
			file_put_contents($file, $contents);
778
		}
779
	}
780
 
781
/**
782
 * get the option parser
783
 *
784
 * @return ConsoleOptionParser
785
 */
786
	public function getOptionParser() {
787
		$subcommandParser = array(
788
			'options' => array(
789
				'plugin' => array(
790
					'short' => 'p',
791
					'help' => __d('cake_console', 'The plugin to update. Only the specified plugin will be updated.')
792
				),
793
				'ext' => array(
794
					'short' => 'e',
795
					'help' => __d('cake_console', 'The extension(s) to search. A pipe delimited list, or a preg_match compatible subpattern'),
796
					'default' => 'php|ctp|thtml|inc|tpl'
797
				),
798
				'git' => array(
799
					'short' => 'g',
800
					'help' => __d('cake_console', 'Use git command for moving files around.'),
801
					'boolean' => true
802
				),
803
				'dry-run' => array(
804
					'short' => 'd',
805
					'help' => __d('cake_console', 'Dry run the update, no files will actually be modified.'),
806
					'boolean' => true
807
				)
808
			)
809
		);
810
 
811
		return parent::getOptionParser()
812
			->description(__d('cake_console', "A shell to help automate upgrading from CakePHP 1.3 to 2.0. \n" .
813
				"Be sure to have a backup of your application before running these commands."))
814
			->addSubcommand('all', array(
815
				'help' => __d('cake_console', 'Run all upgrade commands.'),
816
				'parser' => $subcommandParser
817
			))
818
			->addSubcommand('tests', array(
819
				'help' => __d('cake_console', 'Update tests class names to FooTest rather than FooTestCase.'),
820
				'parser' => $subcommandParser
821
			))
822
			->addSubcommand('locations', array(
823
				'help' => __d('cake_console', 'Move files and folders to their new homes.'),
824
				'parser' => $subcommandParser
825
			))
826
			->addSubcommand('i18n', array(
827
				'help' => __d('cake_console', 'Update the i18n translation method calls.'),
828
				'parser' => $subcommandParser
829
			))
830
			->addSubcommand('helpers', array(
831
				'help' => __d('cake_console', 'Update calls to helpers.'),
832
				'parser' => $subcommandParser
833
			))
834
			->addSubcommand('basics', array(
835
				'help' => __d('cake_console', 'Update removed basics functions to PHP native functions.'),
836
				'parser' => $subcommandParser
837
			))
838
			->addSubcommand('request', array(
839
				'help' => __d('cake_console', 'Update removed request access, and replace with $this->request.'),
840
				'parser' => $subcommandParser
841
			))
842
			->addSubcommand('configure', array(
843
				'help' => __d('cake_console', "Update Configure::read() to Configure::read('debug')"),
844
				'parser' => $subcommandParser
845
			))
846
			->addSubcommand('constants', array(
847
				'help' => __d('cake_console', "Replace Obsolete constants"),
848
				'parser' => $subcommandParser
849
			))
850
			->addSubcommand('components', array(
851
				'help' => __d('cake_console', 'Update components to extend Component class.'),
852
				'parser' => $subcommandParser
853
			))
854
			->addSubcommand('exceptions', array(
855
				'help' => __d('cake_console', 'Replace use of cakeError with exceptions.'),
856
				'parser' => $subcommandParser
857
			));
858
	}
859
 
860
}