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

ParameterHelper::getYamlHelper()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 5
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 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\CoreInstallerBundle\Helper;
15
16
use RandomLib\Factory;
17
use Symfony\Component\HttpFoundation\RequestStack;
18
use Symfony\Component\Yaml\Yaml;
19
use Zikula\Bundle\CoreBundle\CacheClearer;
20
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
21
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel;
22
use Zikula\Bundle\CoreBundle\YamlDumper;
23
use Zikula\ExtensionsModule\Api\ApiInterface\VariableApiInterface;
24
use Zikula\ExtensionsModule\Api\VariableApi;
25
26
class ParameterHelper
27
{
28
    /**
29
     * @var string
30
     */
31
    private $configDir;
32
33
    /**
34
     * @var VariableApiInterface
35
     */
36
    private $variableApi;
37
38
    /**
39
     * @var CacheClearer
40
     */
41
    private $cacheClearer;
42
43
    /**
44
     * @var RequestStack
45
     */
46
    private $requestStack;
47
48
    /**
49
     * @var ZikulaHttpKernelInterface
50
     */
51
    private $kernel;
52
53
    /**
54
     * ParameterHelper constructor.
55
     */
56
    public function __construct(
57
        string $configDir,
58
        VariableApiInterface $variableApi,
59
        CacheClearer $cacheClearer,
60
        RequestStack $requestStack,
61
        ZikulaHttpKernelInterface $kernel
62
    ) {
63
        $this->configDir = $configDir;
64
        $this->variableApi = $variableApi;
65
        $this->cacheClearer = $cacheClearer;
66
        $this->requestStack = $requestStack;
67
        $this->kernel = $kernel;
68
    }
69
70
    public function getYamlHelper(bool $initCopy = false): YamlDumper
71
    {
72
        $copyFile = $initCopy ? 'parameters.yml' : null;
73
74
        return new YamlDumper($this->configDir, 'custom_parameters.yml', $copyFile);
75
    }
76
77
    public function initializeParameters(array $paramsToMerge = []): bool
78
    {
79
        $yamlHelper = $this->getYamlHelper(true);
80
        $params = array_merge($yamlHelper->getParameters(), $paramsToMerge);
81
        if (0 !== mb_strpos($params['database_driver'], 'pdo_')) {
82
            $params['database_driver'] = 'pdo_' . $params['database_driver']; // doctrine requires prefix in custom_parameters.yml
83
        }
84
        $yamlHelper->setParameters($params);
85
        $this->cacheClearer->clear('symfony.config');
86
87
        return true;
88
    }
89
90
    /**
91
     * load and set new default values from the original parameters.yml file into the custom_parameters.yml file.
92
     *
93
     * @return bool
94
     */
95
    public function reInitParameters(): bool
96
    {
97
        $originalParameters = Yaml::parse(file_get_contents($this->kernel->getProjectDir() . '/config/parameters.yml'));
0 ignored issues
show
Bug introduced by
The method getProjectDir() does not exist on Zikula\Bundle\CoreBundle...kulaHttpKernelInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Zikula\Bundle\CoreBundle...kulaHttpKernelInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

97
        $originalParameters = Yaml::parse(file_get_contents($this->kernel->/** @scrutinizer ignore-call */ getProjectDir() . '/config/parameters.yml'));
Loading history...
98
        $yamlHelper = $this->getYamlHelper();
99
        $yamlHelper->setParameters(array_merge($originalParameters['parameters'], $yamlHelper->getParameters()));
100
        $this->cacheClearer->clear('symfony.config');
101
102
        return true;
103
    }
104
105
    public function finalizeParameters(bool $configureRequestContext = true): bool
106
    {
107
        $yamlHelper = $this->getYamlHelper();
108
        $params = $this->decodeParameters($yamlHelper->getParameters());
109
        $this->variableApi->getAll(VariableApi::CONFIG); // forces initialization of API
110
        $this->variableApi->set(VariableApi::CONFIG, 'language_i18n', $params['locale']);
111
        // Set the System Identifier as a unique string.
112
        if (!$this->variableApi->get(VariableApi::CONFIG, 'system_identifier')) {
113
            $this->variableApi->set(VariableApi::CONFIG, 'system_identifier', str_replace('.', '', uniqid((string) (random_int(1000000000, 9999999999)), true)));
114
        }
115
        // add admin email as site email
116
        $this->variableApi->set(VariableApi::CONFIG, 'adminmail', $params['email']);
117
118
        // add remaining parameters and remove unneeded ones
119
        unset($params['username'], $params['password'], $params['email'], $params['dbtabletype']);
120
        $params['datadir'] = !empty($params['datadir']) ? $params['datadir'] : 'web/uploads';
121
122
        $RandomLibFactory = new Factory();
123
        $generator = $RandomLibFactory->getMediumStrengthGenerator();
124
        if (!isset($params['secret']) || ('ThisTokenIsNotSoSecretChangeIt' === $params['secret'])) {
125
            $params['secret'] = $generator->generateString(50);
126
        }
127
        if (!isset($params['url_secret'])) {
128
            $params['url_secret'] = $generator->generateString(10);
129
        }
130
131
        if ($configureRequestContext) {
132
            // Configure the Request Context
133
            // see http://symfony.com/doc/current/cookbook/console/sending_emails.html#configuring-the-request-context-globally
134
            $request = $this->requestStack->getMasterRequest();
135
            $hostFromRequest = isset($request) ? $request->getHost() : null;
136
            $schemeFromRequest = isset($request) ? $request->getScheme() : 'http';
137
            $basePathFromRequest = isset($request) ? $request->getBasePath() : null;
138
            $params['router.request_context.host'] = $params['router.request_context.host'] ?? $hostFromRequest;
139
            $params['router.request_context.scheme'] = $params['router.request_context.scheme'] ?? $schemeFromRequest;
140
            $params['router.request_context.base_url'] = $params['router.request_context.base_url'] ?? $basePathFromRequest;
141
        }
142
        $params['umask'] = $params['umask'] ?? null;
143
        $params['installed'] = true;
144
        // set currently installed version into parameters
145
        $params[ZikulaKernel::CORE_INSTALLED_VERSION_PARAM] = ZikulaKernel::VERSION;
146
        // store the recent version in a config var for later usage. This enables us to determine the version we are upgrading from
147
        $this->variableApi->set(VariableApi::CONFIG, 'Version_Num', ZikulaKernel::VERSION);
148
149
        if (isset($params['upgrading'])) {
150
            $params['zikula_asset_manager.combine'] = false;
151
            $startController = $this->variableApi->getSystemVar('startController');
152
            [$moduleName] = explode(':', $startController);
153
            if (!$this->kernel->isBundle($moduleName)) {
154
                // set the 'start' page information to empty to avoid missing module errors.
155
                $this->variableApi->set(VariableApi::CONFIG, 'startController', '');
156
                $this->variableApi->set(VariableApi::CONFIG, 'startargs', '');
157
            }
158
159
            // on upgrade, if a user doesn't add their custom theme back to the /theme dir, it should be reset to a core theme, if available.
160
            $defaultTheme = (string) $this->variableApi->getSystemVar('Default_Theme');
161
            if (!$this->kernel->isBundle($defaultTheme) && $this->kernel->isBundle('ZikulaBootstrapTheme')) {
162
                $this->variableApi->set(VariableApi::CONFIG, 'Default_Theme', 'ZikulaBootstrapTheme');
163
            }
164
            unset($params['upgrading']);
165
        }
166
167
        $yamlHelper->setParameters($params);
168
169
        // clear the cache
170
        $this->cacheClearer->clear('symfony.config');
171
172
        return true;
173
    }
174
175
    public function protectFiles(): bool
176
    {
177
        // protect custom_parameters.yml files
178
        $files = array_diff(scandir($this->configDir), ['.', '..']);
0 ignored issues
show
Bug introduced by
It seems like scandir($this->configDir) can also be of type false; however, parameter $array1 of array_diff() does only seem to accept array, 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

178
        $files = array_diff(/** @scrutinizer ignore-type */ scandir($this->configDir), ['.', '..']);
Loading history...
179
        foreach ($files as $file) {
180
            @chmod($file, 0400);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

180
            /** @scrutinizer ignore-unhandled */ @chmod($file, 0400);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
181
            if (!is_readable($file)) {
182
                @chmod($file, 0440);
183
                if (!is_readable($file)) {
184
                    @chmod($file, 0444);
185
                }
186
            }
187
        }
188
189
        // clear the cache
190
        $this->cacheClearer->clear('symfony.config');
191
192
        return true;
193
    }
194
195
    /**
196
     * Remove base64 encoding for admin parameters.
197
     */
198
    public function decodeParameters(array $params = []): array
199
    {
200
        if (!empty($params['password'])) {
201
            $params['password'] = base64_decode($params['password']);
202
        }
203
        if (!empty($params['username'])) {
204
            $params['username'] = base64_decode($params['username']);
205
        }
206
        if (!empty($params['email'])) {
207
            $params['email'] = base64_decode($params['email']);
208
        }
209
210
        return $params;
211
    }
212
}
213