Passed
Branch php-cs-fixer (b9836a)
by Fabio
15:02
created

PradoCommandLineActiveRecordGenAll   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 124
rs 8.5454
c 1
b 0
f 0
wmc 49

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getAppDir() 0 7 4
F performAction() 0 50 24
A generate() 0 17 4
B getActiveRecordConfig() 0 11 5
B getXmlFile() 0 7 5
B getOutputFile() 0 10 7

How to fix   Complexity   

Complex Class

Complex classes like PradoCommandLineActiveRecordGenAll often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PradoCommandLineActiveRecordGenAll, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Prado command line developer tools.
5
 *
6
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
7
 * @link https://github.com/pradosoft/prado
8
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
9
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
10
 */
11
12
if(!isset($_SERVER['argv']) || php_sapi_name() !== 'cli')
13
	die('Must be run from the command line');
14
15
// Locate composer's autoloader
16
if(file_exists($autoloader = realpath(__DIR__ . '/../vendor/autoload.php')))
17
{
18
	// if we are running inside a prado repo checkout, get out of bin/
19
	include($autoloader);
20
} elseif(file_exists($autoloader = realpath(__DIR__ . '/../../../autoload.php'))) {
21
	// if we are running from inside an application's vendor/ directory, get out of pradosoft/prado/bin/
22
	include($autoloader);
23
}
24
25
use Prado\TApplication;
26
use Prado\Prado;
27
28
//stub application class
29
class PradoShellApplication extends TApplication
30
{
31
	public function run()
32
	{
33
		$this->initApplication();
34
	}
35
}
36
37
restore_exception_handler();
38
39
40
//register action classes
41
PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineCreateProject');
42
PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineCreateTests');
43
PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLinePhpShell');
44
PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineActiveRecordGen');
45
PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineActiveRecordGenAll');
46
47
//run it;
48
PradoCommandLineInterpreter::getInstance()->run($_SERVER['argv']);
49
50
/**************** END CONFIGURATION **********************/
51
52
/**
53
 * PradoCommandLineInterpreter Class
54
 *
55
 * Command line interface, configures the action classes and dispatches the command actions.
56
 *
57
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
58
 * @since 3.0.5
59
 */
60
class PradoCommandLineInterpreter
61
{
62
	/**
63
	 * @var array command action classes
64
	 */
65
	protected $_actions = [];
66
67
	/**
68
	 * @param string action class name
0 ignored issues
show
Bug introduced by
The type action was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
69
	 */
70
	public function addActionClass($class)
71
	{
72
		$this->_actions[$class] = new $class;
73
	}
74
75
	/**
76
	 * @return PradoCommandLineInterpreter static instance
77
	 */
78
	public static function getInstance()
79
	{
80
		static $instance;
81
		if($instance === null)
82
			$instance = new self;
83
		return $instance;
84
	}
85
86
	public static function printGreeting()
87
	{
88
		echo "Command line tools for Prado " . Prado::getVersion() . ".\n";
89
	}
90
91
	/**
92
	 * Dispatch the command line actions.
0 ignored issues
show
Bug introduced by
The type command was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
93
	 * @param array command line arguments
94
	 */
95
	public function run($args)
96
	{
97
		if(count($args) > 1)
98
			array_shift($args);
99
		$valid = false;
100
		foreach($this->_actions as $class => $action)
101
		{
102
			if($action->isValidAction($args))
103
			{
104
				$valid |= $action->performAction($args);
105
				break;
106
			}
107
			else
108
			{
109
				$valid = false;
110
			}
111
		}
112
		if(!$valid)
0 ignored issues
show
Bug Best Practice introduced by
The expression $valid of type integer|false is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
113
			$this->printHelp();
114
	}
115
116
	/**
117
	 * Print command line help, default action.
118
	 */
119
	public function printHelp()
120
	{
121
		PradoCommandLineInterpreter::printGreeting();
122
123
		echo "usage: php prado-cli.php action <parameter> [optional]\n";
124
		echo "example: php prado-cli.php -c mysite\n\n";
125
		echo "actions:\n";
126
		foreach($this->_actions as $action)
127
			echo $action->renderHelp();
128
	}
129
}
130
131
/**
132
 * Base class for command line actions.
133
 *
134
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
135
 * @since 3.0.5
136
 */
137
abstract class PradoCommandLineAction
138
{
139
	/**
140
	 * Execute the action.
141
	 * @param array command line parameters
142
	 * @return boolean true if action was handled
143
	 */
144
	abstract public function performAction($args);
145
146
	protected function createDirectory($dir, $mask)
147
	{
148
		if(!is_dir($dir))
149
		{
150
			mkdir($dir);
151
			echo "creating $dir\n";
152
		}
153
		if(is_dir($dir))
154
			chmod($dir, $mask);
155
	}
156
157
	protected function createFile($filename, $content)
158
	{
159
		if(!is_file($filename))
160
		{
161
			file_put_contents($filename, $content);
162
			echo "creating $filename\n";
163
		}
164
	}
165
166
	public function isValidAction($args)
167
	{
168
		return 0 == strcasecmp($args[0], $this->action) &&
169
			count($args) - 1 >= count($this->parameters);
170
	}
171
172
	public function renderHelp()
173
	{
174
		$params = [];
175
		foreach($this->parameters as $v)
176
			$params[] = '<' . $v . '>';
177
		$parameters = implode($params, ' ');
0 ignored issues
show
Unused Code introduced by
The call to implode() has too many arguments starting with ' '. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

177
		$parameters = /** @scrutinizer ignore-call */ implode($params, ' ');

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
178
		$options = [];
179
		foreach($this->optional as $v)
180
			$options[] = '[' . $v . ']';
181
		$optional = (strlen($parameters) ? ' ' : '') . implode($options, ' ');
182
		$description = '';
183
		foreach(explode("\n", wordwrap($this->description, 65)) as $line)
184
			$description .= '    ' . $line . "\n";
185
		return <<<EOD
186
  {$this->action} {$parameters}{$optional}
187
{$description}
188
189
EOD;
190
	}
191
192
	protected function initializePradoApplication($directory)
193
	{
194
		$_SERVER['SCRIPT_FILENAME'] = $directory . '/index.php';
195
		$app_dir = realpath($directory . '/protected/');
196
		if($app_dir !== false && is_dir($app_dir))
197
		{
198
			if(Prado::getApplication() === null)
199
			{
200
				$app = new PradoShellApplication($app_dir);
201
				$app->run();
202
				$dir = substr(str_replace(realpath('./'), '', $app_dir), 1);
203
				PradoCommandLineInterpreter::printGreeting();
204
				echo '** Loaded PRADO appplication in directory "' . $dir . "\".\n";
205
			}
206
207
			return Prado::getApplication();
208
		}
209
		else
210
		{
211
			PradoCommandLineInterpreter::printGreeting();
212
			echo '+' . str_repeat('-', 77) . "+\n";
213
			echo '** Unable to load PRADO application in directory "' . $directory . "\".\n";
214
			echo '+' . str_repeat('-', 77) . "+\n";
215
		}
216
		return false;
217
	}
218
219
}
220
221
/**
222
 * Create a Prado project skeleton, including directories and files.
223
 *
224
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
225
 * @since 3.0.5
226
 */
227
class PradoCommandLineCreateProject extends PradoCommandLineAction
228
{
229
	protected $action = '-c';
230
	protected $parameters = ['directory'];
231
	protected $optional = [];
232
	protected $description = 'Creates a Prado project skeleton for the given <directory>.';
233
234
	public function performAction($args)
235
	{
236
		PradoCommandLineInterpreter::printGreeting();
237
		$this->createNewPradoProject($args[1]);
238
		return true;
239
	}
240
241
	/**
242
	 * Functions to create new prado project.
243
	 */
244
	protected function createNewPradoProject($dir)
245
	{
246
		if(strlen(trim($dir)) == 0)
247
			return;
248
249
		$rootPath = realpath(dirname(trim($dir)));
250
251
		if(basename($dir) !== '.')
252
			$basePath = $rootPath . DIRECTORY_SEPARATOR . basename($dir);
253
		else
254
			$basePath = $rootPath;
255
		$appName = basename($basePath);
256
		$assetPath = $basePath . DIRECTORY_SEPARATOR . 'assets';
257
		$protectedPath = $basePath . DIRECTORY_SEPARATOR . 'protected';
258
		$runtimePath = $basePath . DIRECTORY_SEPARATOR . 'protected' . DIRECTORY_SEPARATOR . 'runtime';
259
		$pagesPath = $protectedPath . DIRECTORY_SEPARATOR . 'pages';
260
261
		$indexFile = $basePath . DIRECTORY_SEPARATOR . 'index.php';
262
		$htaccessFile = $protectedPath . DIRECTORY_SEPARATOR . '.htaccess';
263
		$configFile = $protectedPath . DIRECTORY_SEPARATOR . 'application.xml';
264
		$defaultPageFile = $pagesPath . DIRECTORY_SEPARATOR . 'Home.page';
265
266
		$this->createDirectory($basePath, 0755);
267
		$this->createDirectory($assetPath, 0777);
268
		$this->createDirectory($protectedPath, 0755);
269
		$this->createDirectory($runtimePath, 0777);
270
		$this->createDirectory($pagesPath, 0755);
271
272
		$this->createFile($indexFile, $this->renderIndexFile());
273
		$this->createFile($configFile, $this->renderConfigFile($appName));
274
		$this->createFile($htaccessFile, $this->renderHtaccessFile());
275
		$this->createFile($defaultPageFile, $this->renderDefaultPage());
276
	}
277
278
	protected function renderIndexFile()
279
	{
280
		$framework = realpath(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'framework' . DIRECTORY_SEPARATOR . 'prado.php';
281
return '<?php
282
283
$frameworkPath=\'' . $framework . '\';
284
285
// The following directory checks may be removed if performance is required
286
$basePath=dirname(__FILE__);
287
$assetsPath=$basePath.\'/assets\';
288
$runtimePath=$basePath.\'/protected/runtime\';
289
290
if(!is_file($frameworkPath))
291
	die("Unable to find prado framework path $frameworkPath.");
292
if(!is_writable($assetsPath))
293
	die("Please make sure that the directory $assetsPath is writable by Web server process.");
294
if(!is_writable($runtimePath))
295
	die("Please make sure that the directory $runtimePath is writable by Web server process.");
296
297
298
require_once($frameworkPath);
299
300
$application=new TApplication;
301
$application->run();
302
';
303
	}
304
305
	protected function renderConfigFile($appName)
306
	{
307
		return <<<EOD
308
<?xml version="1.0" encoding="utf-8"?>
309
310
<application id="$appName" mode="Debug">
311
  <!-- alias definitions and namespace usings
312
  <paths>
313
    <alias id="myalias" path="./lib" />
314
    <using namespace="Application.common.*" />
315
  </paths>
316
  -->
317
318
  <!-- configurations for modules -->
319
  <modules>
320
    <!-- Remove this comment mark to enable caching
321
    <module id="cache" class="System.Caching.TDbCache" />
322
    -->
323
324
    <!-- Remove this comment mark to enable PATH url format
325
    <module id="request" class="THttpRequest" UrlFormat="Path" />
326
    -->
327
328
    <!-- Remove this comment mark to enable logging
329
    <module id="log" class="System.Util.TLogRouter">
330
      <route class="TBrowserLogRoute" Categories="System" />
331
    </module>
332
    -->
333
  </modules>
334
335
  <!-- configuration for available services -->
336
  <services>
337
    <service id="page" class="TPageService" DefaultPage="Home" />
338
  </services>
339
340
  <!-- application parameters
341
  <parameters>
342
    <parameter id="param1" value="value1" />
343
    <parameter id="param2" value="value2" />
344
  </parameters>
345
  -->
346
</application>
347
EOD;
348
	}
349
350
	protected function renderHtaccessFile()
351
	{
352
		return 'deny from all';
353
	}
354
355
356
	protected function renderDefaultPage()
357
	{
358
return <<<EOD
359
<html>
360
<head>
361
  <title>Welcome to PRADO</title>
362
</head>
363
<body>
364
<h1>Welcome to PRADO!</h1>
365
</body>
366
</html>
367
EOD;
368
	}
369
}
370
371
/**
372
 * Creates test fixtures for a Prado application.
373
 *
374
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
375
 * @since 3.0.5
376
 */
377
class PradoCommandLineCreateTests extends PradoCommandLineAction
378
{
379
	protected $action = '-t';
380
	protected $parameters = ['directory'];
381
	protected $optional = [];
382
	protected $description = 'Create test fixtures in the given <directory>.';
383
384
	public function performAction($args)
385
	{
386
		PradoCommandLineInterpreter::printGreeting();
387
		$this->createTestFixtures($args[1]);
388
		return true;
389
	}
390
391
	protected function createTestFixtures($dir)
392
	{
393
		if(strlen(trim($dir)) == 0)
394
			return;
395
396
		$rootPath = realpath(dirname(trim($dir)));
397
		$basePath = $rootPath . '/' . basename($dir);
398
399
		$tests = $basePath . '/tests';
400
		$unit_tests = $tests . '/unit';
401
		$functional_tests = $tests . '/functional';
402
403
		$this->createDirectory($tests, 0755);
404
		$this->createDirectory($unit_tests, 0755);
405
		$this->createDirectory($functional_tests, 0755);
406
407
		$unit_test_index = $tests . '/unit.php';
408
		$functional_test_index = $tests . '/functional.php';
409
410
		$this->createFile($unit_test_index, $this->renderUnitTestFixture());
411
		$this->createFile($functional_test_index, $this->renderFunctionalTestFixture());
412
	}
413
414
	protected function renderUnitTestFixture()
415
	{
416
		$tester = realpath(dirname(dirname(__FILE__))) . '/tests/test_tools/unit_tests.php';
417
return '<?php
418
419
include_once \'' . $tester . '\';
420
421
$app_directory = "../protected";
422
$test_cases = dirname(__FILE__)."/unit";
423
424
$tester = new PradoUnitTester($test_cases, $app_directory);
425
$tester->run(new HtmlReporter());
426
';
427
	}
428
429
	protected function renderFunctionalTestFixture()
430
	{
431
		$tester = realpath(dirname(dirname(__FILE__))) . '/tests/test_tools/functional_tests.php';
432
return '<?php
433
434
include_once \'' . $tester . '\';
435
436
$test_cases = dirname(__FILE__)."/functional";
437
438
$tester=new PradoFunctionalTester($test_cases);
439
$tester->run(new SimpleReporter());
440
';
441
	}
442
443
}
444
445
/**
446
 * Creates and run a Prado application in a PHP Shell.
447
 *
448
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
449
 * @since 3.0.5
450
 */
451
class PradoCommandLinePhpShell extends PradoCommandLineAction
452
{
453
	protected $action = 'shell';
454
	protected $parameters = [];
455
	protected $optional = ['directory'];
456
	protected $description = 'Runs a PHP interactive interpreter. Initializes the Prado application in the given [directory].';
457
458
	public function performAction($args)
459
	{
460
		if(count($args) > 1)
461
			$this->initializePradoApplication($args[1]);
462
463
		\Psy\debug([], Prado::getApplication());
464
		return true;
465
	}
466
}
467
468
/**
469
 * Create active record skeleton
470
 *
471
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
472
 * @since 3.1
473
 */
474
class PradoCommandLineActiveRecordGen extends PradoCommandLineAction
475
{
476
	protected $action = 'generate';
477
	protected $parameters = ['table', 'output'];
478
	protected $optional = ['directory', 'soap'];
479
	protected $description = 'Generate Active Record skeleton for <table> to <output> file using application.xml in [directory]. May also generate [soap] properties.';
480
	private $_soap = false;
481
482
	public function performAction($args)
483
	{
484
		$app_dir = count($args) > 3 ? $this->getAppDir($args[3]) : $this->getAppDir();
485
		$this->_soap = count($args) > 4;
486
		if($app_dir !== false)
487
		{
488
			$config = $this->getActiveRecordConfig($app_dir);
489
			$output = $this->getOutputFile($app_dir, $args[2]);
490
			if(is_file($output))
0 ignored issues
show
Bug introduced by
It seems like $output can also be of type false; however, parameter $filename of is_file() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

490
			if(is_file(/** @scrutinizer ignore-type */ $output))
Loading history...
491
				echo "** File $output already exists, skiping. \n";
492
			elseif($config !== false && $output !== false)
493
				$this->generateActiveRecord($config, $args[1], $output);
494
		}
495
		return true;
496
	}
497
498
	protected function getAppDir($dir = ".")
499
	{
500
		if(is_dir($dir))
501
			return realpath($dir);
502
		if(false !== ($app_dir = realpath($dir . '/protected/')) && is_dir($app_dir))
503
			return $app_dir;
504
		echo '** Unable to find directory "' . $dir . "\".\n";
505
		return false;
506
	}
507
508
	protected function getXmlFile($app_dir)
509
	{
510
		if(false !== ($xml = realpath($app_dir . '/application.xml')) && is_file($xml))
511
			return $xml;
512
		if(false !== ($xml = realpath($app_dir . '/protected/application.xml')) && is_file($xml))
513
			return $xml;
514
		echo '** Unable to find application.xml in ' . $app_dir . "\n";
515
		return false;
516
	}
517
518
	protected function getActiveRecordConfig($app_dir)
519
	{
520
		if(false === ($xml = $this->getXmlFile($app_dir)))
521
			return false;
522
		if(false !== ($app = $this->initializePradoApplication($app_dir)))
523
		{
524
			Prado::using('System.Data.ActiveRecord.TActiveRecordConfig');
525
			foreach($app->getModules() as $module)
526
				if($module instanceof TActiveRecordConfig)
0 ignored issues
show
Bug introduced by
The type TActiveRecordConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
527
					return $module;
528
			echo '** Unable to find TActiveRecordConfig module in ' . $xml . "\n";
529
		}
530
		return false;
531
	}
532
533
	protected function getOutputFile($app_dir, $namespace)
534
	{
535
		if(is_file($namespace) && strpos($namespace, $app_dir) === 0)
536
				return $namespace;
537
		$file = Prado::getPathOfNamespace($namespace, ".php");
538
		if($file !== null && false !== ($path = realpath(dirname($file))) && is_dir($path))
539
		{
540
			if(strpos($path, $app_dir) === 0)
541
				return $file;
542
		}
543
		echo '** Output file ' . $file . ' must be within directory ' . $app_dir . "\n";
544
		return false;
545
	}
546
547
	protected function generateActiveRecord($config, $tablename, $output)
548
	{
549
		$manager = TActiveRecordManager::getInstance();
0 ignored issues
show
Bug introduced by
The type TActiveRecordManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
550
		if($manager->getDbConnection()) {
551
			$gateway = $manager->getRecordGateway();
552
			$tableInfo = $gateway->getTableInfo($manager->getDbConnection(), $tablename);
553
			if(count($tableInfo->getColumns()) === 0)
554
			{
555
				echo '** Unable to find table or view "' . $tablename . '" in "' . $manager->getDbConnection()->getConnectionString() . "\".\n";
556
				return false;
557
			}
558
			else
559
			{
560
				$properties = [];
561
				foreach($tableInfo->getColumns() as $field => $column)
562
					$properties[] = $this->generateProperty($field, $column);
563
			}
564
565
			$classname = basename($output, '.php');
566
			$class = $this->generateClass($properties, $tablename, $classname);
567
			echo "  Writing class $classname to file $output\n";
568
			file_put_contents($output, $class);
569
		} else {
570
			echo '** Unable to connect to database with ConnectionID=\'' . $config->getConnectionID() . "'. Please check your settings in application.xml and ensure your database connection is set up first.\n";
571
		}
572
	}
573
574
	protected function generateProperty($field, $column)
575
	{
576
		$prop = '';
577
		$name = '$' . $field;
578
		$type = $column->getPHPType();
579
		if($this->_soap)
580
		{
581
			$prop .= <<<EOD
582
583
	/**
584
	 * @var $type $name
585
	 * @soapproperty
586
	 */
587
588
EOD;
589
		}
590
		$prop .= "\tpublic $name;";
591
		return $prop;
592
	}
593
594
	protected function generateClass($properties, $tablename, $class)
595
	{
596
		$props = implode("\n", $properties);
597
		$date = date('Y-m-d h:i:s');
598
return <<<EOD
599
<?php
600
/**
601
 * Auto generated by prado-cli.php on $date.
602
 */
603
class $class extends TActiveRecord
604
{
605
	const TABLE='$tablename';
606
607
$props
608
609
	public static function finder(\$className=__CLASS__)
610
	{
611
		return parent::finder(\$className);
612
	}
613
}
614
615
EOD;
616
	}
617
}
618
619
/**
620
 * Create active record skeleton for all tables in DB and its relations
621
 *
622
 * @author Matthias Endres <me[at]me23[dot]de>
623
 * @author Daniel Sampedro Bello <darthdaniel85[at]gmail[dot]com>
624
 * @since 3.2
625
 */
626
class PradoCommandLineActiveRecordGenAll extends PradoCommandLineAction
627
{
628
	protected $action = 'generateAll';
629
	protected $parameters = ['output'];
630
	protected $optional = ['directory', 'soap', 'overwrite', 'prefix', 'postfix'];
631
	protected $description = "Generate Active Record skeleton for all Tables to <output> file using application.xml in [directory]. May also generate [soap] properties.\nGenerated Classes are named like the Table with optional [Prefix] and/or [Postfix]. [Overwrite] is used to overwrite existing Files.";
632
	private $_soap = false;
633
	private $_prefix = '';
634
	private $_postfix = '';
635
	private $_overwrite = false;
636
637
	public function performAction($args) {
638
		$app_dir = count($args) > 2 ? $this->getAppDir($args[2]) : $this->getAppDir();
639
		$this->_soap = count($args) > 3 ? ($args[3] == "soap" || $args[3] == "true" ? true : false) : false;
640
		$this->_overwrite = count($args) > 4 ? ($args[4] == "overwrite" || $args[4] == "true" ? true : false) : false;
641
		$this->_prefix = count($args) > 5 ? $args[5] : '';
642
		$this->_postfix = count($args) > 6 ? $args[6] : '';
643
644
		if ($app_dir !== false) {
645
			$config = $this->getActiveRecordConfig($app_dir);
646
647
			$manager = TActiveRecordManager::getInstance();
648
			$con = $manager->getDbConnection();
649
			$con->Active = true;
650
651
			switch($con->getDriverName())
652
			   {
653
				case 'mysqli':
654
				case 'mysql':
655
					$command = $con->createCommand("SHOW TABLES");
656
					break;
657
				case 'sqlite': //sqlite 3
658
				case 'sqlite2': //sqlite 2
659
					$command = $con->createCommand("SELECT DISTINCT tbl_name FROM sqlite_master WHERE tbl_name<>'sqlite_sequence'");
660
					break;
661
				case 'pgsql':
662
				case 'mssql': // Mssql driver on windows hosts
663
				case 'sqlsrv': // sqlsrv driver on windows hosts
664
				case 'dblib': // dblib drivers on linux (and maybe others os) hosts
665
				case 'oci':
666
//				case 'ibm':
667
				default:
668
					echo "\n    Sorry, generateAll is not implemented for " . $con->getDriverName() . "\n";
669
					
670
			   }
671
672
			$dataReader = $command->query();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $command does not seem to be defined for all execution paths leading up to this point.
Loading history...
673
			$dataReader->bindColumn(1, $table);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $table does not exist. Did you maybe mean $tables?
Loading history...
674
			$tables = [];
675
			while ($dataReader->read() !== false) {
676
				$tables[] = $table;
677
			}
678
			$con->Active = false;
679
			foreach ($tables as $key => $table) {
680
				$output = $args[1] . "." . $this->_prefix . ucfirst($table) . $this->_postfix;
681
				if ($config !== false && $output !== false) {
682
					$this->generate("generate " . $table . " " . $output . " " . $this->_soap . " " . $this->_overwrite);
683
				}
684
			}
685
		}
686
		return true;
687
	}
688
689
	public function generate($l)
690
	{
691
		$input = explode(" ", trim($l));
692
		if(count($input) > 2)
693
		{
694
			$app_dir = '.';
695
			if(Prado::getApplication() !== null)
696
				$app_dir = dirname(Prado::getApplication()->getBasePath());
697
			$args = [$input[0],$input[1], $input[2],$app_dir];
698
			if(count($input) > 3)
699
				$args = [$input[0],$input[1], $input[2],$app_dir,'soap'];
700
			$cmd = new PradoCommandLineActiveRecordGen;
701
			$cmd->performAction($args);
702
		}
703
		else
704
		{
705
			echo "\n    Usage: generate table_name Application.pages.RecordClassName\n";
706
		}
707
	}
708
709
	protected function getAppDir($dir = ".") {
710
		if (is_dir($dir))
711
			return realpath($dir);
712
		if (false !== ($app_dir = realpath($dir . '/protected/')) && is_dir($app_dir))
713
			return $app_dir;
714
		echo '** Unable to find directory "' . $dir . "\".\n";
715
		return false;
716
	}
717
718
	protected function getXmlFile($app_dir) {
719
		if (false !== ($xml = realpath($app_dir . '/application.xml')) && is_file($xml))
720
			return $xml;
721
		if (false !== ($xml = realpath($app_dir . '/protected/application.xml')) && is_file($xml))
722
			return $xml;
723
		echo '** Unable to find application.xml in ' . $app_dir . "\n";
724
		return false;
725
	}
726
727
	protected function getActiveRecordConfig($app_dir) {
728
		if (false === ($xml = $this->getXmlFile($app_dir)))
729
			return false;
730
		if (false !== ($app = $this->initializePradoApplication($app_dir))) {
731
			Prado::using('System.Data.ActiveRecord.TActiveRecordConfig');
732
			foreach ($app->getModules() as $module)
733
				if ($module instanceof TActiveRecordConfig)
734
					return $module;
735
			echo '** Unable to find TActiveRecordConfig module in ' . $xml . "\n";
736
		}
737
		return false;
738
	}
739
740
	protected function getOutputFile($app_dir, $namespace) {
741
		if (is_file($namespace) && strpos($namespace, $app_dir) === 0)
742
			return $namespace;
743
		$file = Prado::getPathOfNamespace($namespace, "");
744
		if ($file !== null && false !== ($path = realpath(dirname($file))) && is_dir($path)) {
745
			if (strpos($path, $app_dir) === 0)
746
				return $file;
747
		}
748
		echo '** Output file ' . $file . ' must be within directory ' . $app_dir . "\n";
749
		return false;
750
	}
751
752
}
753