Completed
Pull Request — master (#4264)
by Craig
05:51
created

ExtensionController   F

Complexity

Total Complexity 61

Size/Duplication

Total Lines 481
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 187
dl 0
loc 481
rs 3.52
c 1
b 0
f 0
wmc 61

12 Methods

Rating   Name   Duplication   Size   Complexity  
A activateAction() 0 25 3
A compatibilityAction() 0 8 2
A listAction() 0 38 4
B modifyAction() 0 45 8
A deactivateAction() 0 32 5
C installAction() 0 89 17
A upgradeAction() 0 17 3
B uninstallAction() 0 61 10
A postInstallAction() 0 24 5
A postUninstallAction() 0 5 1
A previewAction() 0 6 1
A formatDependencyCheckboxArray() 0 12 2

How to fix   Complexity   

Complex Class

Complex classes like ExtensionController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ExtensionController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula - 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 Psr\Log\LoggerInterface;
17
use RuntimeException;
18
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
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\RouterInterface;
24
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
25
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
26
use Zikula\BlocksModule\Entity\RepositoryInterface\BlockRepositoryInterface;
27
use Zikula\Bundle\CoreBundle\CacheClearer;
28
use Zikula\Bundle\CoreBundle\Composer\MetaData;
29
use Zikula\Bundle\CoreBundle\Controller\AbstractController;
30
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
31
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel;
32
use Zikula\Bundle\FormExtensionBundle\Form\Type\DeletionType;
33
use Zikula\Component\SortableColumns\Column;
34
use Zikula\Component\SortableColumns\SortableColumns;
35
use Zikula\ExtensionsModule\AbstractExtension;
36
use Zikula\ExtensionsModule\Api\VariableApi;
37
use Zikula\ExtensionsModule\Constant;
38
use Zikula\ExtensionsModule\Entity\ExtensionEntity;
39
use Zikula\ExtensionsModule\Entity\RepositoryInterface\ExtensionRepositoryInterface;
40
use Zikula\ExtensionsModule\Event\ExtensionListPreReSyncEvent;
41
use Zikula\ExtensionsModule\Event\ExtensionPostCacheRebuildEvent;
42
use Zikula\ExtensionsModule\Form\Type\ExtensionInstallType;
43
use Zikula\ExtensionsModule\Form\Type\ExtensionModifyType;
44
use Zikula\ExtensionsModule\Helper\BundleSyncHelper;
45
use Zikula\ExtensionsModule\Helper\ExtensionDependencyHelper;
46
use Zikula\ExtensionsModule\Helper\ExtensionHelper;
47
use Zikula\ExtensionsModule\Helper\ExtensionStateHelper;
48
use Zikula\PermissionsModule\Annotation\PermissionCheck;
49
use Zikula\RoutesModule\Event\RoutesNewlyAvailableEvent;
50
use Zikula\ThemeModule\Engine\Annotation\Theme;
51
use Zikula\ThemeModule\Engine\Engine;
52
53
/**
54
 * @Route("")
55
 */
56
class ExtensionController extends AbstractController
57
{
58
    /**
59
     * @Route("/list/{page}", methods = {"GET"}, requirements={"page" = "\d+"})
60
     * @PermissionCheck("admin")
61
     * @Theme("admin")
62
     * @Template("@ZikulaExtensionsModule/Extension/list.html.twig")
63
     */
64
    public function listAction(
65
        Request $request,
66
        EventDispatcherInterface $eventDispatcher,
67
        ExtensionRepositoryInterface $extensionRepository,
68
        BundleSyncHelper $bundleSyncHelper,
69
        RouterInterface $router,
70
        int $page = 1
71
    ): array {
72
        $modulesJustInstalled = $request->query->get('justinstalled');
73
        if (!empty($modulesJustInstalled)) {
74
            // notify the event dispatcher that new routes are available (ids of modules just installed avail as args)
75
            $eventDispatcher->dispatch(new RoutesNewlyAvailableEvent(json_decode($modulesJustInstalled)));
76
        }
77
78
        $sortableColumns = new SortableColumns($router, 'zikulaextensionsmodule_extension_list');
79
        $sortableColumns->addColumns([new Column('displayname'), new Column('state')]);
80
        $sortableColumns->setOrderByFromRequest($request);
81
82
        $upgradedExtensions = [];
83
        $extensionListPreReSyncEvent = new ExtensionListPreReSyncEvent();
84
        $eventDispatcher->dispatch($extensionListPreReSyncEvent);
85
        if (1 === $page && !$extensionListPreReSyncEvent->isPropagationStopped()) {
86
            // regenerate the extension list only when viewing the first page
87
            $extensionsInFileSystem = $bundleSyncHelper->scanForBundles();
88
            $upgradedExtensions = $bundleSyncHelper->syncExtensions($extensionsInFileSystem);
89
        }
90
91
        $pageSize = $this->getVar('itemsperpage');
92
93
        $paginator = $extensionRepository->getPagedCollectionBy([], [
94
            $sortableColumns->getSortColumn()->getName() => $sortableColumns->getSortDirection()
95
        ], $page, $pageSize);
0 ignored issues
show
Bug introduced by
It seems like $pageSize can also be of type false; however, parameter $pageSize 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

95
        ], $page, /** @scrutinizer ignore-type */ $pageSize);
Loading history...
96
        $paginator->setRoute('zikulaextensionsmodule_extension_list');
97
98
        return [
99
            'sort' => $sortableColumns->generateSortableColumns(),
100
            'paginator' => $paginator,
101
            'upgradedExtensions' => $upgradedExtensions
102
        ];
103
    }
104
105
    /**
106
     * @Route("/activate/{id}/{token}", methods = {"GET"}, requirements={"id" = "^[1-9]\d*$"})
107
     * @PermissionCheck("admin")
108
     *
109
     * Activate an extension.
110
     *
111
     * @throws AccessDeniedException Thrown if the CSRF token is invalid
112
     */
113
    public function activateAction(
114
        int $id,
115
        string $token,
116
        ExtensionRepositoryInterface $extensionRepository,
117
        ExtensionStateHelper $extensionStateHelper,
118
        LoggerInterface $zikulaLogger,
119
        CacheClearer $cacheClearer
120
    ): RedirectResponse {
121
        if (!$this->isCsrfTokenValid('activate-extension', $token)) {
122
            throw new AccessDeniedException();
123
        }
124
125
        /** @var ExtensionEntity $extension */
126
        $extension = $extensionRepository->find($id);
127
        $zikulaLogger->notice(sprintf('Extension activating'), ['name' => $extension->getName()]);
128
        if (Constant::STATE_NOTALLOWED === $extension->getState()) {
129
            $this->addFlash('error', $this->trans('Error! Activation of %name% not allowed.', ['%name%' => $extension->getName()]));
130
        } else {
131
            // Update state
132
            $extensionStateHelper->updateState($id, Constant::STATE_ACTIVE);
133
//            $cacheClearer->clear('symfony');
134
            $this->addFlash('status', $this->trans('Done! Activated %name%.', ['%name%' => $extension->getName()]));
135
        }
136
137
        return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
138
    }
139
140
    /**
141
     * @Route("/deactivate/{id}/{token}", methods = {"GET"}, requirements={"id" = "^[1-9]\d*$"})
142
     * @PermissionCheck("admin")
143
     *
144
     * Deactivate an extension
145
     *
146
     * @throws AccessDeniedException Thrown if the CSRF token is invalid
147
     */
148
    public function deactivateAction(
149
        int $id,
150
        string $token,
151
        ExtensionRepositoryInterface $extensionRepository,
152
        ExtensionStateHelper $extensionStateHelper,
153
        LoggerInterface $zikulaLogger,
154
        CacheClearer $cacheClearer
155
    ): RedirectResponse {
156
        if (!$this->isCsrfTokenValid('deactivate-extension', $token)) {
157
            throw new AccessDeniedException();
158
        }
159
160
        /** @var ExtensionEntity $extension */
161
        $extension = $extensionRepository->find($id);
162
        $zikulaLogger->notice(sprintf('Extension deactivating'), ['name' => $extension->getName()]);
163
        $defaultTheme = $this->getVariableApi()->get(VariableApi::CONFIG, 'defaulttheme');
164
        $adminTheme = $this->getVariableApi()->get('ZikulaAdminModule', 'admintheme');
165
166
        if (null !== $extension) {
167
            if (ZikulaKernel::isCoreExtension($extension->getName())) {
168
                $this->addFlash('error', $this->trans('Error! You cannot deactivate the %name%. It is required by the system.', ['%name%' => $extension->getName()]));
169
            } elseif (in_array($extension->getName(), [$defaultTheme, $adminTheme])) {
170
                $this->addFlash('error', $this->trans('Error! You cannot deactivate the %name%. The theme is in use.', ['%name%' => $extension->getName()]));
171
            } else {
172
                // Update state
173
                $extensionStateHelper->updateState($id, Constant::STATE_INACTIVE);
174
//                $cacheClearer->clear('symfony');
175
                $this->addFlash('status', $this->trans('Done! Deactivated %name%.', ['%name%' => $extension->getName()]));
176
            }
177
        }
178
179
        return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
180
    }
181
182
    /**
183
     * @Route("/modify/{id}/{forceDefaults}", requirements={"id" = "^[1-9]\d*$", "forceDefaults" = "0|1"})
184
     * @Theme("admin")
185
     * @Template("@ZikulaExtensionsModule/Extension/modify.html.twig")
186
     *
187
     * Modify a module.
188
     *
189
     * @return array|RedirectResponse
190
     * @throws AccessDeniedException Thrown if the user doesn't have admin permissions for modifying the extension
191
     */
192
    public function modifyAction(
193
        Request $request,
194
        ZikulaHttpKernelInterface $kernel,
195
        ExtensionEntity $extension,
196
        CacheClearer $cacheClearer,
197
        bool $forceDefaults = false
198
    ) {
199
        if (!$this->hasPermission('ZikulaExtensionsModule::modify', $extension->getName() . '::' . $extension->getId(), ACCESS_ADMIN)) {
200
            throw new AccessDeniedException();
201
        }
202
203
        /** @var AbstractExtension $extensionBundle */
204
        $extensionBundle = $kernel->getBundle($extension->getName());
205
        $metaData = $extensionBundle->getMetaData()->getFilteredVersionInfoArray();
206
207
        if ($forceDefaults) {
208
            $extension->setName($metaData['name']);
209
            $extension->setUrl($metaData['url']);
210
            $extension->setDescription($metaData['description']);
211
        }
212
213
        $form = $this->createForm(ExtensionModifyType::class, $extension);
214
        $form->handleRequest($request);
215
        if ($form->isSubmitted() && $form->isValid()) {
216
            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

216
            if ($form->get('defaults')->/** @scrutinizer ignore-call */ isClicked()) {
Loading history...
217
                $this->addFlash('info', 'Default values reloaded. Save to confirm.');
218
219
                return $this->redirectToRoute('zikulaextensionsmodule_extension_modify', ['id' => $extension->getId(), 'forceDefaults' => 1]);
220
            }
221
            if ($form->get('save')->isClicked()) {
222
                $em = $this->getDoctrine()->getManager();
223
                $em->persist($extension);
224
                $em->flush();
225
226
                $cacheClearer->clear('symfony.routing');
227
                $this->addFlash('status', 'Done! Extension updated.');
228
            } elseif ($form->get('cancel')->isClicked()) {
229
                $this->addFlash('status', 'Operation cancelled.');
230
            }
231
232
            return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
233
        }
234
235
        return [
236
            'form' => $form->createView()
237
        ];
238
    }
239
240
    /**
241
     * @Route("/compatibility/{id}", methods = {"GET"}, requirements={"id" = "^[1-9]\d*$"})
242
     * @Theme("admin")
243
     * @Template("@ZikulaExtensionsModule/Extension/compatibility.html.twig")
244
     *
245
     * Display information of a module compatibility with the version of the core
246
     *
247
     * @throws AccessDeniedException Thrown if the user doesn't have admin permission to the requested module
248
     */
249
    public function compatibilityAction(ExtensionEntity $extension): array
250
    {
251
        if (!$this->hasPermission('ZikulaExtensionsModule::', $extension->getName() . '::' . $extension->getId(), ACCESS_ADMIN)) {
252
            throw new AccessDeniedException();
253
        }
254
255
        return [
256
            'extension' => $extension
257
        ];
258
    }
259
260
    /**
261
     * @Route("/install/{id}/{token}", requirements={"id" = "^[1-9]\d*$"})
262
     * @PermissionCheck("admin")
263
     * @Theme("admin")
264
     * @Template("@ZikulaExtensionsModule/Extension/install.html.twig")
265
     *
266
     * Install and initialise an extension.
267
     *
268
     * @return array|RedirectResponse
269
     * @throws AccessDeniedException Thrown if the CSRF token is invalid
270
     */
271
    public function installAction(
272
        Request $request,
273
        ExtensionEntity $extension,
274
        string $token,
275
        ZikulaHttpKernelInterface $kernel,
276
        ExtensionRepositoryInterface $extensionRepository,
277
        ExtensionHelper $extensionHelper,
278
        ExtensionStateHelper $extensionStateHelper,
279
        ExtensionDependencyHelper $dependencyHelper,
280
        LoggerInterface $zikulaLogger,
281
        CacheClearer $cacheClearer
282
    ) {
283
        $id = $extension->getId();
284
        if (!$this->isCsrfTokenValid('install-extension', $token)) {
285
            throw new AccessDeniedException();
286
        }
287
288
        if (!$kernel->isBundle($extension->getName())) {
289
            // set state to transitional which marks the bundle as active for the kernel
290
            if (Constant::STATE_TRANSITIONAL === $extension->getState()) {
291
                $zikulaLogger->info('@1 Wait 3');
292
                sleep(3);
293
            } else {
294
                $extensionStateHelper->updateState($id, Constant::STATE_TRANSITIONAL);
295
            }
296
297
            return $this->redirectToRoute('zikulaextensionsmodule_extension_install', ['id' => $id, 'token' => $token]);
298
        }
299
300
        // check if installer class is known in container
301
        $extensionBundle = $kernel->getBundle($extension->getName());
302
        $installerClass = $extensionHelper->getExtensionInstallerInstance($extensionBundle);
303
        if (null === $installerClass) {
304
            // if not, wait and try again
305
            $zikulaLogger->info('@2 Wait 3');
306
            sleep(3);
307
308
            return $this->redirectToRoute('zikulaextensionsmodule_extension_install', ['id' => $id, 'token' => $token]);
309
        }
310
311
        $unsatisfiedDependencies = $dependencyHelper->getUnsatisfiedExtensionDependencies($extension);
312
        $form = $this->createForm(ExtensionInstallType::class, [
313
            'dependencies' => $this->formatDependencyCheckboxArray($extensionRepository, $unsatisfiedDependencies)
314
        ]);
315
        $hasNoUnsatisfiedDependencies = empty($unsatisfiedDependencies);
316
        $form->handleRequest($request);
317
        if ($hasNoUnsatisfiedDependencies || ($form->isSubmitted() && $form->isValid())) {
318
            if ($hasNoUnsatisfiedDependencies || $form->get('install')->isClicked()) {
319
                $extensionsInstalled = [];
320
                $data = $form->getData();
321
                foreach ($data['dependencies'] as $dependencyId => $installSelected) {
322
                    if (!$installSelected && MetaData::DEPENDENCY_REQUIRED !== $unsatisfiedDependencies[$dependencyId]->getStatus()) {
323
                        continue;
324
                    }
325
                    $dependencyExtensionEntity = $extensionRepository->get($unsatisfiedDependencies[$dependencyId]->getModname());
326
                    if (isset($dependencyExtensionEntity)) {
327
                        if (!$extensionHelper->install($dependencyExtensionEntity)) {
328
                            $this->addFlash('error', $this->trans('Failed to install dependency "%name%"!', ['%name%' => $dependencyExtensionEntity->getName()]));
329
330
                            return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
331
                        }
332
                        $extensionsInstalled[] = $dependencyExtensionEntity->getId();
333
                        $this->addFlash('status', $this->trans('Installed dependency "%name%".', ['%name%' => $dependencyExtensionEntity->getName()]));
334
                    } else {
335
                        $this->addFlash('warning', $this->trans('Warning: could not install selected dependency "%name%".', ['%name%' => $unsatisfiedDependencies[$dependencyId]->getModname()]));
336
                    }
337
                }
338
                if ($extensionHelper->install($extension)) {
339
                    $this->addFlash('status', $this->trans('Done! Installed "%name%".', ['%name%' => $extension->getName()]));
340
                    $extensionsInstalled[] = $id;
341
//                    $cacheClearer->clear('symfony');
342
343
                    return $this->redirectToRoute('zikulaextensionsmodule_extension_postinstall', ['extensions' => json_encode($extensionsInstalled)]);
344
                }
345
                $extensionStateHelper->updateState($id, Constant::STATE_UNINITIALISED);
346
                $this->addFlash('error', $this->trans('Initialization of "%name%" failed!', ['%name%' => $extension->getName()]));
347
            }
348
            if ($form->get('cancel')->isClicked()) {
349
                $extensionStateHelper->updateState($id, Constant::STATE_UNINITIALISED);
350
                $this->addFlash('status', 'Operation cancelled.');
351
            }
352
353
            return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
354
        }
355
356
        return [
357
            'dependencies' => $unsatisfiedDependencies,
358
            'extension' => $extension,
359
            'form' => $form->createView()
360
        ];
361
    }
362
363
    /**
364
     * Post-installation action to trigger the MODULE_POSTINSTALL event.
365
     * The additional Action is required because this event must occur AFTER the rebuild of the cache which occurs on Request.
366
     *
367
     * @Route("/postinstall/{extensions}", methods = {"GET"})
368
     */
369
    public function postInstallAction(
370
        ExtensionRepositoryInterface $extensionRepository,
371
        ZikulaHttpKernelInterface $kernel,
372
        EventDispatcherInterface $eventDispatcher,
373
        string $extensions = null
374
    ): RedirectResponse {
375
        if (!empty($extensions)) {
376
            $extensions = json_decode($extensions);
377
            foreach ($extensions as $extensionId) {
378
                /** @var ExtensionEntity $extensionEntity */
379
                $extensionEntity = $extensionRepository->find($extensionId);
380
                if (null === $extensionRepository) {
381
                    continue;
382
                }
383
                /** @var AbstractExtension $extensionBundle */
384
                $extensionBundle = $kernel->getBundle($extensionEntity->getName());
385
                if (null === $extensionBundle) {
386
                    continue;
387
                }
388
                $eventDispatcher->dispatch(new ExtensionPostCacheRebuildEvent($extensionBundle, $extensionEntity));
389
            }
390
        }
391
392
        return $this->redirectToRoute('zikulaextensionsmodule_extension_list', ['justinstalled' => json_encode($extensions)]);
393
    }
394
395
    /**
396
     * Create array suitable for checkbox FormType [[ID => bool][ID => bool]].
397
     */
398
    private function formatDependencyCheckboxArray(
399
        ExtensionRepositoryInterface $extensionRepository,
400
        array $dependencies
401
    ): array {
402
        $return = [];
403
        foreach ($dependencies as $dependency) {
404
            /** @var ExtensionEntity $dependencyExtension */
405
            $dependencyExtension = $extensionRepository->get($dependency->getModname());
406
            $return[$dependency->getId()] = null !== $dependencyExtension;
407
        }
408
409
        return $return;
410
    }
411
412
    /**
413
     * @Route("/upgrade/{id}/{token}", requirements={"id" = "^[1-9]\d*$"})
414
     * @PermissionCheck("admin")
415
     *
416
     * Upgrade an extension.
417
     *
418
     * @throws AccessDeniedException Thrown if the CSRF token is invalid
419
     */
420
    public function upgradeAction(
421
        ExtensionEntity $extension,
422
        $token,
423
        ExtensionHelper $extensionHelper
424
    ): RedirectResponse {
425
        if (!$this->isCsrfTokenValid('upgrade-extension', $token)) {
426
            throw new AccessDeniedException();
427
        }
428
429
        $result = $extensionHelper->upgrade($extension);
430
        if ($result) {
431
            $this->addFlash('status', $this->trans('%name% upgraded to new version and activated.', ['%name%' => $extension->getDisplayname()]));
432
        } else {
433
            $this->addFlash('error', 'Extension upgrade failed!');
434
        }
435
436
        return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
437
    }
438
439
    /**
440
     * @Route("/uninstall/{id}/{token}", requirements={"id" = "^[1-9]\d*$"})
441
     * @PermissionCheck("admin")
442
     * @Theme("admin")
443
     * @Template("@ZikulaExtensionsModule/Extension/uninstall.html.twig")
444
     *
445
     * Uninstall an extension.
446
     *
447
     * @return array|Response|RedirectResponse
448
     * @throws AccessDeniedException Thrown if the CSRF token is invalid
449
     */
450
    public function uninstallAction(
451
        Request $request,
452
        ExtensionEntity $extension,
453
        string $token,
454
        ZikulaHttpKernelInterface $kernel,
455
        BlockRepositoryInterface $blockRepository,
456
        ExtensionHelper $extensionHelper,
457
        ExtensionStateHelper $extensionStateHelper,
458
        ExtensionDependencyHelper $dependencyHelper,
459
        CacheClearer $cacheClearer
460
    ) {
461
        if (!$this->isCsrfTokenValid('uninstall-extension', $token)) {
462
            throw new AccessDeniedException();
463
        }
464
465
        if (Constant::STATE_MISSING === $extension->getState()) {
466
            throw new RuntimeException($this->trans('Error! The requested extension cannot be uninstalled because its files are missing!'));
467
        }
468
        if (!$kernel->isBundle($extension->getName())) {
469
            $extensionStateHelper->updateState($extension->getId(), Constant::STATE_TRANSITIONAL);
470
//            $cacheClearer->clear('symfony');
471
        }
472
        $requiredDependents = $dependencyHelper->getDependentExtensions($extension);
473
        $blocks = $blockRepository->findBy(['module' => $extension]);
474
475
        $form = $this->createForm(DeletionType::class, [], [
476
            'action' => $this->generateUrl('zikulaextensionsmodule_extension_uninstall', [
477
                'id' => $extension->getId(),
478
                'token' => $token
479
            ]),
480
        ]);
481
        $form->handleRequest($request);
482
        if ($form->isSubmitted() && $form->isValid()) {
483
            if ($form->get('delete')->isClicked()) {
484
                // remove dependent extensions
485
                if (!$extensionHelper->uninstallArray($requiredDependents)) {
486
                    $this->addFlash('error', 'Error: Could not uninstall dependent extensions.');
487
488
                    return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
489
                }
490
                // remove blocks
491
                $blockRepository->remove($blocks);
492
493
                // remove the extension
494
                if ($extensionHelper->uninstall($extension)) {
495
                    $this->addFlash('status', 'Done! Uninstalled extension.');
496
                } else {
497
                    $this->addFlash('error', 'Extension removal failed! (note: blocks and dependents may have been removed)');
498
                }
499
            } elseif ($form->get('cancel')->isClicked()) {
500
                $this->addFlash('status', 'Operation cancelled.');
501
            }
502
503
            return $this->redirectToRoute('zikulaextensionsmodule_extension_postuninstall');
504
        }
505
506
        return [
507
            'form' => $form->createView(),
508
            'extension' => $extension,
509
            'blocks' => $blocks,
510
            'requiredDependents' => $requiredDependents
511
        ];
512
    }
513
514
    /**
515
     * @Route("/post-uninstall")
516
     * @PermissionCheck("admin")
517
     *
518
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
519
     */
520
    public function postUninstallAction(CacheClearer $cacheClearer)
521
    {
522
        $cacheClearer->clear('symfony');
523
524
        return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
525
    }
526
527
    /**
528
     * @Route("/theme-preview/{themeName}")
529
     * @PermissionCheck("admin")
530
     */
531
    public function previewAction(Engine $engine, string $themeName): Response
532
    {
533
        $engine->setActiveTheme($themeName);
534
        $this->addFlash('warning', 'Please note that blocks may appear out of place or even missing in a theme preview because position names are not consistent from theme to theme.');
535
536
        return $this->forward('Zikula\Bundle\CoreBundle\Controller\MainController::homeAction');
537
    }
538
}
539