Completed
Push — master ( a15f89...abb079 )
by Craig
07:12 queued 01:36
created

ZikulaExtensionInstallCommand   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 57
dl 0
loc 113
rs 10
c 4
b 0
f 0
wmc 21

5 Methods

Rating   Name   Duplication   Size   Complexity  
C execute() 0 57 13
A load() 0 15 2
A clearCache() 0 5 1
A installDependencies() 0 13 4
A configure() 0 10 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula Foundation - 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\Command;
15
16
use Symfony\Component\Console\Input\ArrayInput;
17
use Symfony\Component\Console\Input\InputArgument;
18
use Symfony\Component\Console\Input\InputInterface;
19
use Symfony\Component\Console\Input\InputOption;
20
use Symfony\Component\Console\Output\NullOutput;
21
use Symfony\Component\Console\Output\OutputInterface;
22
use Symfony\Component\Console\Style\SymfonyStyle;
23
use Zikula\Bundle\CoreBundle\Bundle\MetaData;
24
use Zikula\Core\CoreEvents;
25
use Zikula\Core\Event\ModuleStateEvent;
26
use Zikula\ExtensionsModule\Constant;
27
use Zikula\ExtensionsModule\Entity\ExtensionEntity;
28
29
class ZikulaExtensionInstallCommand extends AbstractExtensionCommand
30
{
31
    protected static $defaultName = 'zikula:extension:install';
32
33
    protected function configure()
34
    {
35
        $this
36
            ->setDescription('Install a zikula extension (module or theme).')
37
            ->addArgument('bundle_name', InputArgument::REQUIRED, 'Bundle class name (e.g. ZikulaUsersModule)')
38
            ->addOption(
39
                'ignore_deps',
40
                null,
41
                InputOption::VALUE_NONE,
42
                'Force install the extension ignoring all dependencies')
43
        ;
44
    }
45
46
    protected function execute(InputInterface $input, OutputInterface $output): int
47
    {
48
        $io = new SymfonyStyle($input, $output);
49
        $bundleName = $input->getArgument('bundle_name');
50
        $ignoreDeps = $input->getOption('ignore_deps');
51
52
        if (false !== $this->isInstalled($bundleName)) {
0 ignored issues
show
Bug introduced by
It seems like $bundleName can also be of type null and string[]; however, parameter $bundleName of Zikula\ExtensionsModule\...nCommand::isInstalled() does only seem to accept string, 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

52
        if (false !== $this->isInstalled(/** @scrutinizer ignore-type */ $bundleName)) {
Loading history...
53
            if ($input->isInteractive()) {
54
                $io->error('Extension is already installed but possibly inactive.');
55
            }
56
57
            return 1;
58
        }
59
60
        /** @var $extension ExtensionEntity */
61
        if (false === $extension = $this->load($bundleName)) {
0 ignored issues
show
Bug introduced by
It seems like $bundleName can also be of type null and string[]; however, parameter $bundleName of Zikula\ExtensionsModule\...nInstallCommand::load() does only seem to accept string, 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

61
        if (false === $extension = $this->load(/** @scrutinizer ignore-type */ $bundleName)) {
Loading history...
62
            if ($input->isInteractive()) {
63
                $io->error('Extension could not be found and loaded from the expected directory');
64
            }
65
66
            return 2;
67
        }
68
69
        if (!$ignoreDeps) {
70
            if (false === $this->installDependencies($extension)) {
71
                if ($input->isInteractive()) {
72
                    $io->error('Required dependencies could not be installed');
73
                }
74
75
                return 3;
76
            }
77
        }
78
79
        if (false === $this->extensionHelper->install($extension)) {
80
            if ($input->isInteractive()) {
81
                $io->error('Could not install the extension');
82
            }
83
84
            return 4;
85
        }
86
87
        if (0 !== $this->clearCache()) {
88
            if ($input->isInteractive()) {
89
                $io->error('Could not clear the cache (--no-warmup)');
90
            }
91
92
            return 5;
93
        }
94
95
        $event = new ModuleStateEvent($this->kernel->getModule($extension->getName()), $extension->toArray());
96
        $this->eventDispatcher->dispatch($event, CoreEvents::MODULE_POSTINSTALL);
97
98
        if ($input->isInteractive()) {
99
            $io->success('Extension installed');
100
        }
101
102
        return 0;
103
    }
104
105
    private function clearCache(): int
106
    {
107
        $command = $this->getApplication()->find('cache:clear');
108
109
        return $command->run(new ArrayInput(['--no-warmup' => true]), new NullOutput());
110
    }
111
112
    private function load(string $bundleName)
113
    {
114
        // load the extension into the modules table
115
        $extensionsInFileSystem = $this->bundleSyncHelper->scanForBundles();
116
        $this->bundleSyncHelper->syncExtensions($extensionsInFileSystem);
117
        if (!($extension = $this->extensionRepository->findOneBy(['name' => $bundleName]))) {
118
            return false;
119
        }
120
121
        // force the kernel to load the bundle
122
        $extension->setState(Constant::STATE_TRANSITIONAL);
123
        $this->extensionRepository->persistAndFlush($extension);
124
        $this->kernel->reboot(null);
125
126
        return $extension;
127
    }
128
129
    private function installDependencies(ExtensionEntity $extension): bool
130
    {
131
        $unsatisfiedDependencies = $this->dependencyHelper->getUnsatisfiedExtensionDependencies($extension);
132
        $return = true;
133
        foreach ($unsatisfiedDependencies as $dependency) {
134
            if (MetaData::DEPENDENCY_REQUIRED !== $dependency->getStatus()) {
135
                continue;
136
            }
137
            $this->load($dependency->getModname());
138
            $return = $return && $this->extensionHelper->install($dependency);
139
        }
140
141
        return $return;
142
    }
143
}
144