1
|
|
|
<?php |
2
|
|
|
namespace Etobi\CoreAPI\Command; |
3
|
|
|
|
4
|
|
|
/*************************************************************** |
5
|
|
|
* Copyright notice |
6
|
|
|
* |
7
|
|
|
* (c) 2012 Georg Ringer <[email protected]> |
8
|
|
|
* (c) 2014 Stefano Kowalke <[email protected]> |
9
|
|
|
* All rights reserved |
10
|
|
|
* |
11
|
|
|
* This script is part of the TYPO3 project. The TYPO3 project is |
12
|
|
|
* free software; you can redistribute it and/or modify |
13
|
|
|
* it under the terms of the GNU General Public License as published by |
14
|
|
|
* the Free Software Foundation; either version 2 of the License, or |
15
|
|
|
* (at your option) any later version. |
16
|
|
|
* |
17
|
|
|
* The GNU General Public License can be found at |
18
|
|
|
* http://www.gnu.org/copyleft/gpl.html. |
19
|
|
|
* |
20
|
|
|
* This script is distributed in the hope that it will be useful, |
21
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
22
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23
|
|
|
* GNU General Public License for more details. |
24
|
|
|
* |
25
|
|
|
* This copyright notice MUST APPEAR in all copies of the script! |
26
|
|
|
***************************************************************/ |
27
|
|
|
use Exception; |
28
|
|
|
use InvalidArgumentException; |
29
|
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility; |
30
|
|
|
use TYPO3\CMS\Extbase\Mvc\Controller\CommandController; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Extension API Command Controller |
34
|
|
|
* |
35
|
|
|
* @author Georg Ringer <[email protected]> |
36
|
|
|
* @author Stefano Kowalke <[email protected]> |
37
|
|
|
* @package Etobi\CoreAPI\Service\SiteApiService |
38
|
|
|
*/ |
39
|
|
|
class ExtensionApiCommandController extends CommandController { |
40
|
|
|
|
41
|
|
|
const MAXIMUM_LINE_LENGTH = 79; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @var \TYPO3\CMS\Core\Log\LogManager $logManager |
45
|
|
|
*/ |
46
|
|
|
protected $logManager; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var \TYPO3\CMS\Core\Log\Logger $logger |
50
|
|
|
*/ |
51
|
|
|
protected $logger; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @param \TYPO3\CMS\Core\Log\LogManager $logManager |
55
|
|
|
* |
56
|
|
|
* @return void |
57
|
|
|
*/ |
58
|
|
|
public function injectLogManager(\TYPO3\CMS\Core\Log\LogManager $logManager) { |
59
|
|
|
$this->logManager = $logManager; |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Initialize the object |
64
|
|
|
*/ |
65
|
|
|
public function initializeObject() { |
66
|
|
|
$this->logger = $this->objectManager->get('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @var \Etobi\CoreAPI\Service\ExtensionApiService |
71
|
|
|
* @inject |
72
|
|
|
*/ |
73
|
|
|
protected $extensionApiService; |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher |
77
|
|
|
* @inject |
78
|
|
|
*/ |
79
|
|
|
protected $signalSlotDispatcher; |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Information about an extension. |
83
|
|
|
* |
84
|
|
|
* @param string $key The extension key |
85
|
|
|
* |
86
|
|
|
* @return void |
87
|
|
|
*/ |
88
|
|
|
public function infoCommand($key) { |
|
|
|
|
89
|
|
|
$data = array(); |
90
|
|
|
try { |
91
|
|
|
$data = $this->extensionApiService->getExtensionInformation($key); |
92
|
|
|
} catch (Exception $e) { |
93
|
|
|
$message = $e->getMessage(); |
94
|
|
|
$this->outputLine($message); |
95
|
|
|
$this->logger->error($message); |
96
|
|
|
$this->quit(1); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
$this->outputLine(''); |
100
|
|
|
$this->outputLine('EXTENSION "%s": %s %s', array(strtoupper($key), $data['em_conf']['version'], $data['em_conf']['state'])); |
101
|
|
|
$this->outputLine(str_repeat('-', $this->output->getMaximumLineLength())); |
102
|
|
|
|
103
|
|
|
$outputInformation = array(); |
104
|
|
|
$outputInformation['is installed'] = ($data['is_installed'] ? 'yes' : 'no'); |
105
|
|
|
if (!empty($data['em_conf'])) { |
106
|
|
|
foreach ($data['em_conf'] as $emConfKey => $emConfValue) { |
107
|
|
|
// Skip empty properties |
108
|
|
|
if (empty($emConfValue)) { |
109
|
|
|
continue; |
110
|
|
|
} |
111
|
|
|
// Skip properties which are already handled |
112
|
|
|
if ($emConfKey === 'title' || $emConfKey === 'version' || $emConfKey === 'state') { |
113
|
|
|
continue; |
114
|
|
|
} |
115
|
|
|
$outputInformation[$emConfKey] = $emConfValue; |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
foreach ($outputInformation as $outputKey => $outputValue) { |
120
|
|
|
$description = ''; |
121
|
|
|
if (is_array($outputValue)) { |
122
|
|
|
foreach ($outputValue as $additionalKey => $additionalValue) { |
123
|
|
|
if (is_array($additionalValue)) { |
124
|
|
|
|
125
|
|
|
if (empty($additionalValue)) { |
126
|
|
|
continue; |
127
|
|
|
} |
128
|
|
|
$description .= LF . str_repeat(' ', 28) . $additionalKey; |
129
|
|
|
$description .= LF; |
130
|
|
|
foreach ($additionalValue as $ak => $av) { |
131
|
|
|
$description .= str_repeat(' ', 30) . $ak . ': ' . $av . LF; |
132
|
|
|
} |
133
|
|
|
} else { |
134
|
|
|
$description .= LF . str_repeat(' ', 28) . $additionalKey . ': ' . $additionalValue; |
135
|
|
|
} |
136
|
|
|
} |
137
|
|
|
} else { |
138
|
|
|
$description = wordwrap($outputValue, $this->output->getMaximumLineLength() - 28, PHP_EOL . str_repeat(' ', 28), TRUE); |
139
|
|
|
} |
140
|
|
|
$this->outputLine('%-2s%-25s %s', array(' ', $outputKey, $description)); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
$this->logger->info('extensionApi:info executes successfully.'); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* List all installed extensions. |
148
|
|
|
* |
149
|
|
|
* @param string $type Extension type, can either be "Local", |
150
|
|
|
* "System" or "Global". Leave it empty for all |
151
|
|
|
* |
152
|
|
|
* @return void |
153
|
|
|
*/ |
154
|
|
|
public function listInstalledCommand($type = '') { |
155
|
|
|
$type = ucfirst(strtolower($type)); |
156
|
|
|
if (!empty($type) && $type !== 'Local' && $type !== 'Global' && $type !== 'System') { |
157
|
|
|
// TODO: Throw a exception here? |
158
|
|
|
$message = 'Only "Local", "System" and "Global" are supported as type (or nothing)'; |
159
|
|
|
$this->outputLine($message); |
160
|
|
|
$this->logger->error($message); |
161
|
|
|
$this->quit(1); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
$extensions = $this->extensionApiService->listExtensions($type); |
165
|
|
|
|
166
|
|
|
foreach ($extensions as $key => $details) { |
167
|
|
|
$title = $key . ' - ' . $details['version'] . '/' . $details['state']; |
168
|
|
|
$description = $details['title']; |
169
|
|
|
$description = wordwrap($description, $this->output->getMaximumLineLength() - 43, PHP_EOL . str_repeat(' ', 43), TRUE); |
170
|
|
|
$this->outputLine('%-2s%-40s %s', array(' ', $title, $description)); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
$this->outputLine('%-2s%-40s', array(' ', str_repeat('-', $this->output->getMaximumLineLength() - 3))); |
174
|
|
|
$this->outputLine(' Total: ' . count($extensions) . ' extensions'); |
175
|
|
|
$this->logger->info('extensionApi:listInstalled executed successfully'); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Update list. |
180
|
|
|
* |
181
|
|
|
* @return void |
182
|
|
|
*/ |
183
|
|
|
public function updateListCommand() { |
184
|
|
|
$this->outputLine('This may take a while...'); |
185
|
|
|
$result = $this->extensionApiService->updateMirrors(); |
186
|
|
|
|
187
|
|
View Code Duplication |
if ($result) { |
|
|
|
|
188
|
|
|
$message = 'Extension list has been updated.'; |
189
|
|
|
$this->outputLine($message); |
190
|
|
|
$this->logger->info($message); |
191
|
|
|
} else { |
192
|
|
|
$message = 'Extension list already up-to-date.'; |
193
|
|
|
$this->outputLine($message); |
194
|
|
|
$this->logger->info($message); |
195
|
|
|
} |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Install(activate) an extension. |
200
|
|
|
* |
201
|
|
|
* @param string $key The extension key |
202
|
|
|
* |
203
|
|
|
* @return void |
204
|
|
|
*/ |
205
|
|
View Code Duplication |
public function installCommand($key) { |
|
|
|
|
206
|
|
|
try { |
207
|
|
|
$this->emitPackagesMayHaveChangedSignal(); |
208
|
|
|
$this->extensionApiService->installExtension($key); |
209
|
|
|
} catch (Exception $e) { |
210
|
|
|
$message = $e->getMessage(); |
211
|
|
|
$this->outputLine($message); |
212
|
|
|
$this->logger->error($message); |
213
|
|
|
$this->quit(1); |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
$message = sprintf('Extension "%s" is now installed!', $key); |
217
|
|
|
$this->outputLine($message); |
218
|
|
|
$this->logger->info($message); |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* UnInstall(deactivate) an extension. |
223
|
|
|
* |
224
|
|
|
* @param string $key The extension key |
225
|
|
|
* |
226
|
|
|
* @return void |
227
|
|
|
*/ |
228
|
|
View Code Duplication |
public function uninstallCommand($key) { |
|
|
|
|
229
|
|
|
try { |
230
|
|
|
$this->extensionApiService->uninstallExtension($key); |
231
|
|
|
} catch (Exception $e) { |
232
|
|
|
$message = $e->getMessage(); |
233
|
|
|
$this->outputLine($message); |
234
|
|
|
$this->logger->error($message); |
235
|
|
|
$this->quit(1); |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
$message = sprintf('Extension "%s" is now uninstalled!', $key); |
239
|
|
|
$this->outputLine($message); |
240
|
|
|
$this->logger->info($message); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Configure an extension. |
245
|
|
|
* This command enables you to configure an extension. |
246
|
|
|
* |
247
|
|
|
* <code> |
248
|
|
|
* [1] Using a standard formatted ini-file |
249
|
|
|
* ./cli_dispatch.phpsh extbase extensionapi:configure rtehtmlarea --configfile=C:\rteconf.txt |
250
|
|
|
* |
251
|
|
|
* [2] Adding configuration settings directly on the command line |
252
|
|
|
* ./cli_dispatch.phpsh extbase extensionapi:configure rtehtmlarea --settings="enableImages=1;allowStyleAttribute=0" |
253
|
|
|
* |
254
|
|
|
* [3] A combination of [1] and [2] |
255
|
|
|
* ./cli_dispatch.phpsh extbase extensionapi:configure rtehtmlarea --configfile=C:\rteconf.txt --settings="enableImages=1;allowStyleAttribute=0" |
256
|
|
|
* </code> |
257
|
|
|
* |
258
|
|
|
* @param string $key The extension key |
259
|
|
|
* @param string $configFile Path to file containing configuration settings. Must be formatted as a standard ini-file |
260
|
|
|
* @param string $settings String containing configuration settings separated on the form "k1=v1;k2=v2;" |
261
|
|
|
* |
262
|
|
|
* @return void |
263
|
|
|
*/ |
264
|
|
|
public function configureCommand($key, $configFile = '', $settings = '') { |
265
|
|
|
try { |
266
|
|
|
$conf = array(); |
267
|
|
|
if (is_file($configFile)) { |
268
|
|
|
$conf = parse_ini_file($configFile); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
if (strlen($settings)) { |
272
|
|
|
$arr = explode(';', $settings); |
273
|
|
|
foreach ($arr as $v) { |
274
|
|
|
if (strpos($v, '=') === FALSE) { |
275
|
|
|
throw new InvalidArgumentException(sprintf('Ill-formed setting "%s"!', $v)); |
276
|
|
|
} |
277
|
|
|
$parts = GeneralUtility::trimExplode('=', $v, FALSE, 2); |
278
|
|
|
if (!empty($parts[0])) { |
279
|
|
|
$conf[$parts[0]] = $parts[1]; |
280
|
|
|
} |
281
|
|
|
} |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
if (empty($conf)) { |
285
|
|
|
$this->response->setExitCode(1); |
286
|
|
|
$message = sprintf('No configuration settings!', $key); |
287
|
|
|
$this->logger->error($message); |
288
|
|
|
throw new InvalidArgumentException($message); |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
$this->extensionApiService->configureExtension($key, $conf); |
292
|
|
|
|
293
|
|
|
} catch (Exception $e) { |
294
|
|
|
$message = $e->getMessage(); |
295
|
|
|
$this->outputLine($message); |
296
|
|
|
$this->logger->error($message); |
297
|
|
|
$this->quit(1); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
$message = sprintf('Extension "%s" has been configured!', $key); |
301
|
|
|
$this->outputLine($message); |
302
|
|
|
$this->logger->info($message); |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* Fetch an extension from TER. |
307
|
|
|
* |
308
|
|
|
* @param string $key The extension key |
309
|
|
|
* @param string $version The exact version of the extension, otherwise the latest will be picked |
310
|
|
|
* @param string $location Where to put the extension. System = typo3/sysext, Global = typo3/ext, Local = typo3conf/ext |
311
|
|
|
* @param bool $overwrite Overwrite the extension if already exists |
312
|
|
|
* @param int $mirror Mirror to fetch the extension from. Run extensionapi:listmirrors to get the list of all available repositories, otherwise a random mirror will be selected |
313
|
|
|
* |
314
|
|
|
* @return void |
315
|
|
|
*/ |
316
|
|
|
public function fetchCommand($key, $version = '', $location = 'Local', $overwrite = FALSE, $mirror = -1) { |
317
|
|
|
try { |
318
|
|
|
$data = $this->extensionApiService->fetchExtension($key, $version, $location, $overwrite, $mirror); |
319
|
|
|
$message = sprintf('Extension "%s" version %s has been fetched from repository! Dependencies were not resolved.', $data['main']['extKey'], $data['main']['version']); |
320
|
|
|
$this->outputLine($message); |
321
|
|
|
$this->logger->info($message); |
322
|
|
|
} catch (Exception $e) { |
323
|
|
|
$message = $e->getMessage(); |
324
|
|
|
$this->outputLine($message); |
325
|
|
|
$this->logger->error($message); |
326
|
|
|
$this->quit(1); |
327
|
|
|
} |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* Lists the possible mirrors |
332
|
|
|
* |
333
|
|
|
* @return void |
334
|
|
|
*/ |
335
|
|
|
public function listMirrorsCommand() { |
336
|
|
|
try { |
337
|
|
|
$mirrors = $this->extensionApiService->listMirrors(); |
338
|
|
|
$key = 0; |
339
|
|
|
foreach ($mirrors as $mirror) { |
340
|
|
|
$this->outputLine($key . ' = ' . $mirror['title'] . ' ' . $mirror['host']); |
341
|
|
|
++$key; |
342
|
|
|
} |
343
|
|
|
} catch (Exception $e) { |
344
|
|
|
$message = $e->getMessage(); |
345
|
|
|
$this->outputLine($message); |
346
|
|
|
$this->logger->error($message); |
347
|
|
|
$this->quit(1); |
348
|
|
|
} |
349
|
|
|
$this->logger->info('extensionApi:listMirrors executed successfully.'); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
/** |
353
|
|
|
* Import extension from file. |
354
|
|
|
* |
355
|
|
|
* @param string $file Path to t3x file |
356
|
|
|
* @param string $location Where to import the extension. System = typo3/sysext, Global = typo3/ext, Local = typo3conf/ext |
357
|
|
|
* @param boolean $overwrite Overwrite the extension if already exists |
358
|
|
|
* |
359
|
|
|
* @return void |
360
|
|
|
*/ |
361
|
|
View Code Duplication |
public function importCommand($file, $location = 'Local', $overwrite = FALSE) { |
|
|
|
|
362
|
|
|
try { |
363
|
|
|
$data = $this->extensionApiService->importExtension($file, $location, $overwrite); |
364
|
|
|
$message = sprintf('Extension "%s" has been imported!', $data['extKey']); |
365
|
|
|
$this->outputLine($message); |
366
|
|
|
$this->logger->info($message); |
367
|
|
|
} catch (Exception $e) { |
368
|
|
|
$this->outputLine($e->getMessage()); |
369
|
|
|
$this->logger->error($e->getMessage()); |
370
|
|
|
$this->quit(1); |
371
|
|
|
} |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
/** |
375
|
|
|
* Emits packages may have changed signal |
376
|
|
|
* |
377
|
|
|
* @return \Etobi\CoreAPI\Service\ExtensionApiService object |
378
|
|
|
*/ |
379
|
|
|
protected function emitPackagesMayHaveChangedSignal() { |
380
|
|
|
$this->signalSlotDispatcher->dispatch('PackageManagement', 'packagesMayHaveChanged'); |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
|
A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.
You can also find more information in the “Code” section of your repository.