Completed
Pull Request — master (#9)
by ARCANEDEV
04:52
created

Media   C

Complexity

Total Complexity 29

Size/Duplication

Total Lines 384
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 22

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 384
c 0
b 0
f 0
wmc 29
lcom 1
cbo 22
ccs 96
cts 96
cp 1
rs 5.7894

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A filesystem() 0 4 1
A config() 0 4 1
A getDefaultDiskName() 0 4 1
A getExcludedFiles() 0 4 1
A disk() 0 4 2
A all() 0 12 1
A file() 0 8 1
A getExcludedDirectories() 0 6 1
A directories() 0 14 1
A files() 0 21 1
A storeMany() 0 11 2
A store() 0 10 1
A makeDirectory() 0 8 1
A deleteDirectory() 0 8 1
A deleteFile() 0 8 1
A move() 0 8 1
A exists() 0 4 1
A isExcludedDirectory() 0 8 3
A checkDirectory() 0 7 1
A checkDirectoryExists() 0 6 3
A checkDirectoryAccess() 0 6 2
1
<?php namespace Arcanesoft\Media;
2
3
use Arcanesoft\Media\Contracts\Media as MediaContract;
4
use Arcanesoft\Media\Entities\DirectoryCollection;
5
use Arcanesoft\Media\Entities\FileCollection;
6
use Arcanesoft\Media\Exceptions\DirectoryNotFound;
7
use Arcanesoft\Media\Exceptions\FileNotFoundException;
8
use Carbon\Carbon;
9
use Illuminate\Contracts\Foundation\Application;
10
use Illuminate\Http\UploadedFile;
11
use Illuminate\Support\Str;
12
13
/**
14
 * Class     Media
15
 *
16
 * @package  Arcanesoft\Media
17
 * @author   ARCANEDEV <[email protected]>
18
 */
19
class Media implements MediaContract
20
{
21
    /* -----------------------------------------------------------------
22
     |  Constants
23
     | -----------------------------------------------------------------
24
     */
25
26
    const VERSION = '2.2.2';
27
28
    /* -----------------------------------------------------------------
29
     |  Properties
30
     | -----------------------------------------------------------------
31
     */
32
33
    /**
34
     * The application instance.
35
     *
36
     * @var \Illuminate\Contracts\Foundation\Application
37
     */
38
    protected $app;
39
40
    /* -----------------------------------------------------------------
41
     |  Constructor
42
     | -----------------------------------------------------------------
43
     */
44
45
    /**
46
     * Media constructor.
47
     *
48
     * @param  \Illuminate\Contracts\Foundation\Application  $app
49
     */
50 60
    public function __construct(Application $app)
51
    {
52 60
        $this->app = $app;
53 60
    }
54
55
    /* -----------------------------------------------------------------
56
     |  Getters & Setters
57
     | -----------------------------------------------------------------
58
     */
59
60
    /**
61
     * Get the Filesystem Manager instance.
62
     *
63
     * @return \Illuminate\Contracts\Filesystem\Factory
64
     */
65 40
    public function filesystem()
66
    {
67 40
        return $this->app->make('filesystem');
68
    }
69
70
    /**
71
     * Get the Config Repository.
72
     *
73
     * @return \Illuminate\Contracts\Config\Repository
74
     */
75 44
    protected function config()
76
    {
77 44
        return $this->app->make('config');
78
    }
79
80
    /**
81
     * Get the default disk name.
82
     *
83
     * @return string
84
     */
85 40
    public function getDefaultDiskName()
86
    {
87 40
        return $this->config()->get('arcanesoft.media.filesystem.default');
88
    }
89
90
    /**
91
     * Get excluded directories.
92
     *
93
     * @return array
94
     */
95 22
    public function getExcludedDirectories()
96
    {
97 22
        return Helpers\ExcludePattern::directories(
98 22
            $this->config()->get('arcanesoft.media.directories.excluded', [])
99
        );
100
    }
101
102
    /**
103
     * Get excluded files.
104
     *
105
     * @return array
106
     */
107 16
    public function getExcludedFiles()
108
    {
109 16
        return $this->config()->get('arcanesoft.media.files.excluded', []);
110
    }
111
112
    /* -----------------------------------------------------------------
113
     |  Main Methods
114
     | -----------------------------------------------------------------
115
     */
116
117
    /**
118
     * Get a filesystem adapter.
119
     *
120
     * @param  string|null  $driver
121
     *
122
     * @return \Illuminate\Filesystem\FilesystemAdapter|\Illuminate\Contracts\Filesystem\Filesystem
123
     */
124 40
    public function disk($driver = null)
125
    {
126 40
        return $this->filesystem()->disk($driver ?: $this->getDefaultDiskName());
127
    }
128
129
    /**
130
     * Get all the directories & files from a given location.
131
     *
132
     * @param  string  $directory
133
     *
134
     * @return array
135
     */
136 6
    public function all($directory = '/')
137
    {
138
        $directories = $this->directories($directory)->transform(function ($item) {
139 6
            return $item + ['type' => self::MEDIA_TYPE_DIRECTORY];
140 6
        });
141
142
        $files = $this->files($directory)->transform(function (array $item) {
143 4
            return $item + ['type' => self::MEDIA_TYPE_FILE];
144 6
        });
145
146 6
        return array_merge($directories->toArray(), $files->toArray());
147
    }
148
149
    /**
150
     * Get all of the directories within a given directory.
151
     *
152
     * @param  string  $directory
153
     *
154
     * @return \Arcanesoft\Media\Entities\DirectoryCollection
155
     */
156 14
    public function directories($directory)
157
    {
158 14
        $this->checkDirectory($directory);
159
160
        $directories = array_map(function ($dir) use ($directory) {
161
            return [
162 10
                'name' => str_replace("$directory/", '', $dir),
163 10
                'path' => $dir,
164
            ];
165 10
        }, $this->disk()->directories($directory));
166
167 10
        return DirectoryCollection::make($directories)
168 10
            ->exclude($this->getExcludedDirectories());
169
    }
170
171
    /**
172
     * Get a collection of all files in a directory.
173
     *
174
     * @param  string  $directory
175
     *
176
     * @return \Arcanesoft\Media\Entities\FileCollection
177
     */
178 14
    public function files($directory)
179
    {
180 14
        $this->checkDirectory($directory);
181
182 14
        $disk = $this->disk();
183
184
        // TODO: Add a feature to exclude unwanted files.
185
        $files = array_map(function ($filePath) use ($disk, $directory) {
186
            return [
187 12
                'name'         => str_replace("$directory/", '', $filePath),
188 12
                'path'         => $filePath,
189 12
                'url'          => $disk->url($filePath),
190 12
                'mimetype'     => $disk->mimeType($filePath),
191 12
                'lastModified' => Carbon::createFromTimestamp($disk->lastModified($filePath))->toDateTimeString(),
192 12
                'visibility'   => $disk->getVisibility($filePath),
193 12
                'size'         => $disk->size($filePath),
194
            ];
195 14
        }, $disk->files($directory));
196
197 14
        return FileCollection::make($files)->exclude($this->getExcludedFiles());
198
    }
199
200
    /**
201
     * Get the file details.
202
     *
203
     * @param  string  $path
204
     *
205
     * @return array
206
     */
207 4
    public function file($path)
208
    {
209
        return $this->files(dirname($path))->first(function ($file) use ($path) {
210 4
            return $file['path'] === $path;
211 4
        }, function () use ($path) {
212 2
            throw new FileNotFoundException("File [$path] not found!");
213 4
        });
214
    }
215
216
    /**
217
     * Store an array of files.
218
     *
219
     * @param  string  $directory
220
     * @param  array   $files
221
     *
222
     * @return array
223
     */
224 4
    public function storeMany($directory, array $files)
225
    {
226 4
        $uploaded = [];
227
228 4
        foreach ($files as $file) {
229
            /** @var \Illuminate\Http\UploadedFile $file */
230 4
            $uploaded[$directory.'/'.$file->getClientOriginalName()] = $this->store($directory, $file);
231
        }
232
233 4
        return $uploaded;
234
    }
235
236
    /**
237
     * Store a file.
238
     *
239
     * @param  string                         $path
240
     * @param  \Illuminate\Http\UploadedFile  $file
241
     * @param  array                          $options
242
     *
243
     * @return string|false
244
     */
245 8
    public function store($path, UploadedFile $file, array $options = [])
246
    {
247 8
        $options = array_merge(['disk' => $this->getDefaultDiskName()], $options);
248
249 8
        event(new Events\FileStoring($path, $file, $options));
250 8
        $storedPath = $file->storeAs($path, $file->hashName(), $options);
251 8
        event(new Events\FileStored($path, $file, $options, $storedPath));
252
253 8
        return $storedPath;
254
    }
255
256
    /**
257
     * Create a directory.
258
     *
259
     * @param  string  $path
260
     *
261
     * @return bool
262
     */
263 8
    public function makeDirectory($path)
264
    {
265 8
        event(new Events\DirectoryCreating($path));
266 8
        $created = $this->disk()->makeDirectory($path);
267 8
        event(new Events\DirectoryCreated($path, $created));
268
269 8
        return $created;
270
    }
271
272
    /**
273
     * Delete a directory.
274
     *
275
     * @param  string  $directory
276
     *
277
     * @return bool
278
     */
279 8
    public function deleteDirectory($directory)
280
    {
281 8
        event(new Events\DirectoryDeleting($directory));
282 8
        $deleted = $this->disk()->deleteDirectory($directory);
283 8
        event(new Events\DirectoryDeleted($directory, $deleted));
284
285 8
        return $deleted;
286
    }
287
288
    /**
289
     * Delete a file.
290
     *
291
     * @param  string  $path
292
     *
293
     * @return bool
294
     */
295 6
    public function deleteFile($path)
296
    {
297 6
        event(new Events\FileDeleting($path));
298 6
        $deleted = $this->disk()->delete($path);
299 6
        event(new Events\FileDeleted($path, $deleted));
300
301 6
        return $deleted;
302
    }
303
304
    /**
305
     * Move a file to a new location.
306
     *
307
     * @param  string  $from
308
     * @param  string  $to
309
     *
310
     * @return bool
311
     */
312 8
    public function move($from, $to)
313
    {
314 8
        event(new Events\FileMoving($from, $to));
315 8
        $moved = $this->disk()->move($from, $to);
316 8
        event(new Events\FileMoved($from, $to, $moved));
317
318 8
        return $moved;
319
    }
320
321
    /* -----------------------------------------------------------------
322
     |  Check Methods
323
     | -----------------------------------------------------------------
324
     */
325
326
    /**
327
     * Determine if a file/directory exists.
328
     *
329
     * @param  string  $path
330
     *
331
     * @return bool
332
     */
333 26
    public function exists($path)
334
    {
335 26
        return $this->disk()->exists($path);
336
    }
337
338
    /**
339
     * Check if the directory is excluded.
340
     *
341
     * @param  string  $directory
342
     *
343
     * @return bool
344
     */
345 20
    public function isExcludedDirectory($directory)
346
    {
347 20
        foreach ($this->getExcludedDirectories() as $pattern) {
348 20
            if (Str::is($pattern, $directory)) return true;
349
        }
350
351 18
        return false;
352
    }
353
354
    /* -----------------------------------------------------------------
355
     |  Other Methods
356
     | -----------------------------------------------------------------
357
     */
358
359
    /**
360
     * Check the given directory location.
361
     *
362
     * @param  string  &$directory
363
     *
364
     * @throws \Arcanesoft\Media\Exceptions\DirectoryNotFound
365
     * @throws \Arcanesoft\Media\Exceptions\AccessNotAllowed
366
     */
367 22
    protected function checkDirectory(&$directory)
368
    {
369 22
        $directory = trim($directory, '/');
370
371 22
        $this->checkDirectoryExists($directory);
372 20
        $this->checkDirectoryAccess($directory);
373 18
    }
374
375
    /**
376
     * Check if the directory exists.
377
     *
378
     * @param  string  $directory
379
     *
380
     * @throws \Arcanesoft\Media\Exceptions\DirectoryNotFound
381
     */
382 22
    protected function checkDirectoryExists($directory)
383
    {
384 22
        if ( ! empty($directory) && ! $this->exists($directory)) {
385 2
            throw new DirectoryNotFound("Directory [$directory] not found !", 404);
386
        }
387 20
    }
388
389
    /**
390
     * Check if can access the directory.
391
     *
392
     * @param  string  $directory
393
     *
394
     * @throws \Arcanesoft\Media\Exceptions\AccessNotAllowed
395
     */
396 20
    protected function checkDirectoryAccess($directory)
397
    {
398 20
        if ($this->isExcludedDirectory($directory)) {
399 2
            throw new Exceptions\AccessNotAllowed('Access not allowed.', 405);
400
        }
401 18
    }
402
}
403