Test Failed
Pull Request — master (#13)
by Stephen
06:57 queued 02:45
created

S3::allFiles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Sfneal\Helpers\Aws\S3\Utils;
4
5
use Closure;
6
use DateTimeInterface;
7
use Illuminate\Contracts\Filesystem\FileNotFoundException;
8
use Illuminate\Contracts\Filesystem\Filesystem;
9
use Illuminate\Support\Facades\Response;
10
use Illuminate\Support\Facades\Storage;
11
use Sfneal\Helpers\Aws\S3\Interfaces\S3Filesystem;
12
13
class S3 implements S3Filesystem
14
{
15
    /**
16
     * @var string
17
     */
18
    private $s3Key;
19
20
    /**
21
     * @var string
22
     */
23
    private $disk;
24
25
    /**
26
     * S3 constructor.
27
     *
28
     * @param string $s3_key
29
     */
30
    public function __construct(string $s3_key)
31
    {
32
        $this->s3Key = $s3_key;
33
        $this->disk = config('filesystem.cloud', 's3');
34
    }
35
36
    /**
37
     * Retrieve a Filesystem instance for the specified disk.
38
     *
39
     * @return Filesystem
40
     */
41
    private function storageDisk(): Filesystem
42
    {
43
        return Storage::disk($this->disk);
44
    }
45
46
    /**
47
     * Set the filesystem disk.
48
     *
49
     * @param string $disk
50
     * @return $this
51
     */
52
    public function setDisk(string $disk): self
53
    {
54
        $this->disk = $disk;
55
56
        return $this;
57
    }
58
59
    /**
60
     * Return either an S3 file url.
61
     *
62
     * @return string
63
     */
64
    public function url(): string
65
    {
66
        return $this->storageDisk()->url($this->s3Key);
67
    }
68
69
    /**
70
     * Return either a temporary S3 file url.
71
     *
72
     * @param DateTimeInterface|null $expiration
73
     * @return string
74
     */
75
    public function urlTemp(DateTimeInterface $expiration = null): string
76
    {
77
        return $this->storageDisk()->temporaryUrl($this->s3Key, $expiration ?? now()->addMinutes(60));
78
    }
79
80
    /**
81
     * Determine if an S3 file exists.
82
     *
83
     * @return bool
84
     */
85
    public function exists(): bool
86
    {
87
        return $this->storageDisk()->exists($this->s3Key);
88
    }
89
90
    /**
91
     * Determine if an S3 file is missing.
92
     *
93
     * @return bool
94
     */
95
    public function missing(): bool
96
    {
97
        return ! $this->exists();
98
    }
99
100
    /**
101
     * Upload a file to an S3 bucket.
102
     *
103
     * @param string $localFilePath
104
     * @param string|null $acl
105
     * @return string
106
     */
107
    public function upload(string $localFilePath, string $acl = null): string
108
    {
109
        if (is_null($acl)) {
110
            $this->storageDisk()->put($this->s3Key, fopen($localFilePath, 'r+'));
111
        } else {
112
            $this->storageDisk()->put($this->s3Key, fopen($localFilePath, 'r+'), $acl);
113
        }
114
115
        return $this->url();
116
    }
117
118
    /**
119
     * Upload raw file contents to an S3 bucket.
120
     *
121
     * @param string $fileContents
122
     * @param string|null $acl
123
     * @return string
124
     */
125
    public function upload_raw(string $fileContents, string $acl = null): string
126
    {
127
        if (is_null($acl)) {
128
            $this->storageDisk()->put($this->s3Key, $fileContents);
129
        } else {
130
            $this->storageDisk()->put($this->s3Key, $fileContents, $acl);
131
        }
132
133
        return $this->url();
134
    }
135
136
    /**
137
     * Download a file from an S3 bucket.
138
     *
139
     * @param string|null $fileName
140
     * @return \Illuminate\Http\Response
141
     * @throws FileNotFoundException|\League\Flysystem\FileNotFoundException
142
     */
143
    public function download(string $fileName = null): \Illuminate\Http\Response
144
    {
145
        if (is_null($fileName)) {
146
            $fileName = basename($this->s3Key);
147
        }
148
149
        $mime = $this->storageDisk()->getMimetype($this->s3Key);
0 ignored issues
show
Bug introduced by
The method getMimetype() does not exist on Illuminate\Contracts\Filesystem\Filesystem. It seems like you code against a sub-type of Illuminate\Contracts\Filesystem\Filesystem such as Illuminate\Filesystem\FilesystemAdapter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

149
        $mime = $this->storageDisk()->/** @scrutinizer ignore-call */ getMimetype($this->s3Key);
Loading history...
150
        $size = $this->storageDisk()->getSize($this->s3Key);
0 ignored issues
show
Bug introduced by
The method getSize() does not exist on Illuminate\Contracts\Filesystem\Filesystem. It seems like you code against a sub-type of Illuminate\Contracts\Filesystem\Filesystem such as Illuminate\Filesystem\FilesystemAdapter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

150
        $size = $this->storageDisk()->/** @scrutinizer ignore-call */ getSize($this->s3Key);
Loading history...
151
152
        $response = [
153
            'Content-Type' => $mime,
154
            'Content-Length' => $size,
155
            'Content-Description' => 'File Transfer',
156
            'Content-Disposition' => "attachment; filename={$fileName}",
157
            'Content-Transfer-Encoding' => 'binary',
158
        ];
159
160
        return Response::make($this->storageDisk()->get($this->s3Key), 200, $response);
161
    }
162
163
    /**
164
     * Delete a file or folder from an S3 bucket.
165
     *
166
     * @return bool
167
     */
168
    public function delete(): bool
169
    {
170
        return $this->storageDisk()->delete($this->s3Key);
171
    }
172
173
    /**
174
     * List all of the files in an S3 directory.
175
     *
176
     * @return array
177
     */
178
    public function list(): array
179
    {
180
        $storage = $this->storageDisk();
181
        $client = $storage->getAdapter()->getClient();
0 ignored issues
show
Bug introduced by
The method getAdapter() does not exist on Illuminate\Contracts\Filesystem\Filesystem. It seems like you code against a sub-type of Illuminate\Contracts\Filesystem\Filesystem such as Illuminate\Filesystem\FilesystemAdapter. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

181
        $client = $storage->/** @scrutinizer ignore-call */ getAdapter()->getClient();
Loading history...
182
        $command = $client->getCommand('ListObjects');
183
        $command['Bucket'] = $storage->getAdapter()->getBucket();
184
        $command['Prefix'] = $this->s3Key;
185
        $result = $client->execute($command);
186
187
        $files = [];
188
        if (isset($result['Contents']) && ! empty($result['Contents'])) {
189
            foreach ($result['Contents'] as $content) {
190
                $url = fileURL($content['Key']);
191
                $parts = explode('/', explode('?', $url, 2)[0]);
192
                $files[] = [
193
                    'name' => end($parts),
194
                    'url' => $url,
195
                    'key' => $content['Key'],
196
                ];
197
            }
198
        }
199
200
        return $files;
201
    }
202
203
    /**
204
     * Autocomplete an S3 path by providing the known start of a path.
205
     *
206
     * - once path autocompletion is resolved the $s3_key property is replaced with the found path
207
     *
208
     * @return $this
209
     */
210
    public function autocompletePath(): self
211
    {
212
        // Extract the known $base of the path & the $wildcard
213
        $base = dirname($this->s3Key);
214
        $wildcard = basename($this->s3Key);
215
216
        // Get all of the folders in the base directory
217
        $folders = $this->storageDisk()->directories($base);
218
219
        // Filter folders to find the wildcard path
220
        $folders = array_filter($folders, function ($value) use ($base, $wildcard) {
221
            return str_starts_with($value, $base.DIRECTORY_SEPARATOR.$wildcard);
222
        });
223
224
        // return the resolved path
225
        $this->s3Key = collect($folders)->values()->first();
226
227
        return $this;
228
    }
229
230
    /**
231
     * Retrieve an array of all files in a directory with an optional filtering closure.
232
     *
233
     * @param Closure|null $closure
234
     * @return array
235
     */
236
    public function allFiles(Closure $closure = null): array
237
    {
238
        // Create array of all files
239
        $allFiles = $this->storageDisk()->allFiles($this->s3Key);
240
241
        // Apply filtering closure
242
        if (isset($closure)) {
243
            return array_filter(array_values($allFiles), $closure);
244
        }
245
246
        return $allFiles;
247
    }
248
249
    /**
250
     * Retrieve an array of all directories within another directory with an optional filtering closure.
251
     *
252
     * @param Closure|null $closure
253
     * @return array
254
     */
255
    public function allDirectories(Closure $closure = null): array
256
    {
257
        // Create array of all directories
258
        $allDirectories = $this->storageDisk()->allDirectories($this->s3Key);
259
260
        // Apply filtering closure
261
        if (isset($closure)) {
262
            return array_filter(array_values($allDirectories), $closure);
263
        }
264
265
        return $allDirectories;
266
    }
267
}
268