Completed
Push — master ( a15f89...abb079 )
by Craig
07:12 queued 01:36
created

ModuleController::uninstallAction()   B

Complexity

Conditions 11
Paths 19

Size

Total Lines 60
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 11
eloc 31
nc 19
nop 8
dl 0
loc 60
rs 7.3166
c 2
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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()) {
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Component\EventD...:isPropagationStopped() has been deprecated: since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

90
        if (1 === $pos && !/** @scrutinizer ignore-deprecated */ $vetoEvent->isPropagationStopped()) {

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.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like $this->getVar('itemsperpage') can also be of type false; however, parameter $limit of Zikula\ExtensionsModule\...:getPagedCollectionBy() does only seem to accept integer, 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

98
        ], /** @scrutinizer ignore-type */ $this->getVar('itemsperpage'), $pos);
Loading history...
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()) {
0 ignored issues
show
Bug introduced by
The method isClicked() does not exist on Symfony\Component\Form\FormInterface. It seems like you code against a sub-type of Symfony\Component\Form\FormInterface such as Symfony\Component\Form\SubmitButton. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

243
            if ($form->get('defaults')->/** @scrutinizer ignore-call */ isClicked()) {
Loading history...
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);
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with Zikula\Core\CoreEvents::MODULE_POSTINSTALL. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

400
                $eventDispatcher->/** @scrutinizer ignore-call */ 
401
                                  dispatch($event, CoreEvents::MODULE_POSTINSTALL);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
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