Passed
Push — master ( 3e0c86...3b6a1a )
by Stephen
51s queued 11s
created

S3::storageDisk()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Sfneal\Helpers\Aws\S3;
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
12
class S3
13
{
14
    /**
15
     * @var string
16
     */
17
    private $s3_key;
18
19
    /**
20
     * @var string
21
     */
22
    private $disk;
23
24
    /**
25
     * S3 constructor.
26
     *
27
     * @param string $s3_key
28
     */
29
    public function __construct(string $s3_key)
30
    {
31
        $this->s3_key = $s3_key;
32
        $this->disk = config('filesystem.cloud', 's3');
33
    }
34
35
    /**
36
     * Retrieve a Filesystem instance for the specified disk.
37
     *
38
     * @return Filesystem
39
     */
40
    private function storageDisk(): Filesystem
41
    {
42
        return Storage::disk($this->disk);
43
    }
44
45
    /**
46
     * Set the filesystem disk.
47
     *
48
     * @param string $disk
49
     * @return $this
50
     */
51
    public function setDisk(string $disk): self
52
    {
53
        $this->disk = $disk;
54
55
        return $this;
56
    }
57
58
    /**
59
     * Return either an S3 file url.
60
     *
61
     * @param bool $temp
62
     * @param DateTimeInterface|null $expiration
63
     * @return string
64
     */
65
    public function url(bool $temp = true, DateTimeInterface $expiration = null): string
66
    {
67
        if ($temp) {
68
            return $this->storageDisk()->temporaryUrl($this->s3_key, $expiration ?? now()->addMinutes(60));
69
        } else {
70
            return $this->storageDisk()->url($this->s3_key);
71
        }
72
    }
73
74
    /**
75
     * Return either a temporary S3 file url.
76
     *
77
     * @param DateTimeInterface|null $expiration
78
     * @return string
79
     */
80
    public function urlTemp(DateTimeInterface $expiration = null): string
81
    {
82
        return $this->url(true, $expiration);
83
    }
84
85
    /**
86
     * Determine if an S3 file exists.
87
     *
88
     * @return bool
89
     */
90
    public function exists(): bool
91
    {
92
        return $this->storageDisk()->exists($this->s3_key);
93
    }
94
95
    /**
96
     * Upload a file to an S3 bucket.
97
     *
98
     * @param string $file_path
99
     * @param string|null $acl
100
     * @return string
101
     */
102
    public function upload(string $file_path, string $acl = null): string
103
    {
104
        if (is_null($acl)) {
105
            $this->storageDisk()->put($this->s3_key, fopen($file_path, 'r+'));
106
        } else {
107
            $this->storageDisk()->put($this->s3_key, fopen($file_path, 'r+'), $acl);
108
        }
109
110
        return $this->url();
111
    }
112
113
    /**
114
     * Upload raw file contents to an S3 bucket.
115
     *
116
     * @param string $file_contents
117
     * @param string|null $acl
118
     * @return string
119
     */
120
    public function upload_raw(string $file_contents, string $acl = null): string
121
    {
122
        if (is_null($acl)) {
123
            $this->storageDisk()->put($this->s3_key, $file_contents);
124
        } else {
125
            $this->storageDisk()->put($this->s3_key, $file_contents, $acl);
126
        }
127
128
        return $this->url();
129
    }
130
131
    /**
132
     * Download a file from an S3 bucket.
133
     *
134
     * @param string|null $file_name
135
     * @return \Illuminate\Http\Response
136
     * @throws FileNotFoundException|\League\Flysystem\FileNotFoundException
137
     */
138
    public function download(string $file_name = null): \Illuminate\Http\Response
139
    {
140
        if (is_null($file_name)) {
141
            $file_name = basename($this->s3_key);
142
        }
143
144
        $mime = $this->storageDisk()->getMimetype($this->s3_key);
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

144
        $mime = $this->storageDisk()->/** @scrutinizer ignore-call */ getMimetype($this->s3_key);
Loading history...
145
        $size = $this->storageDisk()->getSize($this->s3_key);
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

145
        $size = $this->storageDisk()->/** @scrutinizer ignore-call */ getSize($this->s3_key);
Loading history...
146
147
        $response = [
148
            'Content-Type' => $mime,
149
            'Content-Length' => $size,
150
            'Content-Description' => 'File Transfer',
151
            'Content-Disposition' => "attachment; filename={$file_name}",
152
            'Content-Transfer-Encoding' => 'binary',
153
        ];
154
155
        return Response::make($this->storageDisk()->get($this->s3_key), 200, $response);
156
    }
157
158
    /**
159
     * Delete a file or folder from an S3 bucket.
160
     *
161
     * @return bool
162
     */
163
    public function delete(): bool
164
    {
165
        return $this->storageDisk()->delete($this->s3_key);
166
    }
167
168
    /**
169
     * List all of the files in an S3 directory.
170
     *
171
     * @return array
172
     */
173
    public function list(): array
174
    {
175
        $storage = $this->storageDisk();
176
        $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

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