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

ExtensionStateHelper::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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