1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* See class comment |
4
|
|
|
* |
5
|
|
|
* PHP Version 5 |
6
|
|
|
* |
7
|
|
|
* @category Netresearch |
8
|
|
|
* @package Netresearch\Kite |
9
|
|
|
* @subpackage Console |
10
|
|
|
* @author Christian Opitz <[email protected]> |
11
|
|
|
* @license http://www.netresearch.de Netresearch Copyright |
12
|
|
|
* @link http://www.netresearch.de |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace Netresearch\Kite\Console; |
16
|
|
|
use Netresearch\Kite\Console\Command\LogCommand; |
17
|
|
|
use Netresearch\Kite\Console\Output\ConsoleOutput; |
18
|
|
|
use Netresearch\Kite\Console\Output\Output; |
19
|
|
|
use Netresearch\Kite\Exception; |
20
|
|
|
use Netresearch\Kite\Service\Config; |
21
|
|
|
use Netresearch\Kite\Console\Command\JobCommand; |
22
|
|
|
use Netresearch\Kite\Service\Factory; |
23
|
|
|
use Symfony\Component\Console\Command\Command; |
24
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
25
|
|
|
use Symfony\Component\Console\Input\InputOption; |
26
|
|
|
use Symfony\Component\Console\Input\StringInput; |
27
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
28
|
|
|
use Symfony\Component\Process\Process; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Kite application |
32
|
|
|
* |
33
|
|
|
* @category Netresearch |
34
|
|
|
* @package Netresearch\Kite |
35
|
|
|
* @subpackage Console |
36
|
|
|
* @author Christian Opitz <[email protected]> |
37
|
|
|
* @license http://www.netresearch.de Netresearch Copyright |
38
|
|
|
* @link http://www.netresearch.de |
39
|
|
|
*/ |
40
|
|
|
class Application extends \Symfony\Component\Console\Application |
41
|
|
|
{ |
42
|
|
|
/** |
43
|
|
|
* @var \Netresearch\Kite\Service\Config |
44
|
|
|
*/ |
45
|
|
|
protected $config; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var Output |
49
|
|
|
*/ |
50
|
|
|
protected $output; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Application constructor. |
54
|
|
|
*/ |
55
|
|
|
public function __construct() |
56
|
|
|
{ |
57
|
|
|
$this->output = new ConsoleOutput(); |
58
|
|
|
$this->output->setTerminalDimensions($this->getTerminalDimensions()); |
59
|
|
|
|
60
|
|
|
$this->loadConfig(); |
61
|
|
|
|
62
|
|
|
parent::__construct('Kite'); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Load the configuration |
67
|
|
|
* |
68
|
|
|
* @return void |
69
|
|
|
*/ |
70
|
|
|
protected function loadConfig() |
71
|
|
|
{ |
72
|
|
|
$this->config = new Config(); |
73
|
|
|
|
74
|
|
|
$expectedFile = 'kite.php'; |
75
|
|
|
$app = null; |
76
|
|
|
$indicators = [ |
77
|
|
|
'TYPO3' => ['typo3conf', 'Kite.php'], |
78
|
|
|
'Magento' => ['app/etc', 'kite.php'], |
79
|
|
|
]; |
80
|
|
|
foreach ($indicators as $appName => $dirAndFile) { |
81
|
|
|
list($dir, $file) = $dirAndFile; |
82
|
|
|
if (is_dir($dir)) { |
83
|
|
|
$app = $appName; |
84
|
|
|
$expectedFile = $dir . '/' . $file; |
85
|
|
|
break; |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
try { |
90
|
|
|
$this->config->loadConfigFile($expectedFile); |
91
|
|
|
} catch (\Exception $e) { |
92
|
|
|
if ($app) { |
|
|
|
|
93
|
|
|
$message = [ |
94
|
|
|
'You appear to be in a ' . $app . ' root directory but', |
95
|
|
|
'there is no kite config file at the expected', |
96
|
|
|
'location (' . $expectedFile . ').' |
97
|
|
|
]; |
98
|
|
|
} else { |
99
|
|
|
$message = [ |
100
|
|
|
'You are either not in an application root directory or', |
101
|
|
|
'you have no appropriate config file yet.', |
102
|
|
|
'', |
103
|
|
|
'The config file path is expected to be:', |
104
|
|
|
]; |
105
|
|
|
foreach ($indicators as $appName => $dirAndFile) { |
106
|
|
|
$message[] = ' - "' . implode('/', $dirAndFile) . '" for ' . $appName . ' applications or'; |
107
|
|
|
} |
108
|
|
|
$message[] = ' - "' . $expectedFile . '" for any other application'; |
109
|
|
|
} |
110
|
|
|
$lMax = 0; |
111
|
|
|
foreach ($message as $line) { |
112
|
|
|
if (($l = strlen($line)) > $lMax) { |
113
|
|
|
$lMax = $l; |
114
|
|
|
} |
115
|
|
|
} |
116
|
|
|
$this->output->writeln('<warning>' . str_repeat(' ', $lMax + 4) . '</warning>'); |
117
|
|
|
foreach ($message as $line) { |
118
|
|
|
$line = str_pad($line, $lMax + 2); |
119
|
|
|
$this->output->writeln("<warning> $line</warning>"); |
120
|
|
|
} |
121
|
|
|
$this->output->writeln('<warning>' . str_repeat(' ', $lMax + 4) . '</warning>'); |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Gets the help message. |
127
|
|
|
* |
128
|
|
|
* @return string A help message. |
129
|
|
|
*/ |
130
|
|
|
public function getHelp() |
131
|
|
|
{ |
132
|
|
|
$help |
133
|
|
|
= " _ ___ _ \n" |
134
|
|
|
. "| |/ /_| |_ ___\n" |
135
|
|
|
. "| ' /| | __/ _ \\\n" |
136
|
|
|
. "| . \\| | |_| __/\n" |
137
|
|
|
. "|_|\\_|_|\\__\\___|\n\n" |
138
|
|
|
. $this->getLongVersion() . "\n\n" |
139
|
|
|
. $this->getSelfPackage()->description; |
140
|
|
|
|
141
|
|
|
return $help; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Returns the long version of the application. |
146
|
|
|
* |
147
|
|
|
* @return string The long application version |
148
|
|
|
*/ |
149
|
|
|
public function getLongVersion() |
150
|
|
|
{ |
151
|
|
|
$package = $this->getSelfPackage(); |
152
|
|
|
$v = "<info>Kite</info> version <comment>{$package->version}</comment>"; |
153
|
|
|
if (isset($package->source)) { |
154
|
|
|
$v .= " <comment>({$package->source->reference})</comment>"; |
155
|
|
|
} |
156
|
|
|
$v .= ' ' . $package->time; |
157
|
|
|
return $v; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Get package info from composer.lock |
162
|
|
|
* |
163
|
|
|
* @return object |
164
|
|
|
*/ |
165
|
|
|
protected function getSelfPackage() |
166
|
|
|
{ |
167
|
|
|
static $package = null; |
168
|
|
|
if (!$package) { |
169
|
|
|
$files = [__DIR__ . '/../../../../composer/installed.json', __DIR__ . '/vendor/composer/installed.json']; |
170
|
|
|
foreach ($files as $file) { |
171
|
|
|
if (file_exists($file)) { |
172
|
|
|
$installed = json_decode(file_get_contents($file)); |
173
|
|
|
foreach ($installed as $candidate) { |
174
|
|
|
if (substr($candidate->name, -5) === '/kite') { |
175
|
|
|
$package = $candidate; |
176
|
|
|
break 2; |
177
|
|
|
} |
178
|
|
|
} |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
if (!$package) { |
182
|
|
|
$kitePath = dirname(dirname(__DIR__)); |
183
|
|
|
$process = new Process('git symbolic-ref -q --short HEAD || git describe --tags --exact-match; git rev-parse HEAD; git show -s --format=%ct HEAD', $kitePath); |
184
|
|
|
$process->run(); |
185
|
|
|
if ($output = $process->getOutput()) { |
186
|
|
|
$package = json_decode(file_get_contents($kitePath . '/composer.json')); |
187
|
|
|
list($name, $revision, $tstamp) = explode("\n", trim($output), 3); |
188
|
|
|
$package->version = preg_match('/^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9]+)?$/i', $name) ? $name : 'dev-' . $name; |
189
|
|
|
$package->source = (object) ['reference' => $revision]; |
190
|
|
|
$package->time = date('Y-m-d H:i:s', $tstamp); |
191
|
|
|
} else { |
192
|
|
|
throw new Exception('Could not determine self version'); |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
} |
196
|
|
|
return $package; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Add workflow option |
201
|
|
|
* |
202
|
|
|
* @return \Symfony\Component\Console\Input\InputDefinition |
203
|
|
|
*/ |
204
|
|
|
protected function getDefaultInputDefinition() |
|
|
|
|
205
|
|
|
{ |
206
|
|
|
$definition = parent::getDefaultInputDefinition(); |
207
|
|
|
$definition->addOption(new InputOption('workflow', null, InputOption::VALUE_OPTIONAL, 'Run a workflow on the fly')); |
208
|
|
|
|
209
|
|
|
if (isset($_SERVER['HOME']) && is_writable($_SERVER['HOME'])) { |
210
|
|
|
$debugDir = $_SERVER['HOME'] . '/.kite/log'; |
211
|
|
|
} else { |
212
|
|
|
$debugDir = false; |
213
|
|
|
} |
214
|
|
|
$definition->addOption( |
215
|
|
|
new InputOption( |
216
|
|
|
'debug-dir', null, InputOption::VALUE_OPTIONAL, |
217
|
|
|
"Path to directory to which to dump the debug output file", |
218
|
|
|
$debugDir |
219
|
|
|
) |
220
|
|
|
); |
221
|
|
|
return $definition; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Runs the current application. |
226
|
|
|
* |
227
|
|
|
* @param InputInterface $input An Input instance |
228
|
|
|
* |
229
|
|
|
* @return int 0 if everything went fine, or an error code |
230
|
|
|
*/ |
231
|
|
|
public function run(InputInterface $input = null) |
232
|
|
|
{ |
233
|
|
|
return parent::run($input, $this->output); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* Create job on the fly when workflow option is present |
239
|
|
|
* |
240
|
|
|
* @param InputInterface $input The input |
241
|
|
|
* @param OutputInterface $output The output |
242
|
|
|
* |
243
|
|
|
* @return int |
244
|
|
|
*/ |
245
|
|
|
public function doRun(InputInterface $input, OutputInterface $output) |
246
|
|
|
{ |
247
|
|
|
if ($input->hasParameterOption('--workflow')) { |
248
|
|
|
$strInput = (string) $input; |
249
|
|
|
if ($this->getCommandName($input) === 'help') { |
250
|
|
|
$strInput = str_replace('help ', '', $strInput); |
251
|
|
|
$strInput .= ' --help'; |
252
|
|
|
} |
253
|
|
|
$workflow = $input->getParameterOption('--workflow'); |
254
|
|
|
$jobName = 'generic:workflow:' . $workflow; |
255
|
|
|
$this->config->configureJob($jobName, array('workflow' => $workflow)); |
|
|
|
|
256
|
|
|
$command = new JobCommand($jobName, $this->config); |
257
|
|
|
$this->add($command); |
258
|
|
|
|
259
|
|
|
$parameterOption = '--workflow=' . $workflow; |
260
|
|
|
$input = new StringInput( |
261
|
|
|
rtrim( |
262
|
|
|
$jobName . ' ' . |
263
|
|
|
str_replace( |
264
|
|
|
array( |
265
|
|
|
$parameterOption . ' ', |
266
|
|
|
' ' . $parameterOption, |
267
|
|
|
$parameterOption |
268
|
|
|
), '', $strInput |
269
|
|
|
) |
270
|
|
|
) |
271
|
|
|
); |
272
|
|
|
} |
273
|
|
|
return parent::doRun($input, $output); |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Gets the default commands that should always be available. |
279
|
|
|
* |
280
|
|
|
* @return Command[] An array of default Command instances |
281
|
|
|
*/ |
282
|
|
|
protected function getDefaultCommands() |
283
|
|
|
{ |
284
|
|
|
$commands = parent::getDefaultCommands(); |
285
|
|
|
$commands[] = new LogCommand(); |
286
|
|
|
|
287
|
|
|
foreach ($this->config->getJobConfiguration() as $name => $configuration) { |
288
|
|
|
$commands[] = new JobCommand($name, $this->config); |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
return $commands; |
|
|
|
|
292
|
|
|
} |
293
|
|
|
} |
294
|
|
|
?> |
295
|
|
|
|
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: