Passed
Pull Request — master (#6)
by Roy
14:56 queued 05:30
created

Synchronizer::getDirectory()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 6
rs 10
cc 2
nc 1
nop 0
1
<?php
2
3
namespace LaravelSynchronize\Console\Synchronizer;
4
5
use Illuminate\Filesystem\Filesystem;
6
use Illuminate\Support\Collection;
7
use Illuminate\Support\Facades\DB;
8
use Illuminate\Support\Str;
9
use Symfony\Component\Finder\SplFileInfo;
10
11
class Synchronizer
12
{
13
    /**
14
     * The filesystem instance.
15
     *
16
     * @var \Illuminate\Filesystem\Filesystem
17
     */
18
    protected $files;
19
20
    /**
21
     * The Repository instance.
22
     *
23
     * @var \LaravelSynchronize\Console\Synchronizer\SynchronizerRepository $repository
24
     */
25
    protected $repository;
26
27
    /**
28
     * Create a new controller creator command instance.
29
     *
30
     * @param  \Illuminate\Filesystem\Filesystem  $files
31
     * @param  \LaravelSynchronize\Console\Synchronizer\SynchronizerRepository  $repository
32
     *
33
     * @return void
34
     */
35
    public function __construct(FileSystem $files, SynchronizerRepository $repository)
36
    {
37
        $this->repository = $repository;
38
        $this->files = $files;
39
    }
40
41
    /**
42
     * Get the directory where synchronizations are saved
43
     * It will be created if the directive doesn't exist.
44
     *
45
     * @return string
46
     */
47
    public function getDirectory()
48
    {
49
        $directory = config('synchronizer.folder') ?? $this->getDefaultDirectory();
50
        $this->files->isDirectory($directory) ?: $this->files->makeDirectory($directory);
51
52
        return $directory;
53
    }
54
55
    /**
56
     * Get the instance of Filesystem
57
     *
58
     * @return \Illuminate\Filesystem\Filesystem
59
     */
60
    public function getFileSystem()
61
    {
62
        return $this->files;
63
    }
64
65
    /**
66
     * Get all synchronization files
67
     *
68
     * @return \Illuminate\Support\Collection
69
     */
70
    public function getSynchronizations(): Collection
71
    {
72
        return collect($this->files->files($this->getDirectory()))
73
            ->filter()
74
            ->values()
75
            ->keyBy(function ($file) {
76
                return $this->getSynchronizationName($file);
77
            })
78
            ->sortBy(function ($file, $key) {
79
                return $key;
80
            });
81
    }
82
83
    /**
84
     * Get the name of the synchronization stripped of the date and time.
85
     *
86
     * @param  string  $path
87
     *
88
     * @return string
89
     */
90
    public function getSynchronizationName($path)
91
    {
92
        $path = str_replace($this->getDirectory(), '', $path);
93
94
        return str_replace('.php', '', basename($path));
95
    }
96
97
    /**
98
     * Get the class name of a synchronization name.
99
     *
100
     * @param  string  $fileName
101
     *
102
     * @return string
103
     */
104
    public function getClassName(string $fileName)
105
    {
106
        return Str::studly(implode('_', array_slice(explode('_', $fileName), 4)));
107
    }
108
109
    /**
110
     * Determine if a synchronization exists with given name
111
     *
112
     * @param string $name
113
     *
114
     * @return boolean
115
     */
116
    public function hasSynchronization(string $name)
117
    {
118
        return !empty($this->files->glob($this->getDirectory() . "/*_*_{$name}.php"));
119
    }
120
121
    /**
122
     * Resolve a synchronization instance from a file.
123
     *
124
     * @param  string  $fileName
125
     *
126
     * @return object
127
     */
128
    public function resolve($fileName)
129
    {
130
        $class = $this->getClassName($fileName);
131
132
        return new $class();
133
    }
134
135
    /**
136
     * include the file with Require and call the class it's handler
137
     *
138
     * @param  \Symfony\Component\Finder\SplFileInfo $file
139
     *
140
     * @return void
141
     */
142
    public function run(SplFileInfo $file)
143
    {
144
        $this->files->getRequire($file);
145
146
        $synchronization = $this->resolve(
147
            $this->getSynchronizationName($file)
148
        );
149
150
        $this->startTransaction($synchronization);
151
152
        $this->tryHandle($synchronization);
153
154
        $this->repository->log(
155
            $file->getFileName(),
156
            $this->repository->getNextBatchNumber()
157
        );
158
159
        $this->commitTransaction($synchronization);
160
    }
161
162
    /**
163
     * Try to execute the resolved class, if anything fails
164
     * rollback the database changes and throw an exception.
165
     * Rollback will only work when $withTransactions is true
166
     *
167
     * @param mixed $synchronization
168
     *
169
     * @return void
170
     *
171
     * @throws \Exception
172
     */
173
    public function tryHandle($synchronization)
174
    {
175
        try {
176
            $synchronization->handle();
177
        } catch (\Exception $exception) {
178
179
            if ($synchronization->withTransactions) {
180
                DB::rollBack();
181
            }
182
183
            throw $exception;
184
        }
185
    }
186
187
    /**
188
     * If the synchronization has database transactions enabled, start the transaction
189
     *
190
     * @param mixed $synchronization
191
     *
192
     * @return void
193
     */
194
    private function startTransaction($synchronization)
195
    {
196
        if ($synchronization->withTransactions) {
197
            DB::beginTransaction();
198
        }
199
    }
200
201
    /**
202
     * If the synchronization has database transactions enabled, commit the transaction.
203
     *
204
     * @param mixed $synchronization
205
     *
206
     * @return void
207
     */
208
    private function commitTransaction($synchronization)
209
    {
210
        if ($synchronization->withTransactions) {
211
            DB::commit();
212
        }
213
    }
214
215
    /**
216
     * Get default directive synchronizations are stored
217
     *
218
     * @return string
219
     */
220
    private function getDefaultDirectory()
221
    {
222
        return database_path('synchronizations');
223
    }
224
}
225