Completed
Pull Request — master (#4285)
by Craig
05:54
created

ParameterHelper::finalizeParameters()   B

Complexity

Conditions 11
Paths 108

Size

Total Lines 48
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 27
c 1
b 0
f 0
nc 108
nop 1
dl 0
loc 48
rs 7.25

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula - 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\Filesystem\Exception\IOException;
18
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
19
use Symfony\Component\HttpFoundation\RequestStack;
20
use Symfony\Component\Yaml\Yaml;
21
use Zikula\Bundle\CoreBundle\CacheClearer;
22
use Zikula\Bundle\CoreBundle\Helper\LocalDotEnvHelper;
23
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
24
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel;
25
use Zikula\Bundle\CoreBundle\YamlDumper;
26
use Zikula\Component\Wizard\AbortStageException;
27
use Zikula\ExtensionsModule\Api\ApiInterface\VariableApiInterface;
28
use Zikula\ExtensionsModule\Api\VariableApi;
29
30
class ParameterHelper
31
{
32
    /**
33
     * @var string
34
     */
35
    private $configDir;
36
37
    /**
38
     * @var string
39
     */
40
    private $projectDir;
41
42
    /**
43
     * @var VariableApiInterface
44
     */
45
    private $variableApi;
46
47
    /**
48
     * @var CacheClearer
49
     */
50
    private $cacheClearer;
51
52
    /**
53
     * @var RequestStack
54
     */
55
    private $requestStack;
56
57
    /**
58
     * @var ZikulaHttpKernelInterface
59
     */
60
    private $kernel;
61
62
    private $encodedParameterNames = [
63
        'password',
64
        'username',
65
        'email',
66
        'transport',
67
        'mailer_id',
68
        'mailer_key',
69
        'host',
70
        'port',
71
        'customParameters',
72
        'enableLogging'
73
    ];
74
75
    /**
76
     * ParameterHelper constructor.
77
     */
78
    public function __construct(
79
        string $projectDir,
80
        VariableApiInterface $variableApi,
81
        CacheClearer $cacheClearer,
82
        RequestStack $requestStack,
83
        ZikulaHttpKernelInterface $kernel
84
    ) {
85
        $this->configDir = $projectDir . '/config';
86
        $this->projectDir = $projectDir;
87
        $this->variableApi = $variableApi;
88
        $this->cacheClearer = $cacheClearer;
89
        $this->requestStack = $requestStack;
90
        $this->kernel = $kernel;
91
    }
92
93
    public function getYamlHelper(bool $initCopy = false): YamlDumper
94
    {
95
        $copyFile = $initCopy ? 'services.yaml' : null;
96
97
        return new YamlDumper($this->configDir, 'services_custom.yaml', $copyFile);
98
    }
99
100
    public function initializeParameters(array $paramsToMerge = []): bool
101
    {
102
        $yamlHelper = $this->getYamlHelper(true);
103
        $params = array_merge($yamlHelper->getParameters(), $paramsToMerge);
104
        $yamlHelper->setParameters($params);
105
        $this->cacheClearer->clear('symfony.config');
106
107
        return true;
108
    }
109
110
    /**
111
     * Load and set new default values from the original services.yaml file into the services_custom.yaml file.
112
     */
113
    public function reInitParameters(): bool
114
    {
115
        $originalParameters = Yaml::parse(file_get_contents($this->kernel->getProjectDir() . '/config/services.yaml'));
116
        $yamlHelper = $this->getYamlHelper();
117
        $yamlHelper->setParameters(array_merge($originalParameters['parameters'], $yamlHelper->getParameters()));
118
        $this->cacheClearer->clear('symfony.config');
119
120
        return true;
121
    }
122
123
    /**
124
     * @throws IOExceptionInterface If .env.local could not be dumped
125
     */
126
    public function finalizeParameters(bool $configureRequestContext = true): bool
127
    {
128
        $yamlHelper = $this->getYamlHelper();
129
        $params = $this->decodeParameters($yamlHelper->getParameters());
130
131
        $this->variableApi->getAll(VariableApi::CONFIG); // forces initialization of API
132
        if (!isset($params['upgrading']) || !$params['upgrading']) {
133
            $this->variableApi->set(VariableApi::CONFIG, 'locale', $params['locale']);
134
            // Set the System Identifier as a unique string.
135
            if (!$this->variableApi->get(VariableApi::CONFIG, 'system_identifier')) {
136
                $this->variableApi->set(VariableApi::CONFIG, 'system_identifier', str_replace('.', '', uniqid((string) (random_int(1000000000, 9999999999)), true)));
137
            }
138
            // add admin email as site email
139
            $this->variableApi->set(VariableApi::CONFIG, 'adminmail', $params['email']);
140
            $this->setMailerData($params);
141
        }
142
143
        $params = array_diff_key($params, array_flip($this->encodedParameterNames)); // remove all encoded params
144
        $params['datadir'] = !empty($params['datadir']) ? $params['datadir'] : 'public/uploads';
145
146
        if ($configureRequestContext) {
147
            // Configure the Request Context
148
            // see http://symfony.com/doc/current/cookbook/console/sending_emails.html#configuring-the-request-context-globally
149
            $request = $this->requestStack->getMasterRequest();
150
            $hostFromRequest = isset($request) ? $request->getHost() : null;
151
            $schemeFromRequest = isset($request) ? $request->getScheme() : 'http';
152
            $basePathFromRequest = isset($request) ? $request->getBasePath() : null;
153
            $params['router.request_context.host'] = $params['router.request_context.host'] ?? $hostFromRequest;
154
            $params['router.request_context.scheme'] = $params['router.request_context.scheme'] ?? $schemeFromRequest;
155
            $params['router.request_context.base_url'] = $params['router.request_context.base_url'] ?? $basePathFromRequest;
156
        }
157
        // store the recent version in a config var for later usage. This enables us to determine the version we are upgrading from
158
        $this->variableApi->set(VariableApi::CONFIG, 'Version_Num', ZikulaKernel::VERSION);
159
160
        $this->writeEnvVars($params);
161
        (new DbCredsHelper($this->projectDir))->writeDatabaseDsn($params);
162
163
        if (isset($params['upgrading']) && $params['upgrading']) {
164
            $this->resetLegacyParams($params);
165
        }
166
167
        // write parameters into config/services_custom.yaml
168
        $yamlHelper->setParameters($params);
169
170
        // clear the cache
171
        $this->cacheClearer->clear('symfony.config');
172
173
        return true;
174
    }
175
176
    /**
177
     * @param array $params values from upgrade
178
     */
179
    private function writeEnvVars(array $params)
180
    {
181
        $randomLibFactory = new Factory();
182
        $generator = $randomLibFactory->getMediumStrengthGenerator();
183
        $vars = [
184
            'APP_ENV' => $params['env'] ?? 'prod',
185
            'APP_DEBUG' => isset($params['debug']) ? intval($params['debug']) : 1,
186
            'APP_SECRET' => '!\'' . $params['secret'] ?? $generator->generateString(50) . '\'',
187
            'ZIKULA_INSTALLED' => '\'' . ZikulaKernel::VERSION . '\''
188
        ];
189
        (new LocalDotEnvHelper($this->projectDir))->writeLocalEnvVars($vars);
190
    }
191
192
    private function resetLegacyParams(array &$params): void
193
    {
194
        unset($params['temp_dir'], $params['system.chmod_dir'], $params['url_secret'], $params['umask']);
195
        unset($params['env'], $params['debug'], $params['secret']);
196
        unset($params['database_driver'], $params['database_host'], $params['database_port'], $params['database_name']);
197
        unset($params['database_user'], $params['database_password'], $params['database_path'], $params['database_socket'], $params['database_server_version']);
198
        $params['installed'] = '%env(ZIKULA_INSTALLED)%';
199
        $params['zikula_asset_manager.combine'] = false;
200
    }
201
202
    /**
203
     * Write params to file as encoded values.
204
     *
205
     * @throws AbortStageException
206
     */
207
    public function writeEncodedParameters(array $data): void
208
    {
209
        $yamlHelper = $this->getYamlHelper();
210
        foreach ($data as $k => $v) {
211
            $data[$k] = is_string($v) ? base64_encode($v) : $v; // encode so values are 'safe' for json
212
        }
213
        $params = array_merge($yamlHelper->getParameters(), $data);
214
        try {
215
            $yamlHelper->setParameters($params);
216
        } catch (IOException $exception) {
217
            throw new AbortStageException(sprintf('Cannot write parameters to %s file.', 'services_custom.yaml'));
218
        }
219
    }
220
221
    /**
222
     * Remove base64 encoding for parameters.
223
     */
224
    public function decodeParameters(array $params = []): array
225
    {
226
        foreach ($this->encodedParameterNames as $parameterName) {
227
            if (!empty($params[$parameterName])) {
228
                $params[$parameterName] = is_string($params[$parameterName]) ? base64_decode($params[$parameterName]) : $params[$parameterName];
229
            }
230
        }
231
232
        return $params;
233
    }
234
235
    private function setMailerData(array $params): void
236
    {
237
        // params have already been decoded
238
        $mailerParams = array_intersect_key($params, array_flip($this->encodedParameterNames));
239
        unset($mailerParams['mailer_key'], $mailerParams['password'], $mailerParams['username'], $mailerParams['email']);
240
        $this->variableApi->setAll('ZikulaMailerModule', $mailerParams);
241
    }
242
}
243