Completed
Push — master ( 139fb8...7c9eb0 )
by Thomas
10s
created

getSubstituteOriginalDrupalKernelConfiguration()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the ekino Drupal Debug project.
7
 *
8
 * (c) ekino
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 Ekino\Drupal\Debug\Configuration;
15
16
use Ekino\Drupal\Debug\Cache\FileCache;
17
use Ekino\Drupal\Debug\Configuration\Model\DefaultsConfiguration;
18
use Ekino\Drupal\Debug\Configuration\Model\SubstituteOriginalDrupalKernelConfiguration;
19
use Ekino\Drupal\Debug\Resource\Model\ResourcesCollection;
20
use Symfony\Component\Config\Definition\Processor;
21
use Symfony\Component\Config\Resource\FileExistenceResource;
22
use Symfony\Component\Config\Resource\FileResource;
23
use Symfony\Component\Filesystem\Filesystem;
24
use Symfony\Component\PropertyAccess\PropertyAccess;
25
use Symfony\Component\Yaml\Parser;
26
27
class ConfigurationManager
28
{
29
    /**
30
     * @var string
31
     */
32
    const CONFIGURATION_FILE_PATH_ENVIRONMENT_VARIABLE_NAME = 'DRUPAL_DEBUG_CONFIGURATION_FILE_PATH';
33
34
    /**
35
     * @var string
36
     */
37
    const CONFIGURATION_CACHE_DIRECTORY_ENVIRONMENT_VARIABLE_NAME = 'DRUPAL_DEBUG_CONFIGURATION_CACHE_DIRECTORY';
38
39
    /**
40
     * @var string
41
     */
42
    const DEFAULT_CONFIGURATION_FILE_NAME = 'drupal-debug.yml.dist';
43
44
    /**
45
     * @var bool
46
     */
47
    private static $initialized = false;
48
49
    /**
50
     * @var array|null
51
     */
52
    private static $configurationFilePathInfo = null;
53
54
    /**
55
     * @var array|null
56
     */
57
    private static $processedConfigurations = null;
58
59
    /**
60
     * @var DefaultsConfiguration|null
61
     */
62
    private static $defaultsConfiguration = null;
63
64
    /**
65
     * @var SubstituteOriginalDrupalKernelConfiguration|null
66
     */
67
    private static $substituteOriginalDrupalKernelConfiguration = null;
68
69 2
    public static function initialize(): void
70
    {
71 2
        if (self::$initialized) {
72
            throw new \RuntimeException('The configuration should not be initialized twice.');
73
        }
74
75 2
        self::$initialized = true;
76
77 2
        $configurationCacheDirectory = \getenv(self::CONFIGURATION_CACHE_DIRECTORY_ENVIRONMENT_VARIABLE_NAME);
78 2
        if (false === $configurationCacheDirectory) {
79
            $configurationCacheDirectory = \sys_get_temp_dir();
80
        }
81
82 2
        $configurationFilePathInfo = self::getConfigurationFilePathInfo();
83 2
        list($configurationFilePath, $configurationFilePathExists) = $configurationFilePathInfo;
84
85 2
        $fileCache = new FileCache(\sprintf('%s/drupal_debug_configuration.php', $configurationCacheDirectory), new ResourcesCollection(array(
86 2
            $configurationFilePathExists ? new FileResource($configurationFilePath) : new FileExistenceResource($configurationFilePath),
87 2
            new FileResource(\sprintf('%s/Configuration.php', __DIR__)),
88
        )));
89 2
        if ($fileCache->isFresh() && !empty($data = $fileCache->getData())) {
90
            list(
91
                'defaults' => self::$defaultsConfiguration,
92
                'substitute_original_drupal_kernel' => self::$substituteOriginalDrupalKernelConfiguration
93
            ) = \array_map(function ($serializedConfiguration) {
94
                return \unserialize($serializedConfiguration);
95
            }, $data);
96
        } else {
97 2
            self::$configurationFilePathInfo = $configurationFilePathInfo;
98
99 2
            $fileCache->invalidate();
100 2
            $fileCache->write(array(
101 2
                'defaults' => \serialize(self::getDefaultsConfiguration()),
102 2
                'substitute_original_drupal_kernel' => \serialize(self::getSubstituteOriginalDrupalKernelConfiguration()),
103
            ));
104
        }
105 2
    }
106
107
    /**
108
     * @return DefaultsConfiguration
109
     */
110 2
    public static function getDefaultsConfiguration(): DefaultsConfiguration
111
    {
112 2
        if (!self::$defaultsConfiguration instanceof DefaultsConfiguration) {
113 2
            self::process();
114
115 2
            self::$defaultsConfiguration = new DefaultsConfiguration(self::$processedConfigurations['defaults']);
116
        }
117
118 2
        return self::$defaultsConfiguration;
119
    }
120
121
    /**
122
     * @return SubstituteOriginalDrupalKernelConfiguration
123
     */
124 2
    public static function getSubstituteOriginalDrupalKernelConfiguration(): SubstituteOriginalDrupalKernelConfiguration
125
    {
126 2
        if (!self::$substituteOriginalDrupalKernelConfiguration instanceof SubstituteOriginalDrupalKernelConfiguration) {
127 2
            self::process();
128
129 2
            self::$substituteOriginalDrupalKernelConfiguration = new SubstituteOriginalDrupalKernelConfiguration(self::$processedConfigurations['substitute_original_drupal_kernel']);
130
        }
131
132 2
        return self::$substituteOriginalDrupalKernelConfiguration;
133
    }
134
135
    /**
136
     * @return array
137
     */
138 26
    public static function getConfigurationFilePathInfo(): array
139
    {
140 26
        $possibleConfigurationFilePath = \getenv(self::CONFIGURATION_FILE_PATH_ENVIRONMENT_VARIABLE_NAME);
141 26
        if (false === $possibleConfigurationFilePath) {
142
            // The default configuration file location is the same than the vendor directory.
143
            $possibleAutoloadPaths = array(
144
                // Vendor of a project : Configuration\src\drupal-debug\ekino\autoload.php
145
                \sprintf('%s/../../../../autoload.php', __DIR__),
146
                // Directly this project : Configuration\src\/vendor/autoload.php
147
                \sprintf('%s/../../vendor/autoload.php', __DIR__),
148
                // For other cases (if they exist), please use the dedicated environment variable.
149
            );
150
151
            foreach ($possibleAutoloadPaths as $possibleAutoloadPath) {
152
                if (\is_file($possibleAutoloadPath)) {
153
                    $possibleConfigurationFilePath = \sprintf('%s/../%s', \dirname($possibleAutoloadPath), self::DEFAULT_CONFIGURATION_FILE_NAME);
154
155
                    break;
156
                }
157
            }
158
159
            if (false === $possibleConfigurationFilePath) {
160
                throw new \RuntimeException('The composer autoload.php file could not be found.');
161
            }
162
        }
163
164
        $possibleConfigurationFilePaths = array(
165 26
            $possibleConfigurationFilePath,
166 26
            \rtrim($possibleConfigurationFilePath, '.dist'),
167
        );
168
169 26
        $exists = false;
170 26
        foreach ($possibleConfigurationFilePaths as $possibleConfigurationFilePath) {
171 26
            if (\is_file($possibleConfigurationFilePath)) {
172 18
                $exists = true;
173
174 26
                break;
175
            }
176
        }
177
178
        return array(
179 26
            $possibleConfigurationFilePath,
180 26
            $exists,
181
        );
182
    }
183
184 2
    private static function process(): void
185
    {
186 2
        if (!self::$initialized) {
187
            throw new \RuntimeException('The configuration has not been initialized.');
188
        }
189
190 2
        if (\is_array(self::$processedConfigurations)) {
191 2
            return;
192
        }
193
194 2
        $processedConfigurations = (new Processor())->process((new Configuration())->getConfigTreeBuilder()->buildTree(), self::getConfigurationFileContent());
195 2
        self::$processedConfigurations = self::makeRelativePathsAbsolutes($processedConfigurations);
196 2
    }
197
198
    /**
199
     * @return array
200
     */
201 2
    private static function getConfigurationFileContent(): array
202
    {
203 2
        list($configurationFilePath, $configurationFilePathExists) = self::$configurationFilePathInfo;
204 2
        if (!$configurationFilePathExists) {
205
            return array();
206
        }
207
208 2
        $parser = new Parser();
209 2
        $content = $parser->parseFile($configurationFilePath);
210 2
        if (!\is_array($content)) {
211
            throw new \RuntimeException('The content of the drupal-debug configuration file should be an array.');
212
        }
213
214 2
        return $content;
215
    }
216
217
    /**
218
     * @param array $processedConfigurations
219
     *
220
     * @return array
221
     */
222 2
    private static function makeRelativePathsAbsolutes(array $processedConfigurations): array
223
    {
224 2
        $filesystem = new Filesystem();
225
226 2
        $propertyAccessor = PropertyAccess::createPropertyAccessor();
227
228
        $configurationPaths = array(
229 2
            '[defaults][cache_directory]',
230
            '[defaults][logger][file_path]',
231
            '[substitute_original_drupal_kernel][composer_autoload_file_path]',
232
            '[substitute_original_drupal_kernel][cache_directory]',
233
        );
234
235 2
        list($configurationFilePath) = self::$configurationFilePathInfo;
236 2
        $configurationFilePathDirectory = \dirname($configurationFilePath);
237 2
        foreach ($configurationPaths as $configurationPath) {
238 2
            if (!$propertyAccessor->isReadable($processedConfigurations, $configurationPath)) {
239
                continue;
240
            }
241
242 2
            $path = $propertyAccessor->getValue($processedConfigurations, $configurationPath);
243 2
            if (null === $path || '' === $path) {
244 2
                continue;
245
            }
246
247 2
            if (!$filesystem->isAbsolutePath($path)) {
248 2
                $propertyAccessor->setValue($processedConfigurations, $configurationPath, \sprintf('%s/%s', $configurationFilePathDirectory, $path));
249
            }
250
        }
251
252 2
        return $processedConfigurations;
253
    }
254
}
255