TraefikCreator::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 8
dl 0
loc 19
rs 9.9666
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php declare(strict_types=1);
2
3
namespace Cocotte\Template\Traefik;
4
5
use Cocotte\Console\Style;
6
use Cocotte\Filesystem\Filesystem;
7
use Cocotte\Shell\BasicAuth;
8
use Cocotte\Shell\EnvironmentSubstitution\EnvironmentSubstitution;
9
use Cocotte\Shell\EnvironmentSubstitution\SubstitutionFactory;
10
use Cocotte\Shell\ProcessRunner;
11
use Symfony\Component\Process\Process;
12
13
final class TraefikCreator
14
{
15
16
    /**
17
     * @var Style
18
     */
19
    private $style;
20
21
    /**
22
     * @var ProcessRunner
23
     */
24
    private $processRunner;
25
26
    /**
27
     * @var Filesystem
28
     */
29
    private $filesystem;
30
31
    /**
32
     * @var SubstitutionFactory
33
     */
34
    private $substitutionFactory;
35
36
    /**
37
     * @var TraefikHostname
38
     */
39
    private $traefikHostname;
40
41
    /**
42
     * @var TraefikPassword
43
     */
44
    private $traefikPassword;
45
46
    /**
47
     * @var TraefikUsername
48
     */
49
    private $traefikUsername;
50
51
    /**
52
     * @var BasicAuth
53
     */
54
    private $basicAuth;
55
56
    /**
57
     * @var string
58
     */
59
    private $tmpTemplatePath;
60
61
    public function __construct(
62
        Style $style,
63
        ProcessRunner $processRunner,
64
        Filesystem $filesystem,
65
        SubstitutionFactory $substitutionFactory,
66
        TraefikHostname $traefikHostname,
67
        TraefikPassword $traefikPassword,
68
        TraefikUsername $traefikUsername,
69
        BasicAuth $basicAuth
70
    ) {
71
        $this->style = $style;
72
        $this->processRunner = $processRunner;
73
        $this->filesystem = $filesystem;
74
        $this->substitutionFactory = $substitutionFactory;
75
        $this->traefikHostname = $traefikHostname;
76
        $this->traefikPassword = $traefikPassword;
77
        $this->traefikUsername = $traefikUsername;
78
        $this->basicAuth = $basicAuth;
79
        $this->tmpTemplatePath = "/tmp/".uniqid('traefik-');
80
    }
81
82
    public function create()
83
    {
84
        $this->backup();
85
        $this->copyTemplateToTmp();
86
        $this->removeIgnoredFiles();
87
        $this->createDockerComposeOverride();
88
        $this->createDotEnv();
89
        $this->copyTmpToHost();
90
    }
91
92
    public function hostAppPath(): string
93
    {
94
        return "/host/traefik";
95
    }
96
97
    private function backup(): void
98
    {
99
        $this->style->verbose('Backup');
100
        if ($this->filesystem->exists($this->hostAppPath())) {
101
            $this->style->note("Backing up old 'traefik' folder on host filesystem");
102
            $this->mustRun(
103
                [
104
                    'mv',
105
                    '-v',
106
                    $this->hostAppPath(),
107
                    $this->hostAppPath().'.'.date("YmdHis"),
108
                ]
109
            );
110
        } else {
111
            $this->style->veryVerbose('No backup was necessary');
112
        }
113
    }
114
115
    private function copyTemplateToTmp(): void
116
    {
117
        $this->style->verbose('Copy template to tmp directory');
118
        $this->cleanUpTmp();
119
        $this->mustRun(
120
            [
121
                'rsync',
122
                '-rv',
123
                $this->installerTemplatePath().'/',
124
                $this->tmpTemplatePath(),
125
            ]
126
        );
127
        $this->mustRun(['mv', '-v', $this->tmpTemplatePath(), $this->tmpAppPath()]);
128
    }
129
130
    private function removeIgnoredFiles(): void
131
    {
132
        $this->style->verbose('Remove ignored files (needed when developing only)');
133
        $this->mustRun(
134
            [
135
                'rm',
136
                '-fv',
137
                $this->tmpAppPath()."/.env",
138
                $this->tmpAppPath()."/.env-override",
139
                $this->tmpAppPath()."/docker-compose.override.yml",
140
            ]
141
        );
142
    }
143
144
    private function createDockerComposeOverride(): void
145
    {
146
        $this->style->verbose('Create ignored docker-compose.override.yml from dist');
147
        $this->mustRun(
148
            [
149
                'cp',
150
                '-v',
151
                $this->tmpAppPath()."/docker-compose.override.yml.dist",
152
                $this->tmpAppPath()."/docker-compose.override.yml",
153
            ]
154
        );
155
    }
156
157
    private function createDotEnv(): void
158
    {
159
        $this->style->verbose("Create '.env' and '.env-override' from command options + env");
160
161
        $this->createDotEnvProd();
162
        $this->createDotEnvDev();
163
    }
164
165
    private function copyTmpToHost(): void
166
    {
167
        $this->style->verbose('Copy tmp to host filesystem');
168
        $this->mustRun(
169
            [
170
                'rsync',
171
                '-rv',
172
                $this->tmpAppPath(),
173
                '/host',
174
            ]
175
        );
176
        $this->cleanUpTmp();
177
    }
178
179
    private function mustRun($command)
180
    {
181
        $this->processRunner->mustRun(new Process($command));
182
    }
183
184
    private function cleanUpTmp(): void
185
    {
186
        $this->mustRun(['rm', '-rfv', $this->tmpAppPath()]);
187
        $this->mustRun(['rm', '-rfv', $this->tmpTemplatePath()]);
188
    }
189
190
    private function tmpAppPath(): string
191
    {
192
        return "/tmp/traefik";
193
    }
194
195
    private function tmpTemplatePath(): string
196
    {
197
        return $this->tmpTemplatePath;
198
    }
199
200
    private function installerTemplatePath(): string
201
    {
202
        return "/installer/template/traefik";
203
    }
204
205
    private function createDotEnvProd(): void
206
    {
207
        EnvironmentSubstitution::withDefaults()
208
            ->restrict(
209
                [
210
                    'TRAEFIK_UI_HOSTNAME',
211
                    'TRAEFIK_ACME_EMAIL',
212
                    'MACHINE_NAME',
213
                    'MACHINE_STORAGE_PATH',
214
                ]
215
            )
216
            ->substitute($this->dotEnvProdSubstitution());
217
    }
218
219
    private function createDotEnvDev(): void
220
    {
221
        EnvironmentSubstitution::withDefaults()
222
            ->export(
223
                [
224
                    'APP_HOSTS' => $this->traefikHostname->toLocal()->toString(),
225
                ]
226
            )->substitute(
227
                $this->substitutionFactory->dumpFile(
228
                    $this->tmpAppPath().'/.env-override',
229
                    EnvironmentSubstitution::formatEnvFile(
230
                        [
231
                            'APP_HOSTS="${APP_HOSTS}"',
232
                        ]
233
                    )
234
                )
235
            );
236
    }
237
238
    /**
239
     * @return \Cocotte\Shell\EnvironmentSubstitution\DumpFileSubstitution
240
     */
241
    private function dotEnvProdSubstitution(): \Cocotte\Shell\EnvironmentSubstitution\DumpFileSubstitution
242
    {
243
        $basicAuth = $this->basicAuth->generate(
244
            $this->traefikUsername->toString(),
245
            $this->traefikPassword->toString()
246
        );
247
248
        $substitutionStrategy = $this->substitutionFactory->dumpFile(
249
            $this->tmpAppPath().'/.env',
250
            EnvironmentSubstitution::formatEnvFile(
251
                [
252
                    'APP_HOSTS="${TRAEFIK_UI_HOSTNAME}"',
253
                    "APP_AUTH_BASIC='{$basicAuth}'",
254
                    'ACME_EMAIL="${TRAEFIK_ACME_EMAIL}"',
255
                    'MACHINE_NAME="${MACHINE_NAME}"',
256
                    'MACHINE_STORAGE_PATH="${MACHINE_STORAGE_PATH}"',
257
                ]
258
            )
259
        );
260
261
        return $substitutionStrategy;
262
    }
263
}