Completed
Push — master ( 94ee7f...8c2cbc )
by Craig
10:45
created

PersistedBundleHandler   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 57
dl 0
loc 113
rs 10
c 0
b 0
f 0
wmc 22

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getConnection() 0 11 1
B extensionIsActive() 0 34 6
B addAutoloaders() 0 18 8
A doGetPersistedBundles() 0 22 5
A getPersistedBundles() 0 5 2
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\Bundle\CoreBundle\Bundle;
15
16
use function Composer\Autoload\includeFile;
17
use Doctrine\DBAL\Configuration;
18
use Doctrine\DBAL\Connection;
19
use Doctrine\DBAL\DriverManager;
20
use Exception;
21
use PDO;
22
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
23
use Zikula\ExtensionsModule\Constant;
24
use Zikula\ThemeModule\Entity\Repository\ThemeEntityRepository;
25
26
class PersistedBundleHandler
27
{
28
    /**
29
     * @var array the active/inactive state of each extension
30
     */
31
    private $extensionStateMap = [];
32
33
    public function getConnection(ZikulaHttpKernelInterface $kernel): Connection
34
    {
35
        // get bundles from persistence
36
        $connectionParams = $kernel->getConnectionConfig();
37
        $connectionParams['dbname'] = $connectionParams['parameters']['database_name'];
38
        $connectionParams['user'] = $connectionParams['parameters']['database_user'];
39
        $connectionParams['password'] = $connectionParams['parameters']['database_password'];
40
        $connectionParams['host'] = $connectionParams['parameters']['database_host'];
41
        $connectionParams['driver'] = $connectionParams['parameters']['database_driver'];
42
43
        return DriverManager::getConnection($connectionParams, new Configuration());
44
    }
45
46
    public function getPersistedBundles(ZikulaHttpKernelInterface $kernel, array &$bundles): void
47
    {
48
        try {
49
            $this->doGetPersistedBundles($kernel, $bundles);
50
        } catch (Exception $exception) {
51
            // fail silently on purpose
52
        }
53
    }
54
55
    private function doGetPersistedBundles(ZikulaHttpKernelInterface $kernel, array &$bundles): void
56
    {
57
        $conn = $this->getConnection($kernel);
58
        $conn->connect();
59
        $res = $conn->executeQuery('SELECT bundleclass, autoload, bundlestate, bundletype FROM bundles');
60
        foreach ($res->fetchAll(PDO::FETCH_NUM) as list($class, $autoload, $state, $type)) {
61
            $extensionIsActive = $this->extensionIsActive($conn, $class, $type);
62
            if ($extensionIsActive) {
63
                try {
64
                    $autoload = unserialize($autoload);
65
                    $this->addAutoloaders($kernel, $autoload);
66
67
                    if (class_exists($class)) {
68
                        $bundle = $class;
69
                        $bundles[] = $bundle;
70
                    }
71
                } catch (Exception $exception) {
72
                    // unable to autoload $prefix / $path
73
                }
74
            }
75
        }
76
        $conn->close();
77
    }
78
79
    /**
80
     * Determine if an extension is active.
81
     */
82
    private function extensionIsActive(Connection $conn, string $class, string $type): ?bool
83
    {
84
        $extensionNameArray = explode('\\', $class);
85
        $extensionName = array_pop($extensionNameArray);
86
        if (isset($this->extensionStateMap[$extensionName])) {
87
            // used cached value
88
            $state = $this->extensionStateMap[$extensionName];
89
        } else {
90
            // load all values into class var for lookup
91
            $sql = 'SELECT m.name, m.state, m.id FROM modules as m';
92
            $rows = $conn->executeQuery($sql);
93
            foreach ($rows as $row) {
94
                $this->extensionStateMap[$row['name']] = [
95
                    'state' => (int)$row['state'],
96
                    'id'    => (int)$row['id'],
97
                ];
98
            }
99
            $sql = 'SELECT t.name, t.state, t.id FROM themes as t';
100
            $rows = $conn->executeQuery($sql);
101
            foreach ($rows as $row) {
102
                $this->extensionStateMap[$row['name']] = [
103
                    'state' => (int)$row['state'],
104
                    'id'    => (int)$row['id'],
105
                ];
106
            }
107
108
            $state = $this->extensionStateMap[$extensionName] ?? ['state' => ('T' === $type) ? ThemeEntityRepository::STATE_INACTIVE : Constant::STATE_UNINITIALISED];
109
        }
110
111
        if ('T' === $type) {
112
            return ThemeEntityRepository::STATE_ACTIVE === $state['state'];
113
        }
114
115
        return in_array($state['state'], [Constant::STATE_ACTIVE, Constant::STATE_UPGRADED, Constant::STATE_TRANSITIONAL], true);
116
    }
117
118
    /**
119
     * Add autoloaders to kernel or include files from json.
120
     */
121
    public function addAutoloaders(ZikulaHttpKernelInterface $kernel, array $autoload = []): void
122
    {
123
        if (isset($autoload['psr-0'])) {
124
            foreach ($autoload['psr-0'] as $prefix => $path) {
125
                $kernel->getAutoloader()->add($prefix, $path);
126
            }
127
        }
128
        if (isset($autoload['psr-4'])) {
129
            foreach ($autoload['psr-4'] as $prefix => $path) {
130
                $kernel->getAutoloader()->addPsr4($prefix, $path);
131
            }
132
        }
133
        if (isset($autoload['classmap'])) {
134
            $kernel->getAutoloader()->addClassMap($autoload['classmap']);
135
        }
136
        if (isset($autoload['files'])) {
137
            foreach ($autoload['files'] as $path) {
138
                includeFile($path);
139
            }
140
        }
141
    }
142
}
143