FileManager::getAdapter()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
1
<?php namespace Nord\Lumen\FileManager;
2
3
use Carbon\Carbon;
4
use Illuminate\Contracts\Filesystem\Factory as FilesystemFactory;
5
use Nord\Lumen\FileManager\Contracts\FileFactory;
6
use Nord\Lumen\FileManager\Contracts\IdGenerator;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Nord\Lumen\FileManager\IdGenerator.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
use Nord\Lumen\FileManager\Contracts\DiskAdapter;
8
use Nord\Lumen\FileManager\Contracts\File as FileContract;
9
use Nord\Lumen\FileManager\Contracts\FileManager as FileManagerContract;
10
use Nord\Lumen\FileManager\Contracts\FileStorage;
11
use Nord\Lumen\FileManager\Exceptions\AdapterException;
12
use Nord\Lumen\FileManager\Exceptions\StorageException;
13
use Symfony\Component\HttpFoundation\File\File as FileInfo;
14
use Symfony\Component\HttpFoundation\File\UploadedFile;
15
16
class FileManager implements FileManagerContract
17
{
18
19
    /**
20
     * @var FilesystemFactory
21
     */
22
    private $filesystem;
23
24
    /**
25
     * @var FileFactory
26
     */
27
    private $factory;
28
29
    /**
30
     * @var FileStorage
31
     */
32
    private $storage;
33
34
    /**
35
     * @var IdGenerator
36
     */
37
    private $idGenerator;
38
39
    /**
40
     * @var DiskAdapter[]
41
     */
42
    private $adapters = [];
43
44
45
    /**
46
     * FileManager constructor.
47
     *
48
     * @param FilesystemFactory $filesystem
49
     * @param FileFactory       $factory
50
     * @param FileStorage       $storage
51
     */
52
    public function __construct(FilesystemFactory $filesystem, FileFactory $factory, FileStorage $storage)
53
    {
54
        $this->filesystem = $filesystem;
55
        $this->factory    = $factory;
56
        $this->storage    = $storage;
57
    }
58
59
60
    /**
61
     * @inheritdoc
62
     */
63
    public function saveFile(FileInfo $info, array $options = [])
64
    {
65
        if (!isset($options['name'])) {
66
            $filename        = $this->getFilenameFromFileInfo($info);
67
            $options['name'] = substr($filename, 0, (strrpos($filename, '.')));
68
        }
69
70
        $file = $this->factory->createFile(
71
            $this->generateId(),
72
            $this->normalizeName(array_pull($options, 'name')),
73
            $this->getExtensionFromFileInfo($info),
74
            array_pull($options, 'path'),
75
            $info->getMimeType(),
76
            $info->getSize(),
77
            $this->extractDataFromFileInfo($info),
78
            array_pull($options, 'disk', FileContract::DISK_LOCAL),
79
            Carbon::now()
80
        );
81
82
        $disk     = $file->getDisk();
83
        $savePath = $file->getFilePath();
84
85
        $resource    = fopen($info->getRealPath(), 'r+');
86
        $savedToDisk = $this->getAdapter($disk)->saveFile($savePath, $resource, $options);
87
        if (is_resource($resource)) {
88
            fclose($resource);
89
        }
90
        if (!$savedToDisk) {
91
            throw new AdapterException("Failed to save file on disk.");
92
        }
93
94
        if (!$this->storage->saveFile($file)) {
95
            throw new StorageException("Failed to insert file into database.");
96
        }
97
98
        return $file;
99
    }
100
101
102
    /**
103
     * @inheritdoc
104
     */
105
    public function getFile($id)
106
    {
107
        return $this->storage->getFile($id);
108
    }
109
110
111
    /**
112
     * @inheritdoc
113
     */
114
    public function getFilePath(FileContract $file, array $options = [])
115
    {
116
        return $this->getAdapter($file->getDisk())->getFilePath($file, $options);
117
    }
118
119
120
    /**
121
     * @inheritdoc
122
     */
123
    public function getFileUrl(FileContract $file, array $options = [])
124
    {
125
        return $this->getAdapter($file->getDisk())->getFileUrl($file, $options);
126
    }
127
128
129
    /**
130
     * @inheritdoc
131
     */
132
    public function deleteFile(FileContract $file, array $options = [])
133
    {
134
        if (!$this->getAdapter($file->getDisk())->deleteFile($file, $options)) {
135
            throw new AdapterException("Failed to remove file from disk.");
136
        }
137
138
        if (!$this->storage->deleteFile($file->getId())) {
139
            throw new StorageException("Failed to delete file from database.");
140
        }
141
    }
142
143
144
    /**
145
     * @param DiskAdapter $adapter
146
     */
147
    public function addAdapter(DiskAdapter $adapter)
148
    {
149
        $name = $adapter->getName();
150
151
        $adapter->setFilesystem($this->filesystem->disk($name));
152
153
        $this->adapters[$name] = $adapter;
154
    }
155
156
157
    /**
158
     * @param IdGenerator $idGenerator
159
     */
160
    public function setIdGenerator(IdGenerator $idGenerator)
161
    {
162
        $this->idGenerator = $idGenerator;
163
    }
164
165
166
    /**
167
     * @param string $name
168
     *
169
     * @return DiskAdapter
170
     * @throws AdapterException
171
     */
172
    protected function getAdapter($name)
173
    {
174
        if (!isset($this->adapters[$name])) {
175
            throw new AdapterException("Adapter for filesystem '$name' not found.");
176
        }
177
178
        return $this->adapters[$name];
179
    }
180
181
182
    /**
183
     * @return mixed
184
     */
185
    protected function generateId()
186
    {
187
        while (!isset($id) || $this->storage->idExists($id)) {
188
            $id = $this->idGenerator->generate();
189
        }
190
191
        return $id;
192
    }
193
194
195
    /**
196
     * @param string $name
197
     *
198
     * @return string
199
     */
200
    protected function normalizeName($name)
201
    {
202
        return $name !== null ? str_slug($name) : null;
203
    }
204
205
206
    /**
207
     * @param FileInfo $info
208
     *
209
     * @return null|string
210
     */
211
    protected function getFilenameFromFileInfo(FileInfo $info)
212
    {
213
        return $info instanceof UploadedFile ? $info->getClientOriginalName() : $info->getFilename();
214
    }
215
216
217
    /**
218
     * @param FileInfo $info
219
     *
220
     * @return string
221
     */
222
    protected function getExtensionFromFileInfo(FileInfo $info)
223
    {
224
        return $info instanceof UploadedFile ? $info->getClientOriginalExtension() : $info->getExtension();
225
    }
226
227
228
    /**
229
     * @param FileInfo $info
230
     *
231
     * @return array
232
     */
233
    protected function extractDataFromFileInfo(FileInfo $info)
234
    {
235
        $data = [];
236
237
        if ($info instanceof UploadedFile) {
238
            $data['original_name']      = $info->getClientOriginalName();
239
            $data['original_extension'] = $info->getClientOriginalExtension();
240
        }
241
242
        return $data;
243
    }
244
}
245