Passed
Push — master ( 8a455a...42a228 )
by Craig
07:01
created

Bootstrap::doGetPersistedBundles()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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