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

ParameterHelper   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 193
Duplicated Lines 0 %

Importance

Changes 4
Bugs 1 Features 0
Metric Value
eloc 82
c 4
b 1
f 0
dl 0
loc 193
rs 10
wmc 26

9 Methods

Rating   Name   Duplication   Size   Complexity  
A initializeParameters() 0 8 1
A __construct() 0 13 1
A writeEnvVars() 0 19 6
A finalizeParameters() 0 31 4
A getYamlHelper() 0 3 1
A configureRequestContext() 0 9 4
A decodeParameters() 0 9 4
A writeEncodedParameters() 0 11 4
A setMailerData() 0 6 1
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
    /**
184
     * Write params to file as encoded values.
185
     *
186
     * @throws AbortStageException
187
     */
188
    public function writeEncodedParameters(array $data): void
189
    {
190
        $yamlHelper = $this->getYamlHelper();
191
        foreach ($data as $k => $v) {
192
            $data[$k] = is_string($v) ? base64_encode($v) : $v; // encode so values are 'safe' for json
193
        }
194
        $params = array_merge($yamlHelper->getParameters(), $data);
195
        try {
196
            $yamlHelper->setParameters($params);
197
        } catch (IOException $exception) {
198
            throw new AbortStageException(sprintf('Cannot write parameters to %s file.', 'services_custom.yaml'));
199
        }
200
    }
201
202
    /**
203
     * Remove base64 encoding for parameters.
204
     */
205
    public function decodeParameters(array $params = []): array
206
    {
207
        foreach ($this->encodedParameterNames as $parameterName) {
208
            if (!empty($params[$parameterName])) {
209
                $params[$parameterName] = is_string($params[$parameterName]) ? base64_decode($params[$parameterName]) : $params[$parameterName];
210
            }
211
        }
212
213
        return $params;
214
    }
215
216
    private function setMailerData(array $params): void
217
    {
218
        // params have already been decoded
219
        $mailerParams = array_intersect_key($params, array_flip($this->encodedParameterNames));
220
        unset($mailerParams['mailer_key'], $mailerParams['password'], $mailerParams['username'], $mailerParams['email']);
221
        $this->variableApi->setAll('ZikulaMailerModule', $mailerParams);
222
    }
223
}
224