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

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