Code

< 40 %
40-60 %
> 60 %
1
<?php
2
3
namespace League\Flysystem\Dropbox;
4
5
use Dropbox\Client;
6
use Dropbox\Exception;
7
use Dropbox\Exception_BadResponseCode;
8
use Dropbox\WriteMode;
9
use League\Flysystem\Adapter\AbstractAdapter;
10
use League\Flysystem\Adapter\Polyfill\NotSupportingVisibilityTrait;
11
use League\Flysystem\Config;
12
use League\Flysystem\Util;
13
14
class DropboxAdapter extends AbstractAdapter
15
{
16
    use NotSupportingVisibilityTrait;
17
18
    /**
19
     * @var array
20
     */
21
    protected static $resultMap = [
22
        'bytes' => 'size',
23
        'mime_type' => 'mimetype',
24
    ];
25
26
    /**
27
     * @var Client
28
     */
29
    protected $client;
30
31
    /**
32
     * Constructor.
33
     *
34
     * @param Client $client
35
     * @param string $prefix
36
     */
37 21
    public function __construct(Client $client, $prefix = null)
38
    {
39 21
        $this->client = $client;
40 21
        $this->setPathPrefix($prefix);
41 21
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46 9
    public function has($path)
47
    {
48 9
        return $this->getMetadata($path);
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54 3
    public function write($path, $contents, Config $config)
55
    {
56 3
        return $this->upload($path, $contents, WriteMode::add());
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 3
    public function writeStream($path, $resource, Config $config)
63
    {
64 3
        return $this->uploadStream($path, $resource, WriteMode::add());
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70 3
    public function update($path, $contents, Config $config)
71
    {
72 3
        return $this->upload($path, $contents, WriteMode::force());
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78 3
    public function updateStream($path, $resource, Config $config)
79
    {
80 3
        return $this->uploadStream($path, $resource, WriteMode::force());
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 3
    public function read($path)
87
    {
88 3
        if ( ! $object = $this->readStream($path)) {
89 3
            return false;
90
        }
91
92 3
        $object['contents'] = stream_get_contents($object['stream']);
93 3
        fclose($object['stream']);
94 3
        unset($object['stream']);
95
96 3
        return $object;
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102 6
    public function readStream($path)
103
    {
104 6
        $stream = fopen('php://temp', 'w+');
105 6
        $location = $this->applyPathPrefix($path);
106
107 6
        if ( ! $this->client->getFile($location, $stream)) {
108 6
            fclose($stream);
109
110 6
            return false;
111
        }
112
113 6
        rewind($stream);
114
115 6
        return compact('stream');
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121 6
    public function rename($path, $newpath)
122
    {
123 6
        $path = $this->applyPathPrefix($path);
124 6
        $newpath = $this->applyPathPrefix($newpath);
125
126
        try {
127 6
            $this->client->move($path, $newpath);
128 6
        } catch (Exception $e) {
129 3
            return false;
130
        }
131
132 3
        return true;
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     */
138 6
    public function copy($path, $newpath)
139
    {
140 6
        $path = $this->applyPathPrefix($path);
141 6
        $newpath = $this->applyPathPrefix($newpath);
142
143
        try {
144 6
            $this->client->copy($path, $newpath);
145 6
        } catch (Exception $e) {
146 3
            return false;
147
        }
148
149 3
        return true;
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155 3
    public function delete($path)
156
    {
157 3
        $location = $this->applyPathPrefix($path);
158 3
        $result = $this->client->delete($location);
159
160 3
        return isset($result['is_deleted']) ? $result['is_deleted'] : false;
161
    }
162
163
    /**
164
     * {@inheritdoc}
165
     */
166 3
    public function deleteDir($path)
167
    {
168 3
        return $this->delete($path);
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174 3
    public function createDir($path, Config $config)
175
    {
176 3
        $location = $this->applyPathPrefix($path);
177 3
        $result = $this->client->createFolder($location);
178
179 3
        if ($result === null) {
180 3
            return false;
181
        }
182
183 3
        return $this->normalizeResponse($result, $path);
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189 21
    public function getMetadata($path)
190
    {
191 21
        $location = $this->applyPathPrefix($path);
192
193
        try {
194 21
            $object = $this->client->getMetadata($location);
195 21
        } catch(Exception_BadResponseCode $e) {
196 6
            if ($e->getStatusCode() === 301) {
197 3
                return false;
198
            }
199
200 3
            throw $e;
201
        }
202
203 15
        if ( ! $object) {
204 15
            return false;
205
        }
206
207 15
        return $this->normalizeResponse($object, $path);
208
    }
209
210
    /**
211
     * {@inheritdoc}
212
     */
213 3
    public function getMimetype($path)
214
    {
215 3
        return $this->getMetadata($path);
216
    }
217
218
    /**
219
     * {@inheritdoc}
220
     */
221 3
    public function getSize($path)
222
    {
223 3
        return $this->getMetadata($path);
224
    }
225
226
    /**
227
     * {@inheritdoc}
228
     */
229 3
    public function getTimestamp($path)
230
    {
231 3
        return $this->getMetadata($path);
232
    }
233
234
    /**
235
     * {@inheritdoc}
236
     */
237 3
    public function getClient()
238
    {
239 3
        return $this->client;
240
    }
241
242
    /**
243
     * {@inheritdoc}
244
     */
245 3
    public function listContents($directory = '', $recursive = false)
246
    {
247 3
        $listing = [];
248 3
        $directory = trim($directory, '/.');
249 3
        $location = $this->applyPathPrefix($directory);
250
251 3
        if ( ! $result = $this->client->getMetadataWithChildren($location)) {
252 3
            return [];
253
        }
254
255 3
        foreach ($result['contents'] as $object) {
256 3
            $path = $this->removePathPrefix($object['path']);
257 3
            $listing[] = $this->normalizeResponse($object, $path);
258
259 3
            if ($recursive && $object['is_dir']) {
260 3
                $listing = array_merge($listing, $this->listContents($path, true));
261 3
            }
262 3
        }
263
264 3
        return $listing;
265
    }
266
267
    /**
268
     * Apply the path prefix.
269
     *
270
     * @param string $path
271
     *
272
     * @return string prefixed path
273
     */
274 60
    public function applyPathPrefix($path)
275
    {
276
277 60
        $path = parent::applyPathPrefix($path);
278
279 60
        return '/' . ltrim(rtrim($path, '/'), '/');
280
    }
281
282
    /**
283
     * Do the actual upload of a string file.
284
     *
285
     * @param string    $path
286
     * @param string    $contents
287
     * @param WriteMode $mode
288
     *
289
     * @return array|false file metadata
290
     */
291 6
    protected function upload($path, $contents, WriteMode $mode)
292
    {
293 6
        $location = $this->applyPathPrefix($path);
294
295 6
        if ( ! $result = $this->client->uploadFileFromString($location, $mode, $contents)) {
296 6
            return false;
297
        }
298
299 6
        return $this->normalizeResponse($result, $path);
300
    }
301
302
    /**
303
     * Do the actual upload of a file resource.
304
     *
305
     * @param string    $path
306
     * @param resource  $resource
307
     * @param WriteMode $mode
308
     *
309
     * @return array|false file metadata
310
     */
311 6
    protected function uploadStream($path, $resource, WriteMode $mode)
312
    {
313 6
        $location = $this->applyPathPrefix($path);
314
315
        // If size is zero, consider it unknown.
316 6
        $size = Util::getStreamSize($resource) ?: null;
317
318 6
        if ( ! $result = $this->client->uploadFile($location, $mode, $resource, $size)) {
319 6
            return false;
320
        }
321
322 6
        return $this->normalizeResponse($result, $path);
323
    }
324
325
    /**
326
     * Normalize a Dropbox response.
327
     *
328
     * @param array $response
329
     *
330
     * @return array
331
     */
332 33
    protected function normalizeResponse(array $response)
333
    {
334 33
        $result = ['path' => ltrim($this->removePathPrefix($response['path']), '/')];
335
336 33
        if (isset($response['modified'])) {
337 27
            $result['timestamp'] = strtotime($response['modified']);
338 27
        }
339
340 33
        $result = array_merge($result, Util::map($response, static::$resultMap));
341 33
        $result['type'] = $response['is_dir'] ? 'dir' : 'file';
342
343 33
        return $result;
344
    }
345
}
346