1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace JellyBool\Flysystem\Upyun; |
4
|
|
|
|
5
|
|
|
use Upyun\Upyun; |
6
|
|
|
use League\Flysystem\Config; |
7
|
|
|
use League\Flysystem\Adapter\AbstractAdapter; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Class UpyunAdapter |
11
|
|
|
* @package JellyBool\Flysystem\Upyun |
12
|
|
|
*/ |
13
|
|
|
class UpyunAdapter extends AbstractAdapter |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* @var |
17
|
|
|
*/ |
18
|
|
|
protected $bucket; |
19
|
|
|
/** |
20
|
|
|
* @var |
21
|
|
|
*/ |
22
|
|
|
protected $operator; |
23
|
|
|
/** |
24
|
|
|
* @var |
25
|
|
|
*/ |
26
|
|
|
protected $password; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var |
30
|
|
|
*/ |
31
|
|
|
protected $domain; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @var |
35
|
|
|
*/ |
36
|
|
|
protected $protocol; |
37
|
|
|
/** |
38
|
|
|
* UpyunAdapter constructor. |
39
|
|
|
* @param $bucket |
40
|
|
|
* @param $operator |
41
|
|
|
* @param $password |
42
|
|
|
* @param mixed $domain |
43
|
|
|
* @param mixed $protocol |
44
|
|
|
*/ |
45
|
|
|
public function __construct($bucket, $operator, $password, $domain, $protocol = 'http') |
46
|
|
|
{ |
47
|
|
|
$this->bucket = $bucket; |
48
|
|
|
$this->operator = $operator; |
49
|
|
|
$this->password = $password; |
50
|
|
|
$this->domain = $domain; |
51
|
|
|
$this->protocol = $protocol; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @param string $path |
56
|
|
|
* @param string $contents |
57
|
|
|
* @param Config $config |
58
|
|
|
*/ |
59
|
|
|
public function write($path, $contents, Config $config) |
60
|
|
|
{ |
61
|
|
|
return $this->client()->write($path, $contents); |
|
|
|
|
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* @param string $path |
66
|
|
|
* @param resource $resource |
67
|
|
|
* @param Config $config |
68
|
|
|
*/ |
69
|
|
|
public function writeStream($path, $resource, Config $config) |
70
|
|
|
{ |
71
|
|
|
return $this->client()->write($path, $resource); |
|
|
|
|
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* @param string $path |
76
|
|
|
* @param string $contents |
77
|
|
|
* @param Config $config |
78
|
|
|
*/ |
79
|
|
|
public function update($path, $contents, Config $config) |
80
|
|
|
{ |
81
|
|
|
return $this->write($path, $contents, $config); |
|
|
|
|
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @param string $path |
86
|
|
|
* @param resource $resource |
87
|
|
|
* @param Config $config |
88
|
|
|
*/ |
89
|
|
|
public function updateStream($path, $resource, Config $config) |
90
|
|
|
{ |
91
|
|
|
return $this->writeStream($path, $resource, $config); |
|
|
|
|
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* @param string $path |
96
|
|
|
* @param string $newpath |
97
|
|
|
*/ |
98
|
|
|
public function rename($path, $newpath) |
99
|
|
|
{ |
100
|
|
|
$this->copy($path,$newpath); |
101
|
|
|
return $this->delete($path); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* @param string $path |
106
|
|
|
* @param string $newpath |
107
|
|
|
*/ |
108
|
|
|
public function copy($path, $newpath) |
109
|
|
|
{ |
110
|
|
|
$this->writeStream($newpath, fopen($this->getUrl($path), 'r'), new Config()); |
111
|
|
|
return true; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @param string $path |
116
|
|
|
*/ |
117
|
|
|
public function delete($path) |
118
|
|
|
{ |
119
|
|
|
return $this->client()->delete($path); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @param string $dirname |
124
|
|
|
*/ |
125
|
|
|
public function deleteDir($dirname) |
126
|
|
|
{ |
127
|
|
|
return $this->client()->deleteDir($dirname); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @param string $dirname |
132
|
|
|
* @param Config $config |
133
|
|
|
*/ |
134
|
|
|
public function createDir($dirname, Config $config) |
135
|
|
|
{ |
136
|
|
|
return $this->client()->createDir($dirname); |
|
|
|
|
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* @param string $path |
141
|
|
|
* @param string $visibility |
142
|
|
|
*/ |
143
|
|
|
public function setVisibility($path, $visibility) |
144
|
|
|
{ |
145
|
|
|
return true; |
|
|
|
|
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* @param string $path |
150
|
|
|
*/ |
151
|
|
|
public function has($path) |
152
|
|
|
{ |
153
|
|
|
return $this->client()->has($path); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* @param string $path |
158
|
|
|
*/ |
159
|
|
|
public function read($path) |
160
|
|
|
{ |
161
|
|
|
$contents = file_get_contents($this->getUrl($path)); |
162
|
|
|
return compact('contents', 'path'); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* @param string $path |
167
|
|
|
*/ |
168
|
|
|
public function readStream($path) |
169
|
|
|
{ |
170
|
|
|
$stream = fopen($this->getUrl($path), 'r'); |
171
|
|
|
return compact('stream', 'path'); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* @param string $directory |
176
|
|
|
* @param bool $recursive |
177
|
|
|
*/ |
178
|
|
|
public function listContents($directory = '', $recursive = false) |
179
|
|
|
{ |
180
|
|
|
$list = []; |
181
|
|
|
|
182
|
|
|
$result = $this->client()->read($directory, null, [ 'X-List-Limit' => 100, 'X-List-Iter' => null]); |
183
|
|
|
|
184
|
|
|
foreach ($result['files'] as $files) { |
185
|
|
|
$list[] = $this->normalizeFileInfo($files, $directory); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
return $list; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* @param string $path |
193
|
|
|
*/ |
194
|
|
|
public function getMetadata($path) |
195
|
|
|
{ |
196
|
|
|
return $this->client()->info($path); |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* @param string $path |
201
|
|
|
*/ |
202
|
|
|
public function getType($path) |
203
|
|
|
{ |
204
|
|
|
$response = $this->getMetadata($path); |
205
|
|
|
|
206
|
|
|
return ['type' => $response['x-upyun-file-type']]; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* @param string $path |
211
|
|
|
*/ |
212
|
|
|
public function getSize($path) |
213
|
|
|
{ |
214
|
|
|
$response = $this->getMetadata($path); |
215
|
|
|
|
216
|
|
|
return ['size' => $response['x-upyun-file-size']]; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* @param string $path |
221
|
|
|
*/ |
222
|
|
|
public function getMimetype($path) |
223
|
|
|
{ |
224
|
|
|
$headers = get_headers($this->getUrl($path), 1); |
225
|
|
|
$mimetype = $headers['Content-Type']; |
226
|
|
|
return compact('mimetype'); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* @param string $path |
231
|
|
|
*/ |
232
|
|
|
public function getTimestamp($path) |
233
|
|
|
{ |
234
|
|
|
$response = $this->getMetadata($path); |
235
|
|
|
|
236
|
|
|
return ['timestamp' => $response['x-upyun-file-date']]; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* @param string $path |
241
|
|
|
*/ |
242
|
|
|
public function getVisibility($path) |
243
|
|
|
{ |
244
|
|
|
return true; |
|
|
|
|
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* @param $path |
249
|
|
|
* @return string |
250
|
|
|
*/ |
251
|
|
|
public function getUrl($path) |
252
|
|
|
{ |
253
|
|
|
return $this->normalizeHost($this->domain).$path; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* @return Upyun |
258
|
|
|
*/ |
259
|
|
|
protected function client() |
260
|
|
|
{ |
261
|
|
|
$config = new \Upyun\Config($this->bucket, $this->operator, $this->password); |
262
|
|
|
$config->useSsl = config('filesystems.disks.upyun.protocol') === 'https' ? true : false; |
263
|
|
|
return new Upyun($config); |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* Normalize the file info. |
268
|
|
|
* |
269
|
|
|
* @param array $stats |
270
|
|
|
* @param string $directory |
271
|
|
|
* |
272
|
|
|
* @return array |
273
|
|
|
*/ |
274
|
|
|
protected function normalizeFileInfo(array $stats, string $directory) |
275
|
|
|
{ |
276
|
|
|
$filePath = ltrim($directory . '/' . $stats['name'], '/'); |
277
|
|
|
|
278
|
|
|
return [ |
279
|
|
|
'type' => $this->getType($filePath)['type'], |
280
|
|
|
'path' => $filePath, |
281
|
|
|
'timestamp' => $stats['time'], |
282
|
|
|
'size' => $stats['size'], |
283
|
|
|
]; |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* @param $domain |
288
|
|
|
* @return string |
289
|
|
|
*/ |
290
|
|
|
protected function normalizeHost($domain) |
291
|
|
|
{ |
292
|
|
|
if (0 !== stripos($domain, 'https://') && 0 !== stripos($domain, 'http://')) { |
293
|
|
|
$domain = $this->protocol."://{$domain}"; |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
return rtrim($domain, '/').'/'; |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.