StaticSiteCreator::createDotEnvProd()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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