Passed
Push — master ( d5adc1...45b033 )
by Fabio
06:12
created

TActiveRecordGenAction::generateClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 10
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 14
rs 9.9332
1
<?php
2
/**
3
 * TActiveRecordGenAction class file
4
 *
5
 * @author Brad Anderson <[email protected]>
6
 * @link https://github.com/pradosoft/prado
7
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
8
 * @package Prado\Shell\Actions
9
 */
10
11
namespace Prado\Shell\Actions;
12
13
use Prado\Data\ActiveRecord\TActiveRecordConfig;
14
use Prado\Data\ActiveRecord\TActiveRecordManager;
15
use Prado\Prado;
16
use Prado\Shell\TShellAction;
17
18
/**
19
 * Create active record skeleton
20
 *
21
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
22
 * @package Prado\Shell\Actions
23
 * @since 3.1
24
 */
25
class TActiveRecordGenAction extends TShellAction
26
{
27
	protected $action = 'generate';
28
	protected $parameters = ['table', 'output'];
29
	protected $optional = ['directory', 'soap'];
30
	protected $description = 'Generate Active Record skeleton for <table> to <output> file using application.xml/php in [directory]. May also generate [soap] properties.';
31
	private $_soap = false;
32
	private $_overwrite = false;
33
34
	/**
35
	 * @param array $args parameters
36
	 * @return bool
37
	 */
38
	public function performAction($args)
39
	{
40
		$app_dir = count($args) > 3 ? $this->getAppDir($args[3]) : $this->getAppDir();
41
		$this->_soap = count($args) > 4;
42
		$this->_overwrite = count($args) > 5;
43
		if ($app_dir !== false) {
44
			$config = $this->getActiveRecordConfig($app_dir);
45
			$output = $this->getOutputFile($app_dir, $args[2]);
46
			if (is_file($output) && !$this->_overwrite) {
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

46
			if (is_file(/** @scrutinizer ignore-type */ $output) && !$this->_overwrite) {
Loading history...
47
				echo "** File $output already exists, skipping. \n";
48
			} elseif ($config !== false && $output !== false) {
0 ignored issues
show
introduced by
The condition $config !== false is always false.
Loading history...
49
				$this->generateActiveRecord($config, $args[1], $output);
50
			}
51
		}
52
		return true;
53
	}
54
55
	/**
56
	 * @param string $dir application directory
57
	 * @return false|string
58
	 */
59
	protected function getAppDir($dir = ".")
60
	{
61
		if (is_dir($dir)) {
62
			return realpath($dir);
63
		}
64
		if (false !== ($app_dir = realpath($dir . '/protected/')) && is_dir($app_dir)) {
65
			return $app_dir;
66
		}
67
		echo '** Unable to find directory "' . $dir . "\".\n";
68
		return false;
69
	}
70
71
	/**
72
	 * @param string $app_dir application directory
73
	 * @return false|string
74
	 */
75
	protected function getActiveRecordConfig($app_dir)
76
	{
77
		if (false === ($xml = $this->getAppConfigFile($app_dir))) {
78
			return false;
79
		}
80
		if (false !== ($app = $this->initializePradoApplication($app_dir))) {
0 ignored issues
show
introduced by
The condition false !== $app = $this->...doApplication($app_dir) is always false.
Loading history...
81
			foreach ($app->getModules() as $module) {
82
				if ($module instanceof TActiveRecordConfig) {
83
					return $module;
84
				}
85
			}
86
			echo '** Unable to find TActiveRecordConfig module in ' . $xml . "\n";
87
		}
88
		return false;
89
	}
90
91
	/**
92
	 * @param string $app_dir application directory
93
	 * @param string $namespace output file in namespace format
94
	 * @return false|string
95
	 */
96
	protected function getOutputFile($app_dir, $namespace)
97
	{
98
		if (is_file($namespace) && strpos($namespace, $app_dir) === 0) {
99
			return $namespace;
100
		}
101
		$file = Prado::getPathOfNamespace($namespace, ".php");
102
		if ($file !== null && false !== ($path = realpath(dirname($file))) && is_dir($path)) {
103
			if (strpos($path, $app_dir) === 0) {
104
				return $file;
105
			}
106
		}
107
		echo '** Output file ' . $file . ' must be within directory ' . $app_dir . "\n";
108
		return false;
109
	}
110
111
	/**
112
	 * @param string $config database configuration
113
	 * @param string $tablename table name
114
	 * @param string $output output file name
115
	 * @return bool
116
	 */
117
	protected function generateActiveRecord($config, $tablename, $output)
118
	{
119
		$manager = TActiveRecordManager::getInstance();
120
		if ($manager->getDbConnection()) {
121
			$gateway = $manager->getRecordGateway();
122
			$tableInfo = $gateway->getTableInfo($manager->getDbConnection(), $tablename);
123
			if (count($tableInfo->getColumns()) === 0) {
124
				echo '** Unable to find table or view "' . $tablename . '" in "' . $manager->getDbConnection()->getConnectionString() . "\".\n";
125
				return false;
126
			} else {
127
				$properties = [];
128
				foreach ($tableInfo->getColumns() as $field => $column) {
129
					$properties[] = $this->generateProperty($field, $column);
130
				}
131
			}
132
133
			$classname = basename($output, '.php');
134
			$class = $this->generateClass($properties, $tablename, $classname);
135
			echo "  Writing class $classname to file $output\n";
136
			file_put_contents($output, $class);
137
		} else {
138
			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";
139
		}
140
	}
141
142
	/**
143
	 * @param string $field php variable name
144
	 * @param string $column database column name
145
	 * @return string
146
	 */
147
	protected function generateProperty($field, $column)
148
	{
149
		$prop = '';
150
		$name = '$' . $field;
151
		$type = $column->getPHPType();
152
		if ($this->_soap) {
153
			$prop .= <<<EOD
154
155
	/**
156
	 * @var $type $name
157
	 * @soapproperty
158
	 */
159
160
EOD;
161
		}
162
		$prop .= "\tpublic $name;";
163
		return $prop;
164
	}
165
166
	/**
167
	 * @param array $properties class varibles
168
	 * @param string $tablename database table name
169
	 * @param string $class php class name
170
	 * @return string
171
	 */
172
	protected function generateClass($properties, $tablename, $class)
173
	{
174
		$props = implode("\n", $properties);
175
		$date = date('Y-m-d h:i:s');
176
		return <<<EOD
177
<?php
178
/**
179
 * Auto generated by prado-cli.php on $date.
180
 */
181
class $class extends TActiveRecord
182
{
183
	const TABLE='$tablename';
184
185
$props
186
187
	public static function finder(\$className=__CLASS__)
188
	{
189
		return parent::finder(\$className);
190
	}
191
}
192
193
EOD;
194
	}
195
}
196