Completed
Pull Request — master (#4433)
by Craig
04:24
created

ParameterHelper::initializeParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 8
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 - 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 Zikula\Bundle\CoreBundle\CacheClearer;
21
use Zikula\Bundle\CoreBundle\Helper\LocalDotEnvHelper;
22
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
23
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel;
24
use Zikula\Bundle\CoreBundle\YamlDumper;
25
use Zikula\Component\Wizard\AbortStageException;
26
use Zikula\ExtensionsModule\Api\ApiInterface\VariableApiInterface;
27
use Zikula\ExtensionsModule\Api\VariableApi;
28
29
class ParameterHelper
30
{
31
    /**
32
     * @var string
33
     */
34
    private $configDir;
35
36
    /**
37
     * @var string
38
     */
39
    private $projectDir;
40
41
    /**
42
     * @var VariableApiInterface
43
     */
44
    private $variableApi;
45
46
    /**
47
     * @var CacheClearer
48
     */
49
    private $cacheClearer;
50
51
    /**
52
     * @var RequestStack
53
     */
54
    private $requestStack;
55
56
    /**
57
     * @var ZikulaHttpKernelInterface
58
     */
59
    private $kernel;
60
61
    private $encodedParameterNames = [
62
        'password',
63
        'username',
64
        'email',
65
        'transport',
66
        'mailer_id',
67
        'mailer_key',
68
        'host',
69
        'port',
70
        'customParameters',
71
        'enableLogging'
72
    ];
73
74
    /**
75
     * ParameterHelper constructor.
76
     */
77
    public function __construct(
78
        string $projectDir,
79
        VariableApiInterface $variableApi,
80
        CacheClearer $cacheClearer,
81
        RequestStack $requestStack,
82
        ZikulaHttpKernelInterface $kernel
83
    ) {
84
        $this->configDir = $projectDir . '/config';
85
        $this->projectDir = $projectDir;
86
        $this->variableApi = $variableApi;
87
        $this->cacheClearer = $cacheClearer;
88
        $this->requestStack = $requestStack;
89
        $this->kernel = $kernel;
90
    }
91
92
    public function getYamlHelper(): YamlDumper
93
    {
94
        return new YamlDumper($this->configDir, 'temp_params.yaml');
0 ignored issues
show
Deprecated Code introduced by
The class Zikula\Bundle\CoreBundle\YamlDumper has been deprecated. ( Ignorable by Annotation )

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

94
        return /** @scrutinizer ignore-deprecated */ new YamlDumper($this->configDir, 'temp_params.yaml');
Loading history...
95
    }
96
97
    public function initializeParameters(array $paramsToMerge = []): bool
98
    {
99
        $yamlHelper = $this->getYamlHelper();
100
        $params = array_merge($yamlHelper->getParameters(), $paramsToMerge);
101
        $yamlHelper->setParameters($params);
102
        $this->cacheClearer->clear('symfony.config');
103
104
        return true;
105
    }
106
107
    /**
108
     * @throws IOExceptionInterface If .env.local could not be dumped
109
     */
110
    public function finalizeParameters(): bool
111
    {
112
        $yamlHelper = $this->getYamlHelper();
113
        $params = $this->decodeParameters($yamlHelper->getParameters());
114
115
        $this->variableApi->getAll(VariableApi::CONFIG); // forces initialization of API
116
        if (!isset($params['upgrading']) || !$params['upgrading']) {
117
            $this->variableApi->set(VariableApi::CONFIG, 'locale', $params['locale']);
118
            // Set the System Identifier as a unique string.
119
            if (!$this->variableApi->get(VariableApi::CONFIG, 'system_identifier')) {
120
                $this->variableApi->set(VariableApi::CONFIG, 'system_identifier', str_replace('.', '', uniqid((string) (random_int(1000000000, 9999999999)), true)));
121
            }
122
            // add admin email as site email
123
            $this->variableApi->set(VariableApi::CONFIG, 'adminmail', $params['email']);
124
            $this->setMailerData($params);
125
            $this->configureRequestContext($params);
126
        }
127
128
        $params = array_diff_key($params, array_flip($this->encodedParameterNames)); // remove all encoded params
129
130
        // store the recent version in a config var for later usage. This enables us to determine the version we are upgrading from
131
        $this->variableApi->set(VariableApi::CONFIG, 'Version_Num', ZikulaKernel::VERSION);
132
133
        $this->writeEnvVars($params);
134
135
        $yamlHelper->deleteFile();
136
137
        // clear the cache
138
        $this->cacheClearer->clear('symfony.config');
139
140
        return true;
141
    }
142
143
    /**
144
     * Configure the Request Context
145
     * see https://symfony.com/doc/current/routing.html#generating-urls-in-commands
146
     * This is needed because emails are sent from CLI requiring routes to be built
147
     */
148
    private function configureRequestContext(array &$params): void
149
    {
150
        $request = $this->requestStack->getMasterRequest();
151
        $hostFromRequest = isset($request) ? $request->getHost() : 'localhost';
152
        $schemeFromRequest = isset($request) ? $request->getScheme() : 'http';
153
        $basePathFromRequest = isset($request) ? $request->getBasePath() : null;
154
        $params['router.request_context.host'] = $params['router.request_context.host'] ?? $hostFromRequest;
155
        $params['router.request_context.scheme'] = $params['router.request_context.scheme'] ?? $schemeFromRequest;
156
        $params['router.request_context.base_url'] = $params['router.request_context.base_url'] ?? $basePathFromRequest;
157
    }
158
159
    /**
160
     * @param array $params values from upgrade
161
     */
162
    private function writeEnvVars(array &$params): void
163
    {
164
        $randomLibFactory = new Factory();
165
        $generator = $randomLibFactory->getMediumStrengthGenerator();
166
        $secret = isset($params['secret']) && !empty($params['secret']) && '%env(APP_SECRET)%' !== $params['secret']
167
            ? $params['secret']
168
            : $generator->generateString(50)
169
        ;
170
        $vars = [
171
            'APP_ENV' => $params['env'] ?? 'prod',
172
            'APP_DEBUG' => isset($params['debug']) ? (int) ($params['debug']) : 0,
173
            'APP_SECRET' => '!\'' . $secret . '\'',
174
            'ZIKULA_INSTALLED' => '\'' . ZikulaKernel::VERSION . '\''
175
        ];
176
        if (isset($params['router.request_context.host'])) {
177
            $vars['DEFAULT_URI'] = sprintf('!%s://%s%s', $params['router.request_context.scheme'], $params['router.request_context.host'], $params['router.request_context.base_url']);
178
            unset($params['router.request_context.scheme'], $params['router.request_context.host'], $params['router.request_context.base_url']);
179
        }
180
        (new LocalDotEnvHelper($this->projectDir))->writeLocalEnvVars($vars);
181
    }
182
183
    private function resetLegacyParams(array &$params): void
0 ignored issues
show
Unused Code introduced by
The method resetLegacyParams() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
184
    {
185
        unset(
186
            $params['temp_dir'],
187
            $params['system.chmod_dir'],
188
            $params['url_secret'],
189
            $params['umask'],
190
            $params['env'],
191
            $params['debug'],
192
            $params['secret'],
193
            $params['database_driver'],
194
            $params['database_host'],
195
            $params['database_port'],
196
            $params['database_name'],
197
            $params['database_user'],
198
            $params['database_password'],
199
            $params['database_path'],
200
            $params['database_socket'],
201
            $params['database_server_version']
202
        );
203
    }
204
205
    /**
206
     * Write params to file as encoded values.
207
     *
208
     * @throws AbortStageException
209
     */
210
    public function writeEncodedParameters(array $data): void
211
    {
212
        $yamlHelper = $this->getYamlHelper();
213
        foreach ($data as $k => $v) {
214
            $data[$k] = is_string($v) ? base64_encode($v) : $v; // encode so values are 'safe' for json
215
        }
216
        $params = array_merge($yamlHelper->getParameters(), $data);
217
        try {
218
            $yamlHelper->setParameters($params);
219
        } catch (IOException $exception) {
220
            throw new AbortStageException(sprintf('Cannot write parameters to %s file.', 'services_custom.yaml'));
221
        }
222
    }
223
224
    /**
225
     * Remove base64 encoding for parameters.
226
     */
227
    public function decodeParameters(array $params = []): array
228
    {
229
        foreach ($this->encodedParameterNames as $parameterName) {
230
            if (!empty($params[$parameterName])) {
231
                $params[$parameterName] = is_string($params[$parameterName]) ? base64_decode($params[$parameterName]) : $params[$parameterName];
232
            }
233
        }
234
235
        return $params;
236
    }
237
238
    private function setMailerData(array $params): void
239
    {
240
        // params have already been decoded
241
        $mailerParams = array_intersect_key($params, array_flip($this->encodedParameterNames));
242
        unset($mailerParams['mailer_key'], $mailerParams['password'], $mailerParams['username'], $mailerParams['email']);
243
        $this->variableApi->setAll('ZikulaMailerModule', $mailerParams);
244
    }
245
}
246