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 © 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 |
|
|
|
|
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. |
|
|
|
|
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) |
|
|
|
|
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, ' '); |
|
|
|
|
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)) |
|
|
|
|
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) |
|
|
|
|
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(); |
|
|
|
|
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(); |
|
|
|
|
673
|
|
|
$dataReader->bindColumn(1, $table); |
|
|
|
|
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
|
|
|
|
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:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths