|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
/* |
|
6
|
|
|
* This file is part of the Zikula package. |
|
7
|
|
|
* |
|
8
|
|
|
* Copyright Zikula Foundation - https://ziku.la/ |
|
9
|
|
|
* |
|
10
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
11
|
|
|
* file that was distributed with this source code. |
|
12
|
|
|
*/ |
|
13
|
|
|
|
|
14
|
|
|
namespace Zikula\ExtensionsModule\Controller; |
|
15
|
|
|
|
|
16
|
|
|
use RuntimeException; |
|
17
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; |
|
18
|
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
|
19
|
|
|
use Symfony\Component\HttpFoundation\RedirectResponse; |
|
20
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
21
|
|
|
use Symfony\Component\HttpFoundation\Response; |
|
22
|
|
|
use Symfony\Component\Routing\Annotation\Route; |
|
23
|
|
|
use Symfony\Component\Routing\Exception\RouteNotFoundException; |
|
24
|
|
|
use Symfony\Component\Routing\RouterInterface; |
|
25
|
|
|
use Symfony\Component\Security\Core\Exception\AccessDeniedException; |
|
26
|
|
|
use Zikula\BlocksModule\Entity\RepositoryInterface\BlockRepositoryInterface; |
|
27
|
|
|
use Zikula\Bundle\CoreBundle\Bundle\MetaData; |
|
28
|
|
|
use Zikula\Bundle\CoreBundle\CacheClearer; |
|
29
|
|
|
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface; |
|
30
|
|
|
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel; |
|
31
|
|
|
use Zikula\Bundle\FormExtensionBundle\Form\Type\DeletionType; |
|
32
|
|
|
use Zikula\Component\SortableColumns\Column; |
|
33
|
|
|
use Zikula\Component\SortableColumns\SortableColumns; |
|
34
|
|
|
use Zikula\Core\AbstractBundle; |
|
35
|
|
|
use Zikula\Core\Controller\AbstractController; |
|
36
|
|
|
use Zikula\Core\CoreEvents; |
|
37
|
|
|
use Zikula\Core\Event\GenericEvent; |
|
38
|
|
|
use Zikula\Core\Event\ModuleStateEvent; |
|
39
|
|
|
use Zikula\ExtensionsModule\Constant; |
|
40
|
|
|
use Zikula\ExtensionsModule\Entity\ExtensionEntity; |
|
41
|
|
|
use Zikula\ExtensionsModule\Entity\RepositoryInterface\ExtensionRepositoryInterface; |
|
42
|
|
|
use Zikula\ExtensionsModule\ExtensionEvents; |
|
43
|
|
|
use Zikula\ExtensionsModule\Form\Type\ExtensionInstallType; |
|
44
|
|
|
use Zikula\ExtensionsModule\Form\Type\ExtensionModifyType; |
|
45
|
|
|
use Zikula\ExtensionsModule\Helper\BundleSyncHelper; |
|
46
|
|
|
use Zikula\ExtensionsModule\Helper\ExtensionDependencyHelper; |
|
47
|
|
|
use Zikula\ExtensionsModule\Helper\ExtensionHelper; |
|
48
|
|
|
use Zikula\ExtensionsModule\Helper\ExtensionStateHelper; |
|
49
|
|
|
use Zikula\ThemeModule\Engine\Annotation\Theme; |
|
50
|
|
|
|
|
51
|
|
|
/** |
|
52
|
|
|
* Class ModuleController |
|
53
|
|
|
* @Route("/module") |
|
54
|
|
|
*/ |
|
55
|
|
|
class ModuleController extends AbstractController |
|
56
|
|
|
{ |
|
57
|
|
|
private const NEW_ROUTES_AVAIL = 'new.routes.avail'; |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* @Route("/list/{pos}") |
|
61
|
|
|
* @Theme("admin") |
|
62
|
|
|
* @Template("@ZikulaExtensionsModule/Module/viewModuleList.html.twig") |
|
63
|
|
|
* |
|
64
|
|
|
* @throws AccessDeniedException Thrown if the user doesn't have admin permissions for the module |
|
65
|
|
|
*/ |
|
66
|
|
|
public function viewModuleListAction( |
|
67
|
|
|
Request $request, |
|
68
|
|
|
ExtensionRepositoryInterface $extensionRepository, |
|
69
|
|
|
BundleSyncHelper $bundleSyncHelper, |
|
70
|
|
|
RouterInterface $router, |
|
71
|
|
|
int $pos = 1 |
|
72
|
|
|
): array { |
|
73
|
|
|
if (!$this->hasPermission('ZikulaExtensionsModule::', '::', ACCESS_ADMIN)) { |
|
74
|
|
|
throw new AccessDeniedException(); |
|
75
|
|
|
} |
|
76
|
|
|
$modulesJustInstalled = $request->query->get('justinstalled'); |
|
77
|
|
|
if (!empty($modulesJustInstalled)) { |
|
78
|
|
|
// notify the event dispatcher that new routes are available (ids of modules just installed avail as args) |
|
79
|
|
|
$event = new GenericEvent(null, json_decode($modulesJustInstalled)); |
|
80
|
|
|
$this->get('event_dispatcher')->dispatch($event, self::NEW_ROUTES_AVAIL); |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
|
|
$sortableColumns = new SortableColumns($router, 'zikulaextensionsmodule_module_viewmodulelist'); |
|
84
|
|
|
$sortableColumns->addColumns([new Column('displayname'), new Column('state')]); |
|
85
|
|
|
$sortableColumns->setOrderByFromRequest($request); |
|
86
|
|
|
|
|
87
|
|
|
$upgradedExtensions = []; |
|
88
|
|
|
$vetoEvent = new GenericEvent(); |
|
89
|
|
|
$this->get('event_dispatcher')->dispatch($vetoEvent, ExtensionEvents::REGENERATE_VETO); |
|
90
|
|
|
if (1 === $pos && !$vetoEvent->isPropagationStopped()) { |
|
|
|
|
|
|
91
|
|
|
// regenerate the extension list only when viewing the first page |
|
92
|
|
|
$extensionsInFileSystem = $bundleSyncHelper->scanForBundles(); |
|
93
|
|
|
$upgradedExtensions = $bundleSyncHelper->syncExtensions($extensionsInFileSystem); |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
$pagedResult = $extensionRepository->getPagedCollectionBy([], [ |
|
97
|
|
|
$sortableColumns->getSortColumn()->getName() => $sortableColumns->getSortDirection() |
|
98
|
|
|
], $this->getVar('itemsperpage'), $pos); |
|
|
|
|
|
|
99
|
|
|
|
|
100
|
|
|
$adminRoutes = []; |
|
101
|
|
|
|
|
102
|
|
|
foreach ($pagedResult as $module) { |
|
103
|
|
|
if (Constant::STATE_ACTIVE !== $module['state'] || !isset($module['capabilities']['admin']) || empty($module['capabilities']['admin'])) { |
|
104
|
|
|
continue; |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
|
|
$adminCapabilityInfo = $module['capabilities']['admin']; |
|
108
|
|
|
$adminUrl = ''; |
|
109
|
|
|
if (isset($adminCapabilityInfo['route'])) { |
|
110
|
|
|
try { |
|
111
|
|
|
$adminUrl = $router->generate($adminCapabilityInfo['route']); |
|
112
|
|
|
} catch (RouteNotFoundException $routeNotFoundException) { |
|
113
|
|
|
// do nothing, just skip this link |
|
114
|
|
|
} |
|
115
|
|
|
} elseif (isset($adminCapabilityInfo['url'])) { |
|
116
|
|
|
$adminUrl = $adminCapabilityInfo['url']; |
|
117
|
|
|
} |
|
118
|
|
|
|
|
119
|
|
|
if (!empty($adminUrl)) { |
|
120
|
|
|
$adminRoutes[$module['name']] = $adminUrl; |
|
121
|
|
|
} |
|
122
|
|
|
} |
|
123
|
|
|
|
|
124
|
|
|
return [ |
|
125
|
|
|
'sort' => $sortableColumns->generateSortableColumns(), |
|
126
|
|
|
'pager' => [ |
|
127
|
|
|
'limit' => $this->getVar('itemsperpage'), |
|
128
|
|
|
'count' => count($pagedResult) |
|
129
|
|
|
], |
|
130
|
|
|
'modules' => $pagedResult, |
|
131
|
|
|
'adminRoutes' => $adminRoutes, |
|
132
|
|
|
'upgradedExtensions' => $upgradedExtensions |
|
133
|
|
|
]; |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
/** |
|
137
|
|
|
* @Route("/modules/activate/{id}/{token}", methods = {"GET"}, requirements={"id" = "^[1-9]\d*$"}) |
|
138
|
|
|
* |
|
139
|
|
|
* Activate an extension. |
|
140
|
|
|
* |
|
141
|
|
|
* @throws AccessDeniedException Thrown if the user doesn't have admin permissions for the module |
|
142
|
|
|
*/ |
|
143
|
|
|
public function activateAction( |
|
144
|
|
|
int $id, |
|
145
|
|
|
string $token, |
|
146
|
|
|
ExtensionRepositoryInterface $extensionRepository, |
|
147
|
|
|
ExtensionStateHelper $extensionStateHelper, |
|
148
|
|
|
CacheClearer $cacheClearer |
|
149
|
|
|
): RedirectResponse { |
|
150
|
|
|
if (!$this->hasPermission('ZikulaExtensionsModule::', '::', ACCESS_ADMIN)) { |
|
151
|
|
|
throw new AccessDeniedException(); |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
if (!$this->isCsrfTokenValid('activate-extension', $token)) { |
|
155
|
|
|
throw new AccessDeniedException(); |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
/** @var ExtensionEntity $extension */ |
|
159
|
|
|
$extension = $extensionRepository->find($id); |
|
160
|
|
|
if (Constant::STATE_NOTALLOWED === $extension->getState()) { |
|
161
|
|
|
$this->addFlash('error', $this->__f('Error! Activation of module %s not allowed.', ['%s' => $extension->getName()])); |
|
162
|
|
|
} else { |
|
163
|
|
|
// Update state |
|
164
|
|
|
$extensionStateHelper->updateState($id, Constant::STATE_ACTIVE); |
|
165
|
|
|
$cacheClearer->clear('symfony.routing'); |
|
166
|
|
|
$this->addFlash('status', $this->__f('Done! Activated %s module.', ['%s' => $extension->getName()])); |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_viewmodulelist'); |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
/** |
|
173
|
|
|
* @Route("/modules/deactivate/{id}/{token}", methods = {"GET"}, requirements={"id" = "^[1-9]\d*$"}) |
|
174
|
|
|
* |
|
175
|
|
|
* Deactivate an extension |
|
176
|
|
|
* |
|
177
|
|
|
* @throws AccessDeniedException Thrown if the user doesn't have admin permissions for the module |
|
178
|
|
|
*/ |
|
179
|
|
|
public function deactivateAction( |
|
180
|
|
|
int $id, |
|
181
|
|
|
string $token, |
|
182
|
|
|
ExtensionRepositoryInterface $extensionRepository, |
|
183
|
|
|
ExtensionStateHelper $extensionStateHelper, |
|
184
|
|
|
CacheClearer $cacheClearer |
|
185
|
|
|
): RedirectResponse { |
|
186
|
|
|
if (!$this->hasPermission('ZikulaExtensionsModule::', '::', ACCESS_ADMIN)) { |
|
187
|
|
|
throw new AccessDeniedException(); |
|
188
|
|
|
} |
|
189
|
|
|
|
|
190
|
|
|
if (!$this->isCsrfTokenValid('deactivate-extension', $token)) { |
|
191
|
|
|
throw new AccessDeniedException(); |
|
192
|
|
|
} |
|
193
|
|
|
|
|
194
|
|
|
/** @var ExtensionEntity $extension */ |
|
195
|
|
|
$extension = $extensionRepository->find($id); |
|
196
|
|
|
if (null !== $extension) { |
|
197
|
|
|
if (ZikulaKernel::isCoreModule($extension->getName())) { |
|
198
|
|
|
$this->addFlash('error', $this->__f('Error! You cannot deactivate this extension [%s]. It is a mandatory core extension, and is required by the system.', ['%s' => $extension->getName()])); |
|
199
|
|
|
} else { |
|
200
|
|
|
// Update state |
|
201
|
|
|
$extensionStateHelper->updateState($id, Constant::STATE_INACTIVE); |
|
202
|
|
|
$cacheClearer->clear('symfony.routing'); |
|
203
|
|
|
$this->addFlash('status', $this->__('Done! Deactivated module.')); |
|
204
|
|
|
} |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_viewmodulelist'); |
|
208
|
|
|
} |
|
209
|
|
|
|
|
210
|
|
|
/** |
|
211
|
|
|
* @Route("/modify/{id}/{forceDefaults}", requirements={"id" = "^[1-9]\d*$", "forceDefaults" = "0|1"}) |
|
212
|
|
|
* @Theme("admin") |
|
213
|
|
|
* @Template("@ZikulaExtensionsModule/Module/modify.html.twig") |
|
214
|
|
|
* |
|
215
|
|
|
* Modify a module. |
|
216
|
|
|
* |
|
217
|
|
|
* @return array|RedirectResponse |
|
218
|
|
|
* @throws AccessDeniedException Thrown if the user doesn't have admin permissions for modifying the extension |
|
219
|
|
|
*/ |
|
220
|
|
|
public function modifyAction( |
|
221
|
|
|
Request $request, |
|
222
|
|
|
ExtensionEntity $extension, |
|
223
|
|
|
CacheClearer $cacheClearer, |
|
224
|
|
|
bool $forceDefaults = false |
|
225
|
|
|
) { |
|
226
|
|
|
if (!$this->hasPermission('ZikulaExtensionsModule::modify', $extension->getName() . '::' . $extension->getId(), ACCESS_ADMIN)) { |
|
227
|
|
|
throw new AccessDeniedException(); |
|
228
|
|
|
} |
|
229
|
|
|
|
|
230
|
|
|
/** @var AbstractBundle $bundle */ |
|
231
|
|
|
$bundle = $this->get('kernel')->getModule($extension->getName()); |
|
232
|
|
|
$metaData = $bundle->getMetaData()->getFilteredVersionInfoArray(); |
|
233
|
|
|
|
|
234
|
|
|
if ($forceDefaults) { |
|
235
|
|
|
$extension->setName($metaData['name']); |
|
236
|
|
|
$extension->setUrl($metaData['url']); |
|
237
|
|
|
$extension->setDescription($metaData['description']); |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
$form = $this->createForm(ExtensionModifyType::class, $extension); |
|
241
|
|
|
$form->handleRequest($request); |
|
242
|
|
|
if ($form->isSubmitted() && $form->isValid()) { |
|
243
|
|
|
if ($form->get('defaults')->isClicked()) { |
|
|
|
|
|
|
244
|
|
|
$this->addFlash('info', $this->__('Default values reloaded. Save to confirm.')); |
|
245
|
|
|
|
|
246
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_modify', ['id' => $extension->getId(), 'forceDefaults' => 1]); |
|
247
|
|
|
} |
|
248
|
|
|
if ($form->get('save')->isClicked()) { |
|
249
|
|
|
$em = $this->getDoctrine()->getManager(); |
|
250
|
|
|
$em->persist($extension); |
|
251
|
|
|
$em->flush(); |
|
252
|
|
|
|
|
253
|
|
|
$cacheClearer->clear('symfony.routing'); |
|
254
|
|
|
$this->addFlash('status', $this->__('Done! Extension updated.')); |
|
255
|
|
|
} |
|
256
|
|
|
if ($form->get('cancel')->isClicked()) { |
|
257
|
|
|
$this->addFlash('status', $this->__('Operation cancelled.')); |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_viewmodulelist'); |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
|
|
return [ |
|
264
|
|
|
'form' => $form->createView() |
|
265
|
|
|
]; |
|
266
|
|
|
} |
|
267
|
|
|
|
|
268
|
|
|
/** |
|
269
|
|
|
* @Route("/compatibility/{id}", methods = {"GET"}, requirements={"id" = "^[1-9]\d*$"}) |
|
270
|
|
|
* @Theme("admin") |
|
271
|
|
|
* @Template("@ZikulaExtensionsModule/Module/compatibility.html.twig") |
|
272
|
|
|
* |
|
273
|
|
|
* Display information of a module compatibility with the version of the core |
|
274
|
|
|
* |
|
275
|
|
|
* @throws AccessDeniedException Thrown if the user doesn't have admin permission to the requested module |
|
276
|
|
|
*/ |
|
277
|
|
|
public function compatibilityAction(ExtensionEntity $extension): array |
|
278
|
|
|
{ |
|
279
|
|
|
if (!$this->hasPermission('ZikulaExtensionsModule::', $extension->getName() . '::' . $extension->getId(), ACCESS_ADMIN)) { |
|
280
|
|
|
throw new AccessDeniedException(); |
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
return [ |
|
284
|
|
|
'extension' => $extension |
|
285
|
|
|
]; |
|
286
|
|
|
} |
|
287
|
|
|
|
|
288
|
|
|
/** |
|
289
|
|
|
* @Route("/install/{id}/{token}", requirements={"id" = "^[1-9]\d*$"}) |
|
290
|
|
|
* @Theme("admin") |
|
291
|
|
|
* @Template("@ZikulaExtensionsModule/Module/install.html.twig") |
|
292
|
|
|
* |
|
293
|
|
|
* Install and initialise an extension. |
|
294
|
|
|
* |
|
295
|
|
|
* @return array|RedirectResponse |
|
296
|
|
|
* @throws AccessDeniedException Thrown if the user doesn't have admin permission for the module |
|
297
|
|
|
*/ |
|
298
|
|
|
public function installAction( |
|
299
|
|
|
Request $request, |
|
300
|
|
|
ExtensionEntity $extension, |
|
301
|
|
|
string $token, |
|
302
|
|
|
ExtensionRepositoryInterface $extensionRepository, |
|
303
|
|
|
ExtensionHelper $extensionHelper, |
|
304
|
|
|
ExtensionStateHelper $extensionStateHelper, |
|
305
|
|
|
ExtensionDependencyHelper $dependencyHelper, |
|
306
|
|
|
CacheClearer $cacheClearer |
|
307
|
|
|
) { |
|
308
|
|
|
if (!$this->hasPermission('ZikulaExtensionsModule::', '::', ACCESS_ADMIN)) { |
|
309
|
|
|
throw new AccessDeniedException(); |
|
310
|
|
|
} |
|
311
|
|
|
|
|
312
|
|
|
$id = $extension->getId(); |
|
313
|
|
|
if (!$this->isCsrfTokenValid('install-extension', $token)) { |
|
314
|
|
|
throw new AccessDeniedException(); |
|
315
|
|
|
} |
|
316
|
|
|
|
|
317
|
|
|
if (!$this->get('kernel')->isBundle($extension->getName())) { |
|
318
|
|
|
$extensionStateHelper->updateState($id, Constant::STATE_TRANSITIONAL); |
|
319
|
|
|
$cacheClearer->clear('symfony'); |
|
320
|
|
|
|
|
321
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_install', ['id' => $id]); |
|
322
|
|
|
} |
|
323
|
|
|
$unsatisfiedDependencies = $dependencyHelper->getUnsatisfiedExtensionDependencies($extension); |
|
324
|
|
|
$form = $this->createForm(ExtensionInstallType::class, [ |
|
325
|
|
|
'dependencies' => $this->formatDependencyCheckboxArray($extensionRepository, $unsatisfiedDependencies) |
|
326
|
|
|
]); |
|
327
|
|
|
$hasNoUnsatisfiedDependencies = empty($unsatisfiedDependencies); |
|
328
|
|
|
$form->handleRequest($request); |
|
329
|
|
|
if ($hasNoUnsatisfiedDependencies || ($form->isSubmitted() && $form->isValid())) { |
|
330
|
|
|
if ($hasNoUnsatisfiedDependencies || $form->get('install')->isClicked()) { |
|
331
|
|
|
$extensionsInstalled = []; |
|
332
|
|
|
$data = $form->getData(); |
|
333
|
|
|
foreach ($data['dependencies'] as $dependencyId => $installSelected) { |
|
334
|
|
|
if (!$installSelected && MetaData::DEPENDENCY_REQUIRED !== $unsatisfiedDependencies[$dependencyId]->getStatus()) { |
|
335
|
|
|
continue; |
|
336
|
|
|
} |
|
337
|
|
|
$dependencyExtensionEntity = $extensionRepository->get($unsatisfiedDependencies[$dependencyId]->getModname()); |
|
338
|
|
|
if (isset($dependencyExtensionEntity)) { |
|
339
|
|
|
if (!$extensionHelper->install($dependencyExtensionEntity)) { |
|
340
|
|
|
$this->addFlash('error', $this->__f('Failed to install dependency %s!', ['%s' => $dependencyExtensionEntity->getName()])); |
|
341
|
|
|
|
|
342
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_viewmodulelist'); |
|
343
|
|
|
} |
|
344
|
|
|
$extensionsInstalled[] = $dependencyExtensionEntity->getId(); |
|
345
|
|
|
$this->addFlash('status', $this->__f('Installed dependency %s.', ['%s' => $dependencyExtensionEntity->getName()])); |
|
346
|
|
|
} else { |
|
347
|
|
|
$this->addFlash('warning', $this->__f('Warning: could not install selected dependency %s', ['%s' => $unsatisfiedDependencies[$dependencyId]->getModname()])); |
|
348
|
|
|
} |
|
349
|
|
|
} |
|
350
|
|
|
if ($extensionHelper->install($extension)) { |
|
351
|
|
|
$this->addFlash('status', $this->__f('Done! Installed %s.', ['%s' => $extension->getName()])); |
|
352
|
|
|
$extensionsInstalled[] = $id; |
|
353
|
|
|
$cacheClearer->clear('symfony'); |
|
354
|
|
|
|
|
355
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_postinstall', ['extensions' => json_encode($extensionsInstalled)]); |
|
356
|
|
|
} |
|
357
|
|
|
$extensionStateHelper->updateState($id, Constant::STATE_UNINITIALISED); |
|
358
|
|
|
$this->addFlash('error', $this->__f('Initialization of %s failed!', ['%s' => $extension->getName()])); |
|
359
|
|
|
} |
|
360
|
|
|
if ($form->get('cancel')->isClicked()) { |
|
361
|
|
|
$extensionStateHelper->updateState($id, Constant::STATE_UNINITIALISED); |
|
362
|
|
|
$this->addFlash('status', $this->__('Operation cancelled.')); |
|
363
|
|
|
} |
|
364
|
|
|
|
|
365
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_viewmodulelist'); |
|
366
|
|
|
} |
|
367
|
|
|
|
|
368
|
|
|
return [ |
|
369
|
|
|
'dependencies' => $unsatisfiedDependencies, |
|
370
|
|
|
'extension' => $extension, |
|
371
|
|
|
'form' => $form->createView() |
|
372
|
|
|
]; |
|
373
|
|
|
} |
|
374
|
|
|
|
|
375
|
|
|
/** |
|
376
|
|
|
* Post-installation action to trigger the MODULE_POSTINSTALL event. |
|
377
|
|
|
* The additional Action is required because this event must occur AFTER the rebuild of the cache which occurs on Request. |
|
378
|
|
|
* |
|
379
|
|
|
* @Route("/postinstall/{extensions}", methods = {"GET"}) |
|
380
|
|
|
*/ |
|
381
|
|
|
public function postInstallAction( |
|
382
|
|
|
ExtensionRepositoryInterface $extensionRepository, |
|
383
|
|
|
ZikulaHttpKernelInterface $kernel, |
|
384
|
|
|
EventDispatcherInterface $eventDispatcher, |
|
385
|
|
|
string $extensions = null |
|
386
|
|
|
): RedirectResponse { |
|
387
|
|
|
if (!empty($extensions)) { |
|
388
|
|
|
$extensions = json_decode($extensions); |
|
389
|
|
|
foreach ($extensions as $extensionId) { |
|
390
|
|
|
/** @var ExtensionEntity $extensionEntity */ |
|
391
|
|
|
$extensionEntity = $extensionRepository->find($extensionId); |
|
392
|
|
|
if (null === $extensionRepository) { |
|
393
|
|
|
continue; |
|
394
|
|
|
} |
|
395
|
|
|
$bundle = $kernel->getModule($extensionEntity->getName()); |
|
396
|
|
|
if (null === $bundle) { |
|
397
|
|
|
continue; |
|
398
|
|
|
} |
|
399
|
|
|
$event = new ModuleStateEvent($bundle, $extensionEntity->toArray()); |
|
400
|
|
|
$eventDispatcher->dispatch($event, CoreEvents::MODULE_POSTINSTALL); |
|
|
|
|
|
|
401
|
|
|
} |
|
402
|
|
|
// currently commented out because it takes a long time. |
|
403
|
|
|
//$extensionHelper->installAssets(); |
|
404
|
|
|
} |
|
405
|
|
|
|
|
406
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_viewmodulelist', ['justinstalled' => json_encode($extensions)]); |
|
407
|
|
|
} |
|
408
|
|
|
|
|
409
|
|
|
/** |
|
410
|
|
|
* Create array suitable for checkbox FormType [[ID => bool][ID => bool]]. |
|
411
|
|
|
*/ |
|
412
|
|
|
private function formatDependencyCheckboxArray( |
|
413
|
|
|
ExtensionRepositoryInterface $extensionRepository, |
|
414
|
|
|
array $dependencies |
|
415
|
|
|
): array { |
|
416
|
|
|
$return = []; |
|
417
|
|
|
foreach ($dependencies as $dependency) { |
|
418
|
|
|
/** @var ExtensionEntity $dependencyExtension */ |
|
419
|
|
|
$dependencyExtension = $extensionRepository->get($dependency->getModname()); |
|
420
|
|
|
$return[$dependency->getId()] = null !== $dependencyExtension; |
|
421
|
|
|
} |
|
422
|
|
|
|
|
423
|
|
|
return $return; |
|
424
|
|
|
} |
|
425
|
|
|
|
|
426
|
|
|
/** |
|
427
|
|
|
* @Route("/upgrade/{id}/{token}", requirements={"id" = "^[1-9]\d*$"}) |
|
428
|
|
|
* |
|
429
|
|
|
* Upgrade an extension. |
|
430
|
|
|
* |
|
431
|
|
|
* @throws AccessDeniedException Thrown if the user doesn't have admin permission for the module |
|
432
|
|
|
*/ |
|
433
|
|
|
public function upgradeAction( |
|
434
|
|
|
ExtensionEntity $extension, |
|
435
|
|
|
$token, |
|
436
|
|
|
ExtensionHelper $extensionHelper |
|
437
|
|
|
): RedirectResponse { |
|
438
|
|
|
if (!$this->hasPermission('ZikulaExtensionsModule::', '::', ACCESS_ADMIN)) { |
|
439
|
|
|
throw new AccessDeniedException(); |
|
440
|
|
|
} |
|
441
|
|
|
|
|
442
|
|
|
if (!$this->isCsrfTokenValid('upgrade-extension', $token)) { |
|
443
|
|
|
throw new AccessDeniedException(); |
|
444
|
|
|
} |
|
445
|
|
|
|
|
446
|
|
|
$result = $extensionHelper->upgrade($extension); |
|
447
|
|
|
if ($result) { |
|
448
|
|
|
$this->addFlash('status', $this->__f('%name% upgraded to new version and activated.', ['%name%' => $extension->getDisplayname()])); |
|
449
|
|
|
} else { |
|
450
|
|
|
$this->addFlash('error', $this->__('Extension upgrade failed!')); |
|
451
|
|
|
} |
|
452
|
|
|
|
|
453
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_viewmodulelist'); |
|
454
|
|
|
} |
|
455
|
|
|
|
|
456
|
|
|
/** |
|
457
|
|
|
* @Route("/uninstall/{id}/{token}", requirements={"id" = "^[1-9]\d*$"}) |
|
458
|
|
|
* @Theme("admin") |
|
459
|
|
|
* @Template("@ZikulaExtensionsModule/Module/uninstall.html.twig") |
|
460
|
|
|
* |
|
461
|
|
|
* Uninstall an extension. |
|
462
|
|
|
* |
|
463
|
|
|
* @return array|Response|RedirectResponse |
|
464
|
|
|
* @throws AccessDeniedException Thrown if the user doesn't have admin permission for the module |
|
465
|
|
|
*/ |
|
466
|
|
|
public function uninstallAction( |
|
467
|
|
|
Request $request, |
|
468
|
|
|
ExtensionEntity $extension, |
|
469
|
|
|
string $token, |
|
470
|
|
|
BlockRepositoryInterface $blockRepository, |
|
471
|
|
|
ExtensionHelper $extensionHelper, |
|
472
|
|
|
ExtensionStateHelper $extensionStateHelper, |
|
473
|
|
|
ExtensionDependencyHelper $dependencyHelper, |
|
474
|
|
|
CacheClearer $cacheClearer |
|
475
|
|
|
) { |
|
476
|
|
|
if (!$this->hasPermission('ZikulaExtensionsModule::', '::', ACCESS_ADMIN)) { |
|
477
|
|
|
throw new AccessDeniedException(); |
|
478
|
|
|
} |
|
479
|
|
|
|
|
480
|
|
|
if (!$this->isCsrfTokenValid('uninstall-extension', $token)) { |
|
481
|
|
|
throw new AccessDeniedException(); |
|
482
|
|
|
} |
|
483
|
|
|
|
|
484
|
|
|
if (Constant::STATE_MISSING === $extension->getState()) { |
|
485
|
|
|
throw new RuntimeException($this->__('Error! The requested extension cannot be uninstalled because its files are missing!')); |
|
486
|
|
|
} |
|
487
|
|
|
if (!$this->get('kernel')->isBundle($extension->getName())) { |
|
488
|
|
|
$extensionStateHelper->updateState($extension->getId(), Constant::STATE_TRANSITIONAL); |
|
489
|
|
|
$cacheClearer->clear('symfony'); |
|
490
|
|
|
} |
|
491
|
|
|
$requiredDependents = $dependencyHelper->getDependentExtensions($extension); |
|
492
|
|
|
$blocks = $blockRepository->findBy(['module' => $extension]); |
|
493
|
|
|
|
|
494
|
|
|
$form = $this->createForm(DeletionType::class); |
|
495
|
|
|
$form->handleRequest($request); |
|
496
|
|
|
if ($form->isSubmitted() && $form->isValid()) { |
|
497
|
|
|
if ($form->get('delete')->isClicked()) { |
|
498
|
|
|
// remove dependent extensions |
|
499
|
|
|
if (!$extensionHelper->uninstallArray($requiredDependents)) { |
|
500
|
|
|
$this->addFlash('error', $this->__('Error: Could not uninstall dependent extensions.')); |
|
501
|
|
|
|
|
502
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_viewmodulelist'); |
|
503
|
|
|
} |
|
504
|
|
|
// remove blocks |
|
505
|
|
|
$blockRepository->remove($blocks); |
|
506
|
|
|
|
|
507
|
|
|
// remove the extension |
|
508
|
|
|
if ($extensionHelper->uninstall($extension)) { |
|
509
|
|
|
$this->addFlash('status', $this->__('Done! Uninstalled extension.')); |
|
510
|
|
|
} else { |
|
511
|
|
|
$this->addFlash('error', $this->__('Extension removal failed! (note: blocks and dependents may have been removed)')); |
|
512
|
|
|
} |
|
513
|
|
|
} |
|
514
|
|
|
if ($form->get('cancel')->isClicked()) { |
|
515
|
|
|
$this->addFlash('status', $this->__('Operation cancelled.')); |
|
516
|
|
|
} |
|
517
|
|
|
|
|
518
|
|
|
return $this->redirectToRoute('zikulaextensionsmodule_module_viewmodulelist'); |
|
519
|
|
|
} |
|
520
|
|
|
|
|
521
|
|
|
return [ |
|
522
|
|
|
'form' => $form->createView(), |
|
523
|
|
|
'extension' => $extension, |
|
524
|
|
|
'blocks' => $blocks, |
|
525
|
|
|
'requiredDependents' => $requiredDependents |
|
526
|
|
|
]; |
|
527
|
|
|
} |
|
528
|
|
|
} |
|
529
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.