Completed
Pull Request — master (#106)
by Jan Philipp
01:58
created

ProcessEnvironment::loadEnvVarsFromDotenvFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Psh\ScriptRuntime\Execution;
4
5
use Dotenv\Dotenv;
6
use Dotenv\Repository\Adapter\MultiReader;
7
use Dotenv\Repository\Adapter\PutenvAdapter;
8
use Dotenv\Repository\Adapter\ServerConstAdapter;
9
use Shopware\Psh\Config\DotenvFile;
10
use Shopware\Psh\Config\ScriptsPath;
11
use Symfony\Component\Process\Process;
12
use function array_keys;
13
use function array_merge;
14
use function pathinfo;
15
16
/**
17
 * Create representation of the current environment variables and constants
18
 */
19
class ProcessEnvironment
20
{
21
    /**
22
     * @var ValueProvider[]
23
     */
24
    private $constants;
25
26
    /**
27
     * @var ValueProvider[]
28
     */
29
    private $variables;
30
31
    /**
32
     * @var Template[]
33
     */
34
    private $templates;
35
36
    /**
37
     * @var array
38
     */
39
    private $dotenvVariables;
40
41
    /**
42
     * @param ScriptsPath[] $dotenvPaths
43
     */
44
    public function __construct(array $constants, array $variables, array $templates, array $dotenvPaths)
45
    {
46
        $this->constants = $this->initializeConstants($constants);
47
        $this->variables = $this->initializeVariables($variables);
48
        $this->templates = $this->initializeTemplates($templates);
49
        $this->dotenvVariables = $this->initializeDotenvVariables($dotenvPaths);
0 ignored issues
show
Documentation introduced by
$dotenvPaths is of type array<integer,object<Sho...sh\Config\ScriptsPath>>, but the function expects a array<integer,object<Sho...Psh\Config\DotenvFile>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
50
    }
51
52
    /**
53
     * @return ValueProvider[]
54
     */
55
    private function initializeConstants(array $constants): array
56
    {
57
        $resolvedValues = [];
58
        foreach ($constants as $name => $value) {
59
            $resolvedValues[$name] = new SimpleValueProvider((string) $value);
60
        }
61
62
        return $resolvedValues;
63
    }
64
65
    /**
66
     * @return ValueProvider[]
67
     */
68
    private function initializeVariables(array $variables): array
69
    {
70
        $resolvedVariables = [];
71
        foreach ($variables as $name => $shellCommand) {
72
            $process = $this->createProcess($shellCommand);
73
            $resolvedVariables[$name] = new ProcessValueProvider($process);
74
        }
75
76
        return $resolvedVariables;
77
    }
78
79
    /**
80
     * @param DotenvFile[] $dotenvPaths
81
     * @return ValueProvider[]
82
     */
83
    private function initializeDotenvVariables(array $dotenvPaths): array
84
    {
85
        $variables = [];
86
87
        foreach ($dotenvPaths as $dotenvPath) {
88
            $dotenvVariables = $this->loadDotenvVariables($dotenvPath);
89
90
            foreach ($dotenvVariables as $variableKey => $variableValue) {
91
                $variables[$variableKey] = new SimpleValueProvider($variableValue);
92
            }
93
        }
94
95
        return $variables;
96
    }
97
98
    /**
99
     * @return Template[]
100
     */
101
    private function initializeTemplates(array $templates): array
102
    {
103
        $resolvedVariables = [];
104
        foreach ($templates as $template) {
105
            $resolvedVariables[] = new Template($template['source'], $template['destination']);
106
        }
107
108
        return $resolvedVariables;
109
    }
110
111
    /**
112
     * @return ValueProvider[]
113
     */
114
    public function getAllValues(): array
115
    {
116
        return array_merge(
117
            $this->constants,
118
            $this->dotenvVariables,
119
            $this->variables
120
        );
121
    }
122
123
    /**
124
     * @return Template[]
125
     */
126
    public function getTemplates(): array
127
    {
128
        return $this->templates;
129
    }
130
131
    public function createProcess(string $shellCommand): Process
132
    {
133
        return new Process($shellCommand);
0 ignored issues
show
Documentation introduced by
$shellCommand is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
134
    }
135
136
    private function loadDotenvVariables(DotenvFile $dotenvPath): array
137
    {
138
        $fileData = $this->loadEnvVarsFromDotenvFile($dotenvPath);
139
140
        return $this->diffDotenvVarsWithCurrentApplicationEnv($fileData);
141
    }
142
143
    private function loadEnvVarsFromDotenvFile(DotenvFile $dotenvPath): array
144
    {
145
        $filePath = $dotenvPath->getPath();
146
147
        $dotenv = Dotenv::createArrayBacked(
148
            pathinfo($filePath, \PATHINFO_DIRNAME),
149
            pathinfo($filePath, \PATHINFO_BASENAME)
150
        );
151
152
        return $dotenv->load();
153
    }
154
155
    private function diffDotenvVarsWithCurrentApplicationEnv(array $fileData): array
156
    {
157
        $fileKeys = array_keys($fileData);
158
        $result = [];
159
160
        $reader = new MultiReader([
161
            PutenvAdapter::create()->get(),
162
            ServerConstAdapter::create()->get(),
163
        ]);
164
165
        foreach ($fileKeys as $key) {
166
            $option = $reader->read($key);
167
168
            if ($option->isEmpty()) {
169
                $result[$key] = $fileData[$key];
170
                continue;
171
            }
172
173
            $result[$key] = $option->get();
174
        }
175
176
        return $result;
177
    }
178
}
179