Completed
Push — master ( da04b5...288c9c )
by Frank
9s
created

WebDAVAdapter::encodePath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 8
rs 9.4285
cc 2
eloc 5
nc 2
nop 1
1
<?php
2
3
namespace League\Flysystem\WebDAV;
4
5
use League\Flysystem\Adapter\AbstractAdapter;
6
use League\Flysystem\Adapter\Polyfill\NotSupportingVisibilityTrait;
7
use League\Flysystem\Adapter\Polyfill\StreamedCopyTrait;
8
use League\Flysystem\Adapter\Polyfill\StreamedTrait;
9
use League\Flysystem\Config;
10
use League\Flysystem\Util;
11
use LogicException;
12
use Sabre\DAV\Client;
13
use Sabre\DAV\Exception;
14
use Sabre\DAV\Exception\NotFound;
15
16
class WebDAVAdapter extends AbstractAdapter
17
{
18
    use StreamedTrait;
19
    use StreamedCopyTrait;
20
    use NotSupportingVisibilityTrait;
21
22
    /**
23
     * @var array
24
     */
25
    protected static $resultMap = [
26
        '{DAV:}getcontentlength' => 'size',
27
        '{DAV:}getcontenttype' => 'mimetype',
28
        'content-length' => 'size',
29
        'content-type' => 'mimetype',
30
    ];
31
32
    /**
33
     * @var Client
34
     */
35
    protected $client;
36
37
    /**
38
     * Constructor.
39
     *
40
     * @param Client $client
41
     * @param string $prefix
42
     */
43
    public function __construct(Client $client, $prefix = null)
44
    {
45
        $this->client = $client;
46
        $this->setPathPrefix($prefix);
47
    }
48
49
    /**
50
     * url encode a path
51
     *
52
     * @param string $path
53
     *
54
     * @return string
55
     */
56
    protected function encodePath($path)
57
	{
58
		$a = explode('/', $path);
59
		for ($i=0; $i<count($a); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
60
			$a[$i] = rawurlencode($a[$i]);
61
		}
62
		return implode('/', $a);
63
	}
64
	
65
    /**
66
     * {@inheritdoc}
67
     */
68
    public function getMetadata($path)
69
    {
70
        $location = $this->applyPathPrefix($this->encodePath($path));
71
72
        try {
73
            $result = $this->client->propFind($location, [
74
                '{DAV:}displayname',
75
                '{DAV:}getcontentlength',
76
                '{DAV:}getcontenttype',
77
                '{DAV:}getlastmodified',
78
            ]);
79
80
            return $this->normalizeObject($result, $path);
81
        } catch (Exception $e) {
82
            return false;
83
        }
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89
    public function has($path)
90
    {
91
        return $this->getMetadata($path);
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function read($path)
98
    {
99
        $location = $this->applyPathPrefix($this->encodePath($path));
100
101
        try {
102
            $response = $this->client->request('GET', $location);
103
104
            if ($response['statusCode'] !== 200) {
105
                return false;
106
            }
107
108
            return array_merge([
109
                'contents' => $response['body'],
110
                'timestamp' => strtotime(is_array($response['headers']['last-modified'])
111
                    ? current($response['headers']['last-modified'])
112
                    : $response['headers']['last-modified']),
113
                'path' => $path,
114
            ], Util::map($response['headers'], static::$resultMap));
115
        } catch (Exception $e) {
116
            return false;
117
        }
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123
    public function write($path, $contents, Config $config)
124
    {
125
        $location = $this->applyPathPrefix($this->encodePath($path));
126
        $response = $this->client->request('PUT', $location, $contents);
127
128
        if ($response['statusCode'] >= 400) {
129
            return false;
130
        }
131
132
        $result = compact('path', 'contents');
133
134
        if ($config->get('visibility')) {
135
            throw new LogicException(__CLASS__.' does not support visibility settings.');
136
        }
137
138
        return $result;
139
    }
140
141
    /**
142
     * {@inheritdoc}
143
     */
144
    public function update($path, $contents, Config $config)
145
    {
146
        return $this->write($path, $contents, $config);
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152
    public function rename($path, $newpath)
153
    {
154
        $location = $this->applyPathPrefix($this->encodePath($path));
155
        $newLocation = $this->applyPathPrefix($this->encodePath($newpath));
156
157
        try {
158
            $response = $this->client->request('MOVE', '/'.ltrim($location, '/'), null, [
159
                'Destination' => '/'.ltrim($newLocation, '/'),
160
            ]);
161
162
            if ($response['statusCode'] >= 200 && $response['statusCode'] < 300) {
163
                return true;
164
            }
165
        } catch (NotFound $e) {
166
            // Would have returned false here, but would be redundant
167
        }
168
169
        return false;
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175
    public function delete($path)
176
    {
177
        $location = $this->applyPathPrefix($this->encodePath($path));
178
179
        try {
180
            $this->client->request('DELETE', $location);
181
182
            return true;
183
        } catch (NotFound $e) {
184
            return false;
185
        }
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     */
191
    public function createDir($path, Config $config)
192
    {
193
        $location = $this->applyPathPrefix($this->encodePath($path));
194
        $response = $this->client->request('MKCOL', $location);
195
196
        if ($response['statusCode'] !== 201) {
197
            return false;
198
        }
199
200
        return compact('path') + ['type' => 'dir'];
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     */
206
    public function deleteDir($dirname)
207
    {
208
        return $this->delete($dirname);
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     */
214
    public function listContents($directory = '', $recursive = false)
215
    {
216
        $location = $this->applyPathPrefix($this->encodePath($directory));
217
        $response = $this->client->propFind($location . '/', [
218
            '{DAV:}displayname',
219
            '{DAV:}getcontentlength',
220
            '{DAV:}getcontenttype',
221
            '{DAV:}getlastmodified',
222
        ], 1);
223
224
        array_shift($response);
225
        $result = [];
226
227
        foreach ($response as $path => $object) {
228
            $path = urldecode($this->removePathPrefix($path));
229
            $object = $this->normalizeObject($object, $path);
230
            $result[] = $object;
231
232
            if ($recursive && $object['type'] === 'dir') {
233
                $result = array_merge($result, $this->listContents($object['path'], true));
234
            }
235
        }
236
237
        return $result;
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243
    public function getSize($path)
244
    {
245
        return $this->getMetadata($path);
246
    }
247
248
    /**
249
     * {@inheritdoc}
250
     */
251
    public function getTimestamp($path)
252
    {
253
        return $this->getMetadata($path);
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     */
259
    public function getMimetype($path)
260
    {
261
        return $this->getMetadata($path);
262
    }
263
264
    /**
265
     * Normalise a WebDAV repsonse object.
266
     *
267
     * @param array  $object
268
     * @param string $path
269
     *
270
     * @return array
271
     */
272
    protected function normalizeObject(array $object, $path)
273
    {
274
        if (! isset($object['{DAV:}getcontentlength'])) {
275
            return ['type' => 'dir', 'path' => trim($path, '/')];
276
        }
277
278
        $result = Util::map($object, static::$resultMap);
279
280
        if (isset($object['{DAV:}getlastmodified'])) {
281
            $result['timestamp'] = strtotime($object['{DAV:}getlastmodified']);
282
        }
283
284
        $result['type'] = 'file';
285
        $result['path'] = trim($path, '/');
286
287
        return $result;
288
    }
289
}
290