Passed
Pull Request — master (#27)
by Keoghan
03:17 queued 23s
created

PorterLibrary::publishConfigFiles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.5

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 6
ccs 2
cts 4
cp 0.5
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2.5
1
<?php
2
3
namespace App;
4
5
use App\Exceptions\PorterSetupFailed;
6
use App\Support\FilePublisher;
7
use App\Support\Mechanics\ChooseMechanic;
8
use Illuminate\Contracts\Foundation\Application;
9
use Illuminate\Filesystem\Filesystem;
10
use Illuminate\Support\Facades\Artisan;
11
12
class PorterLibrary
13
{
14
    /** @var string */
15
    protected $path;
16
17
    /** @var Filesystem */
18
    protected $files;
19
20
    /** @var \App\Support\FilePublisher * */
21
    protected $filePublisher;
22
23
    protected $shouldMigrateAndSeedDatabase = true;
24
25 54
    public function __construct(FilePublisher $filePublisher, $path)
26
    {
27 54
        $this->filePublisher = $filePublisher;
28 54
        $this->files = $filePublisher->getFilesystem();
29 54
        $this->path = $path;
30 54
    }
31
32
    /**
33
     * Return the path for storing container config files.
34
     *
35
     * @return string
36
     */
37 54
    public function configPath()
38
    {
39 54
        return $this->path.'/config';
40
    }
41
42
    /**
43
     * Return the path of the database file.
44
     *
45
     * @return string
46
     */
47 54
    public function databaseFile()
48
    {
49 54
        return $this->path.'/database.sqlite';
50
    }
51
52
    /**
53
     * Return the path of the docker-compose file.
54
     *
55
     * @return string
56
     */
57 16
    public function dockerComposeFile()
58
    {
59 16
        return $this->path.'/docker-compose.yaml';
60
    }
61
62
    /**
63
     * Return the path of additional docker images.
64
     *
65
     * @return string
66
     */
67 54
    public function dockerImagesPath()
68
    {
69 54
        return $this->path.'/docker';
70
    }
71
72
    /**
73
     * Return the path where our generated SSL certs live.
74
     *
75
     * @return string
76
     */
77 6
    public function sslPath()
78
    {
79 6
        return $this->path.'/ssl';
80
    }
81
82
    /**
83
     * Return the library path.
84
     *
85
     * @return string
86
     */
87 5
    public function path()
88
    {
89 5
        return $this->path;
90
    }
91
92
    /**
93
     * Return the path for our additional/customised views
94
     * For example NGiNX config/ docker-compose views
95
     * for alternative container structures.
96
     *
97
     * @return string
98
     */
99 54
    public function viewsPath()
100
    {
101 54
        return $this->path.'/views';
102
    }
103
104
    /**
105
     * Check if the library has previously been set up.
106
     *
107
     * @return bool
108
     */
109 54
    public function alreadySetUp()
110
    {
111 54
        return $this->path && $this->files->exists($this->path);
112
    }
113
114
    /**
115
     * Set up the library, by creating files, storing the path in .env
116
     * creating the sqlite database and updating the app config.
117
     *
118
     * @param Application $app
119
     * @param bool        $force
120
     *
121
     * @throws PorterSetupFailed
122
     */
123 54
    public function setUp(Application $app, $force = false)
124
    {
125 54
        if ($this->alreadySetUp() && !$force) {
126
            throw new PorterSetupFailed(
127
                "The porter library already exists at '{$this->path}'. ".
128
                'You can use the --force flag to continue.'
129
            );
130
        }
131
132 54
        if (!$this->path) {
133
            $this->path = ChooseMechanic::forOS()->getUserHomePath().'/.porter';
134
135
            $this->moveExistingConfig();
136
            $this->publishEnv();
137
            $this->updateEnv();
138
        }
139
140 54
        if (!$this->path) {
141
            throw new PorterSetupFailed('Failed detecting and setting the library path for Porter.');
142
        }
143
144 54
        $this->publishConfigFiles();
145 54
        $this->createDatabase();
146 54
        $this->updateAppConfig($app);
147
148 54
        if ($this->shouldMigrateAndSeedDatabase) {
149 1
            Artisan::call('migrate:fresh');
150 1
            Artisan::call('db:seed');
151
        }
152
153 54
        $app->instance(self::class, $this);
154 54
    }
155
156
    /**
157
     * Publish the .env.example file to .env.
158
     *
159
     * @throws PorterSetupFailed
160
     */
161
    protected function publishEnv()
162
    {
163
        try {
164
            $this->filePublisher->publish(base_path('.env.example'), base_path('.env'));
165
        } catch (\Exception $e) {
166
            throw new PorterSetupFailed('Failed publishing the .env file');
167
        }
168
    }
169
170
    /**
171
     * Move any existing config at the path to a backup directory
172
     * So we can avoid wiping out data/settings completely.
173
     */
174
    protected function moveExistingConfig()
175
    {
176
        if (!$this->alreadySetUp()) {
177
            return;
178
        }
179
180
        $this->files->moveDirectory($this->path, $this->path.'_'.now()->format('YmdHis'));
181
    }
182
183
    /**
184
     * Create the sqlite database.
185
     */
186 54
    protected function createDatabase()
187
    {
188 54
        $this->files->put($this->databaseFile(), '');
189 54
    }
190
191
    /**
192
     * Update the .env file values with the new library path.
193
     *
194
     * @throws PorterSetupFailed
195
     */
196
    protected function updateEnv()
197
    {
198
        try {
199
            $envContent = $this->files->get(base_path('.env'));
200
            $envContent = preg_replace('/LIBRARY_PATH=.*\n/', "LIBRARY_PATH=\"{$this->path}\"\n", $envContent);
201
            $this->files->put(base_path('.env'), $envContent);
202
        } catch (\Exception $e) {
203
            throw new PorterSetupFailed('Failed changing library path in the .env file');
204
        }
205
    }
206
207
    /**
208
     * Update core parts of the app config.
209
     *
210
     * @param Application $app
211
     */
212 54
    protected function updateAppConfig(Application $app)
213
    {
214 54
        $app['config']->set('database.connections.default.database', $this->databaseFile());
215 54
        $app['config']->set('porter.library_path', $this->path);
216 54
    }
217
218
    /**
219
     * Publish the container config files to the library config dir.
220
     *
221
     * @throws PorterSetupFailed
222
     */
223 54
    protected function publishConfigFiles()
224
    {
225
        try {
226 54
            $this->filePublisher->publish(resource_path('stubs/config'), $this->configPath());
227
        } catch (\Exception $e) {
228
            throw new PorterSetupFailed('Failed publishing the container configuration files');
229
        }
230 54
    }
231
232
    /**
233
     * Make sure we don't try to seed and migrate (usually in tests).
234
     *
235
     * @return $this
236
     */
237 54
    public function dontMigrateAndSeedDatabase()
238
    {
239 54
        $this->shouldMigrateAndSeedDatabase = false;
240
241 54
        return $this;
242
    }
243
}
244