TActiveRecordAction::actionGenerateAll()   F
last analyzed

Complexity

Conditions 23
Paths 2816

Size

Total Lines 50
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 23
eloc 38
c 1
b 0
f 0
nc 2816
nop 1
dl 0
loc 50
rs 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * TActiveRecordAction class file
5
 *
6
 * @author Brad Anderson <[email protected]>
7
 * @link https://github.com/pradosoft/prado
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
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
 * TActiveRecordAction class.
20
 *
21
 * Create active record skeleton
22
 *
23
 * @author Brad Anderson <belisoful[at]icloud[dot]com> - Shell refactor
24
 * @author Matthias Endres <me[at]me23[dot]de> - Generate-All
25
 * @author Daniel Sampedro Bello <darthdaniel85[at]gmail[dot]com> - Generate-All
26
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com> - Generate
27
 * @since 3.1
28
 */
29
class TActiveRecordAction extends TShellAction
30
{
31
	protected $action = 'activerecord';
32
	protected $methods = ['generate', 'generate-all'];
33
	protected $parameters = [['table', 'output'], ['output']];
34
	protected $optional = [['soap', 'overwrite'], ['soap', 'overwrite', 'prefix', 'suffix']];
35
	protected $description = [
36
		'Provides Active Record skeleton generation.',
37
		'Generate Active Record skeleton for <table> to <output>. May also generate [soap] properties.',
38
		"Generate Active Record skeleton for all Tables to <output>. May also generate [soap] properties.\nGenerated Classes are named like the Table with optional [Prefix] and/or [Suffix]. [Overwrite] is used to overwrite existing Files.",
39
	];
40
	private $_soap = false;
41
	private $_overwrite = false;
42
43
	private $_soapall = false;
44
	private $_overwriteall = false;
45
	private $_prefix = '';
46
	private $_postfix = '';
47
48
49
50
	/**
51
	 * This is the Shell Command for Generating all Action Record table skeletons
52
	 * @param array $args parameters
53
	 * @return bool is the action handled
54
	 */
55
	public function actionGenerateAll($args)
56
	{
57
		$app_dir = Prado::getApplication()->getBasePath();
58
		$this->_soapall = count($args) > 2 ? ($args[2] == "soap" || $args[2] == "true" ? true : false) : false;
59
		$this->_overwriteall = count($args) > 3 ? ($args[3] == "overwrite" || $args[3] == "true" ? true : false) : false;
60
		$this->_prefix = count($args) > 4 ? $args[4] : '';
61
		$this->_postfix = count($args) > 5 ? $args[5] : '';
62
63
		if ($app_dir !== false) {
0 ignored issues
show
introduced by
The condition $app_dir !== false is always true.
Loading history...
64
			$config = $this->getActiveRecordConfig();
65
66
			$manager = TActiveRecordManager::getInstance();
67
			$con = $manager->getDbConnection();
68
			$con->setActive(true);
69
			$command = null;
70
71
			switch ($con->getDriverName()) {
72
				case 'mysqli':
73
				case 'mysql':
74
					$command = $con->createCommand("SHOW TABLES");
75
					break;
76
				case 'sqlite': //sqlite 3
77
				case 'sqlite2': //sqlite 2
78
					$command = $con->createCommand("SELECT DISTINCT tbl_name FROM sqlite_master WHERE tbl_name<>'sqlite_sequence'");
79
					break;
80
				case 'pgsql':
81
				case 'mssql': // Mssql driver on windows hosts
82
				case 'sqlsrv': // sqlsrv driver on windows hosts
83
				case 'dblib': // dblib drivers on linux (and maybe others os) hosts
84
				case 'oci':
85
					//				case 'ibm':
86
				default:
87
					$this->_outWriter->writeError("Sorry, generateAll is not implemented for " . $con->getDriverName() . ".");
88
			}
89
90
			$dataReader = $command->query();
91
			$dataReader->bindColumn(1, $table);
92
			$tables = [];
93
			while ($dataReader->read() !== false) {
94
				$tables[] = $table;
95
			}
96
			$con->setActive(false);
97
			foreach ($tables as $key => $table) {
98
				$output = $args[1] . "." . $this->_prefix . ucfirst($table) . $this->_postfix;
99
				if ($config !== false && $output !== false) {
100
					$this->generate("generate " . $table . " " . $output . " " . $this->_soapall . " " . $this->_overwriteall);
101
				}
102
			}
103
		}
104
		return true;
105
	}
106
107
	/**
108
	 * @param string $l commandline
109
	 */
110
	public function generate($l)
111
	{
112
		$input = explode(" ", trim($l));
113
		if (count($input) > 2) {
114
			$app_dir = dirname(Prado::getApplication()->getBasePath());
0 ignored issues
show
Unused Code introduced by
The assignment to $app_dir is dead and can be removed.
Loading history...
115
			$args = [$input[0], $input[1], $input[2]];
116
			if (count($input) > 3) {
117
				$args[] = 'soap';
118
			}
119
			if (count($input) > 4) {
120
				$args[] = 'overwrite';
121
			}
122
			$this->actionGenerate($args);
123
		} else {
124
			$this->_outWriter->writeLine("\n    Usage: generate table_name Application.pages.RecordClassName");
125
		}
126
	}
127
128
129
	/**
130
	 * This is the Shell Command for Generating a specific Action Record table skeleton
131
	 * @param array $args parameters
132
	 * @return bool is the action handled
133
	 */
134
	public function actionGenerate($args)
135
	{
136
		$this->_soapall = count($args) > 3 ? ($args[3] == "soap" || $args[2] == "true" ? true : false) : false;
137
		$this->_overwriteall = count($args) > 4 ? ($args[4] == "overwrite" || $args[3] == "true" ? true : false) : false;
138
		$config = $this->getActiveRecordConfig();
139
		$output = $this->getOutputFile($args[2]);
140
		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

140
		if (is_file(/** @scrutinizer ignore-type */ $output) && !$this->_overwrite) {
Loading history...
141
			$this->_outWriter->writeError("File $output already exists, skipping. ");
142
		} elseif ($config !== false && $output !== false) {
143
			$this->generateActiveRecord($config, $args[1], $output);
144
		}
145
		return true;
146
	}
147
148
	/**
149
	 * gets the TActiveRecordConfig for the application
150
	 * @return false|TActiveRecordConfig
151
	 */
152
	protected function getActiveRecordConfig()
153
	{
154
		foreach (Prado::getApplication()->getModules() as $module) {
155
			if ($module instanceof TActiveRecordConfig) {
156
				return $module;
157
			}
158
		}
159
		return null;
160
	}
161
162
	/**
163
	 * @param string $namespace output file in namespace format
164
	 * @return false|string
165
	 */
166
	protected function getOutputFile($namespace)
167
	{
168
		$app_dir = Prado::getApplication()->getBasePath();
169
		if (is_file($namespace) && strpos($namespace, $app_dir) === 0) {
170
			return $namespace;
171
		}
172
		$file = Prado::getPathOfNamespace($namespace, ".php");
173
		if ($file !== null && false !== ($path = realpath(dirname($file))) && is_dir($path)) {
174
			if (strpos($path, $app_dir) === 0) {
175
				return $file;
176
			}
177
		}
178
		$this->_outWriter->writeError('Output file ' . $file . ' must be within directory ' . $app_dir . "");
179
		return false;
180
	}
181
182
	/**
183
	 * @param TActiveRecordConfig $config database configuration
184
	 * @param string $tablename table name
185
	 * @param string $output output file name
186
	 * @return bool
187
	 */
188
	protected function generateActiveRecord($config, $tablename, $output)
189
	{
190
		$manager = TActiveRecordManager::getInstance();
191
		if ($manager->getDbConnection()) {
192
			$gateway = $manager->getRecordGateway();
193
			$tableInfo = $gateway->getTableInfo($manager->getDbConnection(), $tablename);
194
			if (count($tableInfo->getColumns()) === 0) {
195
				$this->_outWriter->writeError('Unable to find table or view "' . $tablename . '" in "' . $manager->getDbConnection()->getConnectionString() . "\".");
196
				return false;
197
			} else {
198
				$properties = [];
199
				foreach ($tableInfo->getColumns() as $field => $column) {
200
					$properties[] = $this->generateProperty($field, $column);
201
				}
202
			}
203
204
			$classname = basename($output, '.php');
205
			$class = $this->generateClass($properties, $tablename, $classname);
206
			$this->_outWriter->writeLine("  Writing class $classname to file $output");
207
			file_put_contents($output, $class);
208
		} else {
209
			$this->_outWriter->writeError('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.");
210
		}
211
		return true;
212
	}
213
214
	/**
215
	 * @param string $field php variable name
216
	 * @param \Prado\Data\Common\TDbTableColumn $column database column name
217
	 * @return string
218
	 */
219
	protected function generateProperty($field, $column)
220
	{
221
		$prop = '';
222
		$name = '$' . $field;
223
		$type = $column->getPHPType();
224
		if ($this->_soap) {
225
			$prop .= <<<EOD
226
227
					/**
228
					 * @var $type $name
229
					 * @soapproperty
230
					 */
231
232
				EOD;
233
		}
234
		$prop .= "\tpublic $name;";
235
		return $prop;
236
	}
237
238
	/**
239
	 * @param array $properties class varibles
240
	 * @param string $tablename database table name
241
	 * @param string $class php class name
242
	 * @return string
243
	 */
244
	protected function generateClass($properties, $tablename, $class)
245
	{
246
		$props = implode("\n", $properties);
247
		$date = date('Y-m-d h:i:s');
248
		return <<<EOD
249
			<?php
250
			/**
251
			 * Auto generated by prado-cli.php on $date.
252
			 */
253
			class $class extends TActiveRecord
254
			{
255
				const TABLE='$tablename';
256
257
			$props
258
259
				public static function finder(\$className=__CLASS__)
260
				{
261
					return parent::finder(\$className);
262
				}
263
			}
264
265
			EOD;
266
	}
267
}
268