Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
621 lars 1
<?php
2
 
3
namespace Laravel\Sail\Console\Concerns;
4
 
5
use Symfony\Component\Process\Process;
6
use Symfony\Component\Yaml\Yaml;
7
 
8
trait InteractsWithDockerComposeServices
9
{
10
    /**
11
     * The available services that may be installed.
12
     *
13
     * @var array<string>
14
     */
15
    protected $services = [
16
        'mysql',
17
        'pgsql',
18
        'mariadb',
19
        'redis',
20
        'memcached',
21
        'meilisearch',
22
        'minio',
23
        'mailpit',
24
        'selenium',
25
        'soketi',
26
    ];
27
 
28
    /**
29
     * The default services used when the user chooses non-interactive mode.
30
     *
31
     * @var string[]
32
     */
33
    protected $defaultServices = ['mysql', 'redis', 'selenium', 'mailpit'];
34
 
35
    /**
36
     * Gather the desired Sail services using a Symfony menu.
37
     *
38
     * @return array
39
     */
40
    protected function gatherServicesWithSymfonyMenu()
41
    {
42
        return $this->choice('Which services would you like to install?', $this->services, 0, null, true);
43
    }
44
 
45
    /**
46
     * Build the Docker Compose file.
47
     *
48
     * @param  array  $services
49
     * @return void
50
     */
51
    protected function buildDockerCompose(array $services)
52
    {
53
        $composePath = base_path('docker-compose.yml');
54
 
55
        $compose = file_exists($composePath)
56
            ? Yaml::parseFile($composePath)
57
            : Yaml::parse(file_get_contents(__DIR__ . '/../../../stubs/docker-compose.stub'));
58
 
59
        // Adds the new services as dependencies of the laravel.test service...
60
        if (! array_key_exists('laravel.test', $compose['services'])) {
61
            $this->warn('Couldn\'t find the laravel.test service. Make sure you add ['.implode(',', $services).'] to the depends_on config.');
62
        } else {
63
            $compose['services']['laravel.test']['depends_on'] = collect($compose['services']['laravel.test']['depends_on'] ?? [])
64
                ->merge($services)
65
                ->unique()
66
                ->values()
67
                ->all();
68
        }
69
 
70
        // Add the services to the docker-compose.yml...
71
        collect($services)
72
            ->filter(function ($service) use ($compose) {
73
                return ! array_key_exists($service, $compose['services'] ?? []);
74
            })->each(function ($service) use (&$compose) {
75
                $compose['services'][$service] = Yaml::parseFile(__DIR__ . "/../../../stubs/{$service}.stub")[$service];
76
            });
77
 
78
        // Merge volumes...
79
        collect($services)
80
            ->filter(function ($service) {
81
                return in_array($service, ['mysql', 'pgsql', 'mariadb', 'redis', 'meilisearch', 'minio']);
82
            })->filter(function ($service) use ($compose) {
83
                return ! array_key_exists($service, $compose['volumes'] ?? []);
84
            })->each(function ($service) use (&$compose) {
85
                $compose['volumes']["sail-{$service}"] = ['driver' => 'local'];
86
            });
87
 
88
        // If the list of volumes is empty, we can remove it...
89
        if (empty($compose['volumes'])) {
90
            unset($compose['volumes']);
91
        }
92
 
93
        // Replace Selenium with ARM base container on Apple Silicon...
94
        if (in_array('selenium', $services) && in_array(php_uname('m'), ['arm64', 'aarch64'])) {
95
            $compose['services']['selenium']['image'] = 'seleniarm/standalone-chromium';
96
        }
97
 
98
        file_put_contents($this->laravel->basePath('docker-compose.yml'), Yaml::dump($compose, Yaml::DUMP_OBJECT_AS_MAP));
99
    }
100
 
101
    /**
102
     * Replace the Host environment variables in the app's .env file.
103
     *
104
     * @param  array  $services
105
     * @return void
106
     */
107
    protected function replaceEnvVariables(array $services)
108
    {
109
        $environment = file_get_contents($this->laravel->basePath('.env'));
110
 
111
        if (in_array('pgsql', $services)) {
112
            $environment = str_replace('DB_CONNECTION=mysql', "DB_CONNECTION=pgsql", $environment);
113
            $environment = str_replace('DB_HOST=127.0.0.1', "DB_HOST=pgsql", $environment);
114
            $environment = str_replace('DB_PORT=3306', "DB_PORT=5432", $environment);
115
        } elseif (in_array('mariadb', $services)) {
116
            $environment = str_replace('DB_HOST=127.0.0.1', "DB_HOST=mariadb", $environment);
117
        } else {
118
            $environment = str_replace('DB_HOST=127.0.0.1', "DB_HOST=mysql", $environment);
119
        }
120
 
121
        $environment = str_replace('DB_USERNAME=root', "DB_USERNAME=sail", $environment);
122
        $environment = preg_replace("/DB_PASSWORD=(.*)/", "DB_PASSWORD=password", $environment);
123
 
124
        if (in_array('memcached', $services)) {
125
            $environment = str_replace('MEMCACHED_HOST=127.0.0.1', 'MEMCACHED_HOST=memcached', $environment);
126
        }
127
 
128
        if (in_array('redis', $services)) {
129
            $environment = str_replace('REDIS_HOST=127.0.0.1', 'REDIS_HOST=redis', $environment);
130
        }
131
 
132
        if (in_array('meilisearch', $services)) {
133
            $environment .= "\nSCOUT_DRIVER=meilisearch";
134
            $environment .= "\nMEILISEARCH_HOST=http://meilisearch:7700\n";
135
        }
136
 
137
        if (in_array('soketi', $services)) {
138
            $environment = preg_replace("/^BROADCAST_DRIVER=(.*)/m", "BROADCAST_DRIVER=pusher", $environment);
139
            $environment = preg_replace("/^PUSHER_APP_ID=(.*)/m", "PUSHER_APP_ID=app-id", $environment);
140
            $environment = preg_replace("/^PUSHER_APP_KEY=(.*)/m", "PUSHER_APP_KEY=app-key", $environment);
141
            $environment = preg_replace("/^PUSHER_APP_SECRET=(.*)/m", "PUSHER_APP_SECRET=app-secret", $environment);
142
            $environment = preg_replace("/^PUSHER_HOST=(.*)/m", "PUSHER_HOST=soketi", $environment);
143
            $environment = preg_replace("/^PUSHER_PORT=(.*)/m", "PUSHER_PORT=6001", $environment);
144
            $environment = preg_replace("/^PUSHER_SCHEME=(.*)/m", "PUSHER_SCHEME=http", $environment);
145
            $environment = preg_replace("/^VITE_PUSHER_HOST=(.*)/m", "VITE_PUSHER_HOST=localhost", $environment);
146
        }
147
 
148
        if (in_array('mailpit', $services)) {
149
            $environment = preg_replace("/^MAIL_HOST=(.*)/m", "MAIL_HOST=mailpit", $environment);
150
        }
151
 
152
        file_put_contents($this->laravel->basePath('.env'), $environment);
153
    }
154
 
155
    /**
156
     * Configure PHPUnit to use the dedicated testing database.
157
     *
158
     * @return void
159
     */
160
    protected function configurePhpUnit()
161
    {
162
        if (! file_exists($path = $this->laravel->basePath('phpunit.xml'))) {
163
            $path = $this->laravel->basePath('phpunit.xml.dist');
164
        }
165
 
166
        $phpunit = file_get_contents($path);
167
 
168
        $phpunit = preg_replace('/^.*DB_CONNECTION.*\n/m', '', $phpunit);
169
        $phpunit = str_replace('<!-- <env name="DB_DATABASE" value=":memory:"/> -->', '<env name="DB_DATABASE" value="testing"/>', $phpunit);
170
 
171
        file_put_contents($this->laravel->basePath('phpunit.xml'), $phpunit);
172
    }
173
 
174
    /**
175
     * Install the devcontainer.json configuration file.
176
     *
177
     * @return void
178
     */
179
    protected function installDevContainer()
180
    {
181
        if (! is_dir($this->laravel->basePath('.devcontainer'))) {
182
            mkdir($this->laravel->basePath('.devcontainer'), 0755, true);
183
        }
184
 
185
        file_put_contents(
186
            $this->laravel->basePath('.devcontainer/devcontainer.json'),
187
            file_get_contents(__DIR__.'/../../../stubs/devcontainer.stub')
188
        );
189
 
190
        $environment = file_get_contents($this->laravel->basePath('.env'));
191
 
192
        $environment .= "\nWWWGROUP=1000";
193
        $environment .= "\nWWWUSER=1000\n";
194
 
195
        file_put_contents($this->laravel->basePath('.env'), $environment);
196
    }
197
 
198
    /**
199
     * Prepare the installation by pulling and building any necessary images.
200
     *
201
     * @param  array  $services
202
     * @return void
203
     */
204
    protected function prepareInstallation($services)
205
    {
206
        // Ensure docker is installed...
207
        if ($this->runCommands(['docker info > /dev/null 2>&1']) !== 0) {
208
            return;
209
        }
210
 
211
        if (count($services) > 0) {
212
            $status = $this->runCommands([
213
                './vendor/bin/sail pull '.implode(' ', $services),
214
            ]);
215
 
216
            if ($status === 0) {
217
                $this->info('Sail images installed successfully.');
218
            }
219
        }
220
 
221
        $status = $this->runCommands([
222
            './vendor/bin/sail build',
223
        ]);
224
 
225
        if ($status === 0) {
226
            $this->info('Sail build successful.');
227
        }
228
    }
229
 
230
    /**
231
     * Run the given commands.
232
     *
233
     * @param  array  $commands
234
     * @return int
235
     */
236
    protected function runCommands($commands)
237
    {
238
        $process = Process::fromShellCommandline(implode(' && ', $commands), null, null, null, null);
239
 
240
        if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) {
241
            try {
242
                $process->setTty(true);
243
            } catch (\RuntimeException $e) {
244
                $this->output->writeln('  <bg=yellow;fg=black> WARN </> '.$e->getMessage().PHP_EOL);
245
            }
246
        }
247
 
248
        return $process->run(function ($type, $line) {
249
            $this->output->write('    '.$line);
250
        });
251
    }
252
}