DockerSync::adjustDockerComposeSetup()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 3.0021

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 17
c 1
b 0
f 0
dl 0
loc 27
ccs 15
cts 16
cp 0.9375
rs 9.7
cc 3
nc 3
nop 1
crap 3.0021
1
<?php
2
3
namespace App\Support\DockerSync;
4
5
use App\Models\PhpVersion;
6
use App\PorterLibrary;
7
use App\Support\Contracts\Cli;
8
use App\Support\Mechanics\MacOs;
9
use App\Support\Mechanics\Mechanic;
10
use Illuminate\Filesystem\Filesystem;
11
use Symfony\Component\Yaml\Yaml;
12
13
class DockerSync
14
{
15
    /** @var Mechanic */
16
    protected $mechanic;
17
    /** @var Cli */
18
    protected $cli;
19
    /** @var FileSystem */
20
    protected $files;
21
    /** @var PorterLibrary */
22
    private $library;
23
24 210
    public function __construct(Mechanic $mechanic, Cli $cli, Filesystem $files, PorterLibrary $library)
25
    {
26 210
        $this->mechanic = $mechanic;
27 210
        $this->cli = $cli;
28 210
        $this->files = $files;
29 210
        $this->library = $library;
30
    }
31
32
    /**
33
     * Check if docker-sync is active.
34
     *
35
     * @return bool
36
     */
37 13
    public function isActive()
38
    {
39 13
        return setting('use_docker-sync') === 'on';
40
    }
41
42
    /**
43
     * Install docker-sync.
44
     *
45
     * @throws CannotInstallDockerSync
46
     */
47 3
    public function install()
48
    {
49 3
        $this->checkForMacOs();
50
51 1
        $this->cli->passthru('gem install --user-install docker-sync');
52
    }
53
54
    /**
55
     * Check this command is running on MacOS.
56
     *
57
     * @throws CannotInstallDockerSync
58
     */
59 3
    protected function checkForMacOs(): void
60
    {
61 3
        if (get_class($this->mechanic) !== MacOs::class) {
62 2
            throw new CannotInstallDockerSync('The OS must be MacOs');
63
        }
64
    }
65
66
    /**
67
     * Adjust the docker-compose file to point to sync volumes, create docker-sync.yaml.
68
     *
69
     * MySQL and Redis usage not explored as yet.
70
     *
71
     * @param string $composeFile
72
     *
73
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
74
     */
75 1
    public function adjustDockerComposeSetup(string $composeFile)
76
    {
77 1
        if (!$this->isActive()) {
78
            return;
79
        }
80
81 1
        $composeYaml = $this->getYaml($composeFile);
82 1
        $syncYamlFile = dirname($composeFile).'/docker-sync.yml';
83
        $syncYaml = [
84
            'version' => 2,
85 1
            'syncs'   => $this->getSyncs(),
86
        ];
87
88 1
        foreach (PhpVersion::active()->get() as $version) {
89 1
            $composeYaml['services'][$version->cli_name]['volumes'][0] = $this->replaceSync($composeYaml['services'][$version->cli_name]['volumes'][0]);
90 1
            $composeYaml['services'][$version->fpm_name]['volumes'][0] = $this->replaceSync($composeYaml['services'][$version->fpm_name]['volumes'][0]);
91
        }
92
93 1
        $composeYaml['services']['node']['volumes'][0] = $this->replaceSync($composeYaml['services']['node']['volumes'][0]);
94 1
        $composeYaml['services']['nginx']['volumes'][0] = $this->replaceSync($composeYaml['services']['nginx']['volumes'][0]);
95
96 1
        $composeYaml['volumes'] = array_map(function () {
97 1
            return ['external' => true];
98 1
        }, $this->getSyncs());
99
100 1
        $this->putYaml($composeFile, $composeYaml);
101 1
        $this->putYaml($syncYamlFile, $syncYaml);
102
    }
103
104 1
    protected function getSyncs()
105
    {
106
        return [
107
            'home' => [
108 1
                'src'           => setting('home'),
109
                'watch_excludes'=> ['.*/.git', '.*/node_modules'],
110
            ],
111
        ];
112
    }
113
114 1
    protected function replaceSync($string, $sync = 'home')
115
    {
116 1
        $pathParts = explode(':', $string);
117
118 1
        $source = $pathParts[0];
119 1
        $target = $pathParts[1];
120
121 1
        $syncPath = $this->getSyncs()[$sync]['src'];
122
123 1
        if ($source !== $syncPath) {
0 ignored issues
show
introduced by
The condition $source !== $syncPath is always true.
Loading history...
124
            return $string;
125
        }
126
127 1
        return implode(':', [$sync, $target, 'nocopy']);
128
    }
129
130
    /**
131
     * Get the yaml from the file.
132
     *
133
     * @param string $file
134
     *
135
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
136
     *
137
     * @return mixed
138
     */
139 1
    public function getYaml(string $file)
140
    {
141 1
        return Yaml::parse($this->files->get($file));
142
    }
143
144
    /**
145
     * Save array to yaml file.
146
     *
147
     * @param string $file
148
     * @param array  $yaml
149
     */
150 1
    public function putYaml(string $file, array $yaml)
151
    {
152 1
        $this->files->put($file, Yaml::dump($yaml, 5, 2));
153
    }
154
155
    /**
156
     * Start the docker-syn daemon.
157
     */
158 4
    public function startDaemon()
159
    {
160 4
        if (!$this->isActive()) {
161 4
            return;
162
        }
163
164 1
        $this->cli->execRealTime($this->getPath().'docker-sync start --config="'.$this->library->path().'/docker-sync.yml"');
165
    }
166
167
    /**
168
     * Stop the docker-sync daemon.
169
     */
170 5
    public function stopDaemon()
171
    {
172 5
        if (!$this->isActive()) {
173 5
            return;
174
        }
175
176 1
        $this->cli->execRealTime($this->getPath().'docker-sync stop --config="'.$this->library->path().'/docker-sync.yml"');
177
    }
178
179
    /**
180
     * Get the path for docker-sync.
181
     *
182
     * @return string
183
     */
184 2
    public function getPath()
185
    {
186 2
        return str_replace("\n", '', $this->cli->exec("ruby -r rubygems -e 'puts Gem.user_dir'")).'/bin/';
187
    }
188
}
189