Completed
Pull Request — master (#4264)
by Craig
05:17 queued 14s
created

ExtensionController::installAction()   C

Complexity

Conditions 15
Paths 9

Size

Total Lines 71
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 43
nc 9
nop 9
dl 0
loc 71
rs 5.9166
c 0
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 - 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\Controller\AbstractController;
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\ExtensionsModule\AbstractExtension;
35
use Zikula\ExtensionsModule\Api\VariableApi;
36
use Zikula\ExtensionsModule\Constant;
37
use Zikula\ExtensionsModule\Entity\ExtensionEntity;
38
use Zikula\ExtensionsModule\Entity\RepositoryInterface\ExtensionRepositoryInterface;
39
use Zikula\ExtensionsModule\Event\ExtensionListPreReSyncEvent;
40
use Zikula\ExtensionsModule\Form\Type\ExtensionModifyType;
41
use Zikula\ExtensionsModule\Helper\BundleSyncHelper;
42
use Zikula\ExtensionsModule\Helper\ExtensionDependencyHelper;
43
use Zikula\ExtensionsModule\Helper\ExtensionHelper;
44
use Zikula\ExtensionsModule\Helper\ExtensionStateHelper;
45
use Zikula\PermissionsModule\Annotation\PermissionCheck;
46
use Zikula\RoutesModule\Event\RoutesNewlyAvailableEvent;
47
use Zikula\ThemeModule\Engine\Annotation\Theme;
48
use Zikula\ThemeModule\Engine\Engine;
49
50
/**
51
 * @Route("")
52
 */
53
class ExtensionController extends AbstractController
54
{
55
    /**
56
     * @Route("/list/{page}", methods = {"GET"}, requirements={"page" = "\d+"})
57
     * @PermissionCheck("admin")
58
     * @Theme("admin")
59
     * @Template("@ZikulaExtensionsModule/Extension/list.html.twig")
60
     */
61
    public function listAction(
62
        Request $request,
63
        EventDispatcherInterface $eventDispatcher,
64
        ExtensionRepositoryInterface $extensionRepository,
65
        BundleSyncHelper $bundleSyncHelper,
66
        RouterInterface $router,
67
        int $page = 1
68
    ): array {
69
        $modulesJustInstalled = $request->query->get('justinstalled');
70
        if (!empty($modulesJustInstalled)) {
71
            // notify the event dispatcher that new routes are available (ids of modules just installed avail as args)
72
            $eventDispatcher->dispatch(new RoutesNewlyAvailableEvent(json_decode($modulesJustInstalled)));
73
        }
74
75
        $sortableColumns = new SortableColumns($router, 'zikulaextensionsmodule_extension_list');
76
        $sortableColumns->addColumns([new Column('displayname'), new Column('state')]);
77
        $sortableColumns->setOrderByFromRequest($request);
78
79
        $upgradedExtensions = [];
80
        $extensionListPreReSyncEvent = new ExtensionListPreReSyncEvent();
81
        $eventDispatcher->dispatch($extensionListPreReSyncEvent);
82
        if (1 === $page && !$extensionListPreReSyncEvent->isPropagationStopped()) {
83
            // regenerate the extension list only when viewing the first page
84
            $extensionsInFileSystem = $bundleSyncHelper->scanForBundles();
85
            $upgradedExtensions = $bundleSyncHelper->syncExtensions($extensionsInFileSystem);
86
        }
87
88
        $pageSize = $this->getVar('itemsperpage');
89
90
        $paginator = $extensionRepository->getPagedCollectionBy([], [
91
            $sortableColumns->getSortColumn()->getName() => $sortableColumns->getSortDirection()
92
        ], $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

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

213
            if ($form->get('defaults')->/** @scrutinizer ignore-call */ isClicked()) {
Loading history...
214
                $this->addFlash('info', 'Default values reloaded. Save to confirm.');
215
216
                return $this->redirectToRoute('zikulaextensionsmodule_extension_modify', ['id' => $extension->getId(), 'forceDefaults' => 1]);
217
            }
218
            if ($form->get('save')->isClicked()) {
219
                $em = $this->getDoctrine()->getManager();
220
                $em->persist($extension);
221
                $em->flush();
222
223
                $cacheClearer->clear('symfony.routing');
224
                $this->addFlash('status', 'Done! Extension updated.');
225
            } elseif ($form->get('cancel')->isClicked()) {
226
                $this->addFlash('status', 'Operation cancelled.');
227
            }
228
229
            return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
230
        }
231
232
        return [
233
            'form' => $form->createView()
234
        ];
235
    }
236
237
    /**
238
     * @Route("/compatibility/{id}", methods = {"GET"}, requirements={"id" = "^[1-9]\d*$"})
239
     * @Theme("admin")
240
     * @Template("@ZikulaExtensionsModule/Extension/compatibility.html.twig")
241
     *
242
     * Display information of a module compatibility with the version of the core
243
     *
244
     * @throws AccessDeniedException Thrown if the user doesn't have admin permission to the requested module
245
     */
246
    public function compatibilityAction(ExtensionEntity $extension): array
247
    {
248
        if (!$this->hasPermission('ZikulaExtensionsModule::', $extension->getName() . '::' . $extension->getId(), ACCESS_ADMIN)) {
249
            throw new AccessDeniedException();
250
        }
251
252
        return [
253
            'extension' => $extension
254
        ];
255
    }
256
257
    /**
258
     * @Route("/upgrade/{id}/{token}", requirements={"id" = "^[1-9]\d*$"})
259
     * @PermissionCheck("admin")
260
     *
261
     * Upgrade an extension.
262
     *
263
     * @throws AccessDeniedException Thrown if the CSRF token is invalid
264
     */
265
    public function upgradeAction(
266
        ExtensionEntity $extension,
267
        $token,
268
        ExtensionHelper $extensionHelper
269
    ): RedirectResponse {
270
        if (!$this->isCsrfTokenValid('upgrade-extension', $token)) {
271
            throw new AccessDeniedException();
272
        }
273
274
        $result = $extensionHelper->upgrade($extension);
275
        if ($result) {
276
            $this->addFlash('status', $this->trans('%name% upgraded to new version and activated.', ['%name%' => $extension->getDisplayname()]));
277
        } else {
278
            $this->addFlash('error', 'Extension upgrade failed!');
279
        }
280
281
        return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
282
    }
283
284
    /**
285
     * @Route("/uninstall/{id}/{token}", requirements={"id" = "^[1-9]\d*$"})
286
     * @PermissionCheck("admin")
287
     * @Theme("admin")
288
     * @Template("@ZikulaExtensionsModule/Extension/uninstall.html.twig")
289
     *
290
     * Uninstall an extension.
291
     *
292
     * @return array|Response|RedirectResponse
293
     * @throws AccessDeniedException Thrown if the CSRF token is invalid
294
     */
295
    public function uninstallAction(
296
        Request $request,
297
        ExtensionEntity $extension,
298
        string $token,
299
        ZikulaHttpKernelInterface $kernel,
300
        BlockRepositoryInterface $blockRepository,
301
        ExtensionHelper $extensionHelper,
302
        ExtensionStateHelper $extensionStateHelper,
303
        ExtensionDependencyHelper $dependencyHelper,
304
        CacheClearer $cacheClearer
305
    ) {
306
        if (!$this->isCsrfTokenValid('uninstall-extension', $token)) {
307
            throw new AccessDeniedException();
308
        }
309
310
        if (Constant::STATE_MISSING === $extension->getState()) {
311
            throw new RuntimeException($this->trans('Error! The requested extension cannot be uninstalled because its files are missing!'));
312
        }
313
        if (!$kernel->isBundle($extension->getName())) {
314
            $extensionStateHelper->updateState($extension->getId(), Constant::STATE_TRANSITIONAL);
315
//            $cacheClearer->clear('symfony');
316
        }
317
        $requiredDependents = $dependencyHelper->getDependentExtensions($extension);
318
        $blocks = $blockRepository->findBy(['module' => $extension]);
319
320
        $form = $this->createForm(DeletionType::class, [], [
321
            'action' => $this->generateUrl('zikulaextensionsmodule_extension_uninstall', [
322
                'id' => $extension->getId(),
323
                'token' => $token
324
            ]),
325
        ]);
326
        $form->handleRequest($request);
327
        if ($form->isSubmitted() && $form->isValid()) {
328
            if ($form->get('delete')->isClicked()) {
329
                // remove dependent extensions
330
                if (!$extensionHelper->uninstallArray($requiredDependents)) {
331
                    $this->addFlash('error', 'Error: Could not uninstall dependent extensions.');
332
333
                    return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
334
                }
335
                // remove blocks
336
                $blockRepository->remove($blocks);
337
338
                // remove the extension
339
                if ($extensionHelper->uninstall($extension)) {
340
                    $this->addFlash('status', 'Done! Uninstalled extension.');
341
                } else {
342
                    $this->addFlash('error', 'Extension removal failed! (note: blocks and dependents may have been removed)');
343
                }
344
            } elseif ($form->get('cancel')->isClicked()) {
345
                $this->addFlash('status', 'Operation cancelled.');
346
            }
347
348
            return $this->redirectToRoute('zikulaextensionsmodule_extension_postuninstall');
349
        }
350
351
        return [
352
            'form' => $form->createView(),
353
            'extension' => $extension,
354
            'blocks' => $blocks,
355
            'requiredDependents' => $requiredDependents
356
        ];
357
    }
358
359
    /**
360
     * @Route("/post-uninstall")
361
     * @PermissionCheck("admin")
362
     *
363
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
364
     */
365
    public function postUninstallAction(CacheClearer $cacheClearer)
366
    {
367
        $cacheClearer->clear('symfony');
368
369
        return $this->redirectToRoute('zikulaextensionsmodule_extension_list');
370
    }
371
372
    /**
373
     * @Route("/theme-preview/{themeName}")
374
     * @PermissionCheck("admin")
375
     */
376
    public function previewAction(Engine $engine, string $themeName): Response
377
    {
378
        $engine->setActiveTheme($themeName);
379
        $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.');
380
381
        return $this->forward('Zikula\Bundle\CoreBundle\Controller\MainController::homeAction');
382
    }
383
}
384