Completed
Pull Request — master (#4264)
by Craig
04:58
created

ExtensionStateHelper::requiresCacheClear()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 5
rs 10
c 1
b 0
f 1
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\Helper;
15
16
use RuntimeException;
17
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
18
use Symfony\Contracts\Translation\TranslatorInterface;
19
use Zikula\Bundle\CoreBundle\CacheClearer;
20
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
21
use Zikula\ExtensionsModule\Constant;
22
use Zikula\ExtensionsModule\Entity\ExtensionEntity;
23
use Zikula\ExtensionsModule\Entity\Repository\ExtensionRepository;
24
use Zikula\ExtensionsModule\Event\ExtensionPostDisabledEvent;
25
use Zikula\ExtensionsModule\Event\ExtensionPostEnabledEvent;
26
use Zikula\ExtensionsModule\Event\ExtensionPreStateChangeEvent;
27
28
class ExtensionStateHelper
29
{
30
    /**
31
     * @var EventDispatcherInterface
32
     */
33
    private $dispatcher;
34
35
    /**
36
     * @var CacheClearer
37
     */
38
    private $cacheClearer;
39
40
    /**
41
     * @var ExtensionRepository
42
     */
43
    private $extensionRepository;
44
45
    /**
46
     * @var TranslatorInterface
47
     */
48
    private $translator;
49
50
    /**
51
     * @var ZikulaHttpKernelInterface
52
     */
53
    private $kernel;
54
55
    public function __construct(
56
        EventDispatcherInterface $dispatcher,
57
        CacheClearer $cacheClearer,
58
        ExtensionRepository $extensionRepository,
59
        TranslatorInterface $translator,
60
        ZikulaHttpKernelInterface $kernel
61
    ) {
62
        $this->dispatcher = $dispatcher;
63
        $this->cacheClearer = $cacheClearer;
64
        $this->extensionRepository = $extensionRepository;
65
        $this->translator = $translator;
66
        $this->kernel = $kernel;
67
    }
68
69
    /**
70
     * Set the state of a module.
71
     */
72
    public function updateState(int $id, int $state): bool
73
    {
74
        /** @var ExtensionEntity $extension */
75
        $extension = $this->extensionRepository->find($id);
76
        $this->dispatcher->dispatch(new ExtensionPreStateChangeEvent($extension, $state));
77
78
        // Check valid state transition
79
        switch ($state) {
80
            case Constant::STATE_INACTIVE:
81
                $eventClass = ExtensionPostDisabledEvent::class;
82
                break;
83
            case Constant::STATE_ACTIVE:
84
                if (Constant::STATE_INACTIVE === $extension->getState()) {
85
                    // ACTIVE is used for freshly installed modules, so only register the transition if previously inactive.
86
                    $eventClass = ExtensionPostEnabledEvent::class;
87
                }
88
                break;
89
            case Constant::STATE_UPGRADED:
90
                if (Constant::STATE_UNINITIALISED === $extension->getState()) {
91
                    throw new RuntimeException($this->translator->trans('Error! Invalid module state transition.'));
92
                }
93
                break;
94
        }
95
        $requiresCacheClear = $this->requiresCacheClear($extension->getState(), $state);
96
97
        // change state
98
        $extension->setState($state);
99
        $this->extensionRepository->persistAndFlush($extension);
100
101
        // clear the cache before calling events
102
        if ($requiresCacheClear) {
103
            $this->cacheClearer->clear('symfony');
104
        }
105
106
        if (isset($eventClass) && $this->kernel->isBundle($extension->getName())) {
107
            $bundle = $this->kernel->getBundle($extension->getName());
108
            $this->dispatcher->dispatch(new $eventClass($bundle, $extension));
109
        }
110
111
        return true;
112
    }
113
114
    /**
115
     * If an extension was previously in an active state and now is inactive or vice versa
116
     */
117
    private function requiresCacheClear(int $oldState, int $newState): bool
118
    {
119
        $activeStates = [Constant::STATE_ACTIVE, Constant::STATE_TRANSITIONAL, Constant::STATE_UPGRADED];
120
121
        return in_array($oldState, $activeStates) !== in_array($newState, $activeStates);
122
    }
123
}
124