Issues (4)

src/BackblazeAdapter.php (4 issues)

1
<?php
2
3
namespace Mhetreramesh\Flysystem;
4
5
use BackblazeB2\Client;
6
use GuzzleHttp\Psr7;
7
use League\Flysystem\Adapter\AbstractAdapter;
8
use League\Flysystem\Adapter\Polyfill\NotSupportingVisibilityTrait;
9
use League\Flysystem\Config;
10
11
class BackblazeAdapter extends AbstractAdapter
12
{
13
    use NotSupportingVisibilityTrait;
14
15
    protected $client;
16
17
    protected $bucketName;
18
19
    protected $bucketId;
20
21
    public function __construct(Client $client, $bucketName, $bucketId = null)
22
    {
23
        $this->client = $client;
24
        $this->bucketName = $bucketName;
25
        $this->bucketId = $bucketId;
26
    }
27
28
    /**
29
     * {@inheritdoc}
30
     */
31 1
    public function has($path)
32
    {
33 1
        return $this->getClient()->fileExists(['FileName' => $path, 'BucketId' => $this->bucketId, 'BucketName' => $this->bucketName]);
34
    }
35
36
    /**
37
     * {@inheritdoc}
38
     */
39 1
    public function write($path, $contents, Config $config)
40
    {
41 1
        $file = $this->getClient()->upload([
42 1
            'BucketId'   => $this->bucketId,
43 1
            'BucketName' => $this->bucketName,
44 1
            'FileName'   => $path,
45 1
            'Body'       => $contents,
46
        ]);
47
48 1
        return $this->getFileInfo($file);
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54 1
    public function writeStream($path, $resource, Config $config)
55
    {
56 1
        $file = $this->getClient()->upload([
57 1
            'BucketId'   => $this->bucketId,
58 1
            'BucketName' => $this->bucketName,
59 1
            'FileName'   => $path,
60 1
            'Body'       => $resource,
61
        ]);
62
63 1
        return $this->getFileInfo($file);
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69 1
    public function update($path, $contents, Config $config)
70
    {
71 1
        $file = $this->getClient()->upload([
72 1
            'BucketId'   => $this->bucketId,
73 1
            'BucketName' => $this->bucketName,
74 1
            'FileName'   => $path,
75 1
            'Body'       => $contents,
76
        ]);
77
78 1
        return $this->getFileInfo($file);
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84 1
    public function updateStream($path, $resource, Config $config)
85
    {
86 1
        $file = $this->getClient()->upload([
87 1
            'BucketId'   => $this->bucketId,
88 1
            'BucketName' => $this->bucketName,
89 1
            'FileName'   => $path,
90 1
            'Body'       => $resource,
91
        ]);
92
93 1
        return $this->getFileInfo($file);
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99 1
    public function read($path)
100
    {
101 1
        $file = $this->getClient()->getFile([
102 1
            'BucketId'   => $this->bucketId,
103 1
            'BucketName' => $this->bucketName,
104 1
            'FileName'   => $path,
105
        ]);
106 1
        $fileContent = $this->getClient()->download([
107 1
            'FileId' => $file->getId(),
108
        ]);
109
110 1
        return ['contents' => $fileContent];
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116 1
    public function readStream($path)
117
    {
118 1
        $stream = Psr7\stream_for();
0 ignored issues
show
The function stream_for was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

118
        $stream = /** @scrutinizer ignore-call */ Psr7\stream_for();
Loading history...
119 1
        $download = $this->getClient()->download([
120 1
            'BucketId'   => $this->bucketId,
121 1
            'BucketName' => $this->bucketName,
122 1
            'FileName'   => $path,
123 1
            'SaveAs'     => $stream,
124
        ]);
125 1
        $stream->seek(0);
126
127
        try {
128 1
            $resource = Psr7\StreamWrapper::getResource($stream);
129
        } catch (InvalidArgumentException $e) {
0 ignored issues
show
The type Mhetreramesh\Flysystem\InvalidArgumentException was not found. Did you mean InvalidArgumentException? If so, make sure to prefix the type with \.
Loading history...
130
            return false;
131
        }
132
133 1
        return $download === true ? ['stream' => $resource] : false;
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 1
    public function rename($path, $newpath)
140
    {
141 1
        return false;
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147 1
    public function copy($path, $newPath)
148
    {
149 1
        return $this->getClient()->upload([
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getClient(...e_get_contents($path))) returns the type BackblazeB2\File which is incompatible with the return type mandated by League\Flysystem\AdapterInterface::copy() of boolean.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
150 1
            'BucketId'   => $this->bucketId,
151 1
            'BucketName' => $this->bucketName,
152 1
            'FileName'   => $newPath,
153 1
            'Body'       => @file_get_contents($path),
154
        ]);
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160
    public function delete($path)
161
    {
162
        return $this->getClient()->deleteFile(['FileName' => $path, 'BucketId' => $this->bucketId, 'BucketName' => $this->bucketName]);
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168
    public function deleteDir($path)
169
    {
170
        return $this->getClient()->deleteFile(['FileName' => $path, 'BucketId' => $this->bucketId, 'BucketName' => $this->bucketName]);
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176
    public function createDir($path, Config $config)
177
    {
178
        return $this->getClient()->upload([
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getClient(...> $path, 'Body' => '')) returns the type BackblazeB2\File which is incompatible with the return type mandated by League\Flysystem\AdapterInterface::createDir() of array|false.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
179
            'BucketId'   => $this->bucketId,
180
            'BucketName' => $this->bucketName,
181
            'FileName'   => $path,
182
            'Body'       => '',
183
        ]);
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189 1
    public function getMetadata($path)
190
    {
191 1
        return false;
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197 1
    public function getMimetype($path)
198
    {
199 1
        return false;
200
    }
201
202
    /**
203
     * {@inheritdoc}
204
     */
205
    public function getSize($path)
206
    {
207
        $file = $this->getClient()->getFile(['FileName' => $path, 'BucketId' => $this->bucketId, 'BucketName' => $this->bucketName]);
208
209
        return $this->getFileInfo($file);
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215
    public function getTimestamp($path)
216
    {
217
        $file = $this->getClient()->getFile(['FileName' => $path, 'BucketId' => $this->bucketId, 'BucketName' => $this->bucketName]);
218
219
        return $this->getFileInfo($file);
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     */
225 9
    public function getClient()
226
    {
227 9
        return $this->client;
228
    }
229
230
    /**
231
     * {@inheritdoc}
232
     */
233 1
    public function listContents($directory = '', $recursive = false)
234
    {
235 1
        $fileObjects = $this->getClient()->listFiles([
236 1
            'BucketId'   => $this->bucketId,
237 1
            'BucketName' => $this->bucketName,
238
        ]);
239 1
        if ($recursive === true && $directory === '') {
240 1
            $regex = '/^.*$/';
241 1
        } elseif ($recursive === true && $directory !== '') {
242 1
            $regex = '/^'.preg_quote($directory).'\/.*$/';
243 1
        } elseif ($recursive === false && $directory === '') {
244 1
            $regex = '/^(?!.*\\/).*$/';
245 1
        } elseif ($recursive === false && $directory !== '') {
246 1
            $regex = '/^'.preg_quote($directory).'\/(?!.*\\/).*$/';
247
        } else {
248 1
            throw new \InvalidArgumentException();
249
        }
250 1
        $fileObjects = array_filter($fileObjects, function ($fileObject) use ($regex) {
251 1
            return 1 === preg_match($regex, $fileObject->getName());
252 1
        });
253 1
        $normalized = array_map(function ($fileObject) {
254 1
            return $this->getFileInfo($fileObject);
255 1
        }, $fileObjects);
256
257 1
        return array_values($normalized);
258
    }
259
260
    /**
261
     * Get file info.
262
     *
263
     * @param $file
264
     *
265
     * @return array
266
     */
267 5
    protected function getFileInfo($file)
268
    {
269
        $normalized = [
270 5
            'type'      => 'file',
271 5
            'path'      => $file->getName(),
272 5
            'timestamp' => substr($file->getUploadTimestamp(), 0, -3),
273 5
            'size'      => $file->getSize(),
274
        ];
275
276 5
        return $normalized;
277
    }
278
}
279