1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* balloon |
7
|
|
|
* |
8
|
|
|
* @copyright Copryright (c) 2012-2019 gyselroth GmbH (https://gyselroth.com) |
9
|
|
|
* @license GPL-3.0 https://opensource.org/licenses/GPL-3.0 |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Balloon\Filesystem\Node; |
13
|
|
|
|
14
|
|
|
use Balloon\AttributeDecorator\AttributeDecoratorInterface; |
15
|
|
|
use Balloon\Filesystem; |
16
|
|
|
use Balloon\Filesystem\Acl; |
17
|
|
|
use Balloon\Server; |
18
|
|
|
use Balloon\Server\AttributeDecorator as RoleAttributeDecorator; |
19
|
|
|
use Closure; |
20
|
|
|
|
21
|
|
|
class AttributeDecorator implements AttributeDecoratorInterface |
22
|
|
|
{ |
23
|
|
|
/** |
24
|
|
|
* Server. |
25
|
|
|
* |
26
|
|
|
* @var Server |
27
|
|
|
*/ |
28
|
|
|
protected $server; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Filesystem. |
32
|
|
|
* |
33
|
|
|
* @var Filesystem |
34
|
|
|
*/ |
35
|
|
|
protected $fs; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Acl. |
39
|
|
|
* |
40
|
|
|
* @var Acl |
41
|
|
|
*/ |
42
|
|
|
protected $acl; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Role decorator. |
46
|
|
|
* |
47
|
|
|
* @var RoleAttributeDecorator |
48
|
|
|
*/ |
49
|
|
|
protected $role_decorator; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Custom attributes. |
53
|
|
|
* |
54
|
|
|
* @var array |
55
|
|
|
*/ |
56
|
|
|
protected $custom = []; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Init. |
60
|
|
|
*/ |
61
|
6 |
|
public function __construct(Server $server, Acl $acl, RoleAttributeDecorator $role_decorator) |
62
|
|
|
{ |
63
|
6 |
|
$this->server = $server; |
64
|
6 |
|
$this->acl = $acl; |
65
|
6 |
|
$this->role_decorator = $role_decorator; |
66
|
6 |
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Decorate attributes. |
70
|
|
|
*/ |
71
|
6 |
|
public function decorate(NodeInterface $node, array $attributes = []): array |
72
|
|
|
{ |
73
|
6 |
|
$requested = $attributes; |
74
|
6 |
|
$attributes = $node->getAttributes(); |
75
|
|
|
|
76
|
6 |
|
$attrs = array_merge( |
77
|
6 |
|
$this->getAttributes($node, $attributes), |
78
|
6 |
|
$this->getTimeAttributes($node, $attributes), |
79
|
6 |
|
$this->getTypeAttributes($node, $attributes), |
80
|
6 |
|
$this->custom |
81
|
|
|
); |
82
|
|
|
|
83
|
6 |
|
if (0 === count($requested)) { |
84
|
2 |
|
return $this->translateAttributes($node, $attrs); |
85
|
|
|
} |
86
|
|
|
|
87
|
4 |
|
return $this->translateAttributes($node, array_intersect_key($attrs, array_flip($requested))); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Add decorator. |
92
|
|
|
*/ |
93
|
2 |
|
public function addDecorator(string $attribute, Closure $decorator): self |
94
|
|
|
{ |
95
|
2 |
|
$this->custom[$attribute] = $decorator; |
96
|
|
|
|
97
|
2 |
|
return $this; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Get Attributes. |
102
|
|
|
*/ |
103
|
6 |
|
protected function getAttributes(NodeInterface $node, array $attributes): array |
104
|
|
|
{ |
105
|
6 |
|
$acl = $this->acl; |
106
|
6 |
|
$server = $this->server; |
107
|
6 |
|
$fs = $this->server->getFilesystem(); |
108
|
6 |
|
$decorator = $this->role_decorator; |
109
|
|
|
|
110
|
|
|
return [ |
111
|
6 |
|
'id' => (string) $attributes['_id'], |
112
|
6 |
|
'name' => (string) $attributes['name'], |
113
|
6 |
|
'mime' => (string) $attributes['mime'], |
114
|
6 |
|
'readonly' => (bool) $attributes['readonly'], |
115
|
6 |
|
'directory' => $node instanceof Collection, |
116
|
6 |
|
'meta' => function ($node) { |
117
|
2 |
|
return (object) $node->getMetaAttributes(); |
118
|
6 |
|
}, |
119
|
6 |
|
'size' => function ($node) { |
120
|
2 |
|
return $node->getSize(); |
121
|
6 |
|
}, |
122
|
6 |
|
'path' => function ($node) { |
123
|
|
|
try { |
124
|
2 |
|
return $node->getPath(); |
125
|
|
|
} catch (\Exception $e) { |
126
|
|
|
return null; |
127
|
|
|
} |
128
|
6 |
|
}, |
129
|
6 |
|
'parent' => function ($node) { |
130
|
2 |
|
$parent = $node->getParent(); |
131
|
|
|
|
132
|
2 |
|
if (null === $parent || $parent->isRoot()) { |
133
|
2 |
|
return null; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
return $this->decorate($node->getParent(), ['id', 'name', '_links']); |
137
|
6 |
|
}, |
138
|
6 |
|
'access' => function ($node) use ($acl) { |
139
|
2 |
|
return $acl->getAclPrivilege($node); |
140
|
6 |
|
}, |
141
|
6 |
|
'acl' => function ($node) use ($attributes) { |
142
|
2 |
|
if ($node->isShareMember() && count($attributes['acl']) > 0) { |
143
|
|
|
return $node->getAcl(); |
144
|
|
|
} |
145
|
|
|
|
146
|
2 |
|
return null; |
147
|
6 |
|
}, |
148
|
6 |
|
'lock' => function ($node) use ($server, $decorator, $attributes) { |
149
|
2 |
|
if (!$node->isLocked()) { |
150
|
2 |
|
return null; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
$lock = $attributes['lock']; |
154
|
|
|
|
155
|
|
|
try { |
156
|
|
|
$user = $decorator->decorate( |
157
|
|
|
$server->getUserById($lock['owner']), |
158
|
|
|
['id', 'name', '_links'] |
159
|
|
|
); |
160
|
|
|
} catch (\Exception $e) { |
161
|
|
|
$user = null; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
$lock = $attributes['lock']; |
165
|
|
|
|
166
|
|
|
return [ |
167
|
|
|
'owner' => $user, |
168
|
|
|
'created' => $lock['created']->toDateTime()->format('c'), |
169
|
|
|
'expire' => $lock['expire']->toDateTime()->format('c'), |
170
|
|
|
'id' => $lock['id'], |
171
|
|
|
]; |
172
|
6 |
|
}, |
173
|
6 |
|
'share' => function ($node) use ($fs) { |
174
|
2 |
|
if ($node->isShared() || !$node->isSpecial()) { |
175
|
2 |
|
return null; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
try { |
179
|
|
|
return $this->decorate($fs->findNodeById($node->getShareId(true)), ['id', 'name', '_links']); |
180
|
|
|
} catch (\Exception $e) { |
181
|
|
|
return null; |
182
|
|
|
} |
183
|
6 |
|
}, |
184
|
6 |
|
'sharename' => function ($node) { |
185
|
2 |
|
if (!$node->isShared()) { |
186
|
2 |
|
return null; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
try { |
190
|
|
|
return $node->getShareName(); |
191
|
|
|
} catch (\Exception $e) { |
192
|
|
|
return null; |
193
|
|
|
} |
194
|
6 |
|
}, |
195
|
6 |
|
'shareowner' => function ($node) use ($server, $fs, $decorator) { |
196
|
2 |
|
if (!$node->isSpecial()) { |
197
|
2 |
|
return null; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
try { |
201
|
|
|
return $decorator->decorate( |
202
|
|
|
$server->getUserById($fs->findRawNode($node->getShareId())['owner']), |
203
|
|
|
['id', 'name', '_links'] |
204
|
|
|
); |
205
|
|
|
} catch (\Exception $e) { |
206
|
|
|
return null; |
207
|
|
|
} |
208
|
6 |
|
}, |
209
|
6 |
|
'owner' => function ($node) use ($server, $decorator) { |
210
|
|
|
try { |
211
|
2 |
|
return $decorator->decorate( |
212
|
2 |
|
$server->getUserById($node->getOwner()), |
213
|
|
|
['id', 'name', '_links'] |
214
|
|
|
); |
215
|
2 |
|
} catch (\Exception $e) { |
216
|
2 |
|
return null; |
217
|
|
|
} |
218
|
6 |
|
}, |
219
|
|
|
]; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* Get Attributes. |
224
|
|
|
* |
225
|
|
|
* @param NodeInterface |
226
|
|
|
*/ |
227
|
|
|
protected function getTimeAttributes(NodeInterface $node, array $attributes): array |
|
|
|
|
228
|
|
|
{ |
229
|
|
|
return [ |
230
|
6 |
|
'created' => function ($node) use ($attributes) { |
|
|
|
|
231
|
2 |
|
return $attributes['created']->toDateTime()->format('c'); |
232
|
6 |
|
}, |
233
|
6 |
|
'changed' => function ($node) use ($attributes) { |
|
|
|
|
234
|
2 |
|
return $attributes['changed']->toDateTime()->format('c'); |
235
|
6 |
|
}, |
236
|
6 |
|
'deleted' => function ($node) use ($attributes) { |
|
|
|
|
237
|
2 |
|
if (false === $attributes['deleted']) { |
238
|
|
|
return null; |
239
|
|
|
} |
240
|
|
|
|
241
|
2 |
|
return $attributes['deleted']->toDateTime()->format('c'); |
242
|
6 |
|
}, |
243
|
6 |
|
'destroy' => function ($node) use ($attributes) { |
|
|
|
|
244
|
2 |
|
if (null === $attributes['destroy']) { |
245
|
|
|
return null; |
246
|
|
|
} |
247
|
|
|
|
248
|
2 |
|
return $attributes['destroy']->toDateTime()->format('c'); |
249
|
6 |
|
}, |
250
|
|
|
]; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Get Attributes. |
255
|
|
|
*/ |
256
|
6 |
|
protected function getTypeAttributes(NodeInterface $node, array $attributes): array |
257
|
|
|
{ |
258
|
6 |
|
$server = $this->server; |
|
|
|
|
259
|
6 |
|
$fs = $this->server->getFilesystem(); |
260
|
|
|
|
261
|
6 |
|
if ($node instanceof File) { |
262
|
|
|
return [ |
263
|
4 |
|
'version' => $attributes['version'], |
264
|
4 |
|
'hash' => $attributes['hash'], |
265
|
|
|
]; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
return [ |
269
|
3 |
|
'shared' => $node->isShared(), |
270
|
3 |
|
'reference' => $node->isReference(), |
271
|
3 |
|
'filter' => function ($node) use ($attributes) { |
|
|
|
|
272
|
1 |
|
if (null === $attributes['filter']) { |
273
|
|
|
return null; |
274
|
|
|
} |
275
|
|
|
|
276
|
1 |
|
return json_decode($attributes['filter'], true, 512, JSON_THROW_ON_ERROR); |
277
|
3 |
|
}, |
278
|
3 |
|
'mount' => function ($node) use ($fs, $attributes) { |
279
|
|
|
$mount = $node->getAttributes()['mount']; |
280
|
|
|
|
281
|
|
|
if (!$node->isMounted() && !$node->isReference()) { |
282
|
|
|
return null; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
if ($node->isReference()) { |
286
|
|
|
$attributes = $fs->findRawNode($node->getShareId()); |
|
|
|
|
287
|
|
|
if (isset($attributes['mount']) && count($attributes['mount']) > 0) { |
288
|
|
|
$mount = $attributes['mount']; |
289
|
|
|
unset($mount['username'], $mount['password']); |
290
|
|
|
|
291
|
|
|
return $mount; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
return null; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
if (!empty($mount['password'])) { |
298
|
|
|
unset($mount['password']); |
299
|
|
|
$mount['has_password'] = true; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
return $mount; |
303
|
3 |
|
}, |
304
|
|
|
]; |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
/** |
308
|
|
|
* Execute closures. |
309
|
|
|
*/ |
310
|
6 |
View Code Duplication |
protected function translateAttributes(NodeInterface $node, array $attributes): array |
|
|
|
|
311
|
|
|
{ |
312
|
6 |
|
foreach ($attributes as $key => &$value) { |
313
|
6 |
|
if ($value instanceof Closure) { |
314
|
4 |
|
$result = $value->call($this, $node); |
315
|
|
|
|
316
|
4 |
|
if (null === $result) { |
317
|
3 |
|
unset($attributes[$key]); |
318
|
|
|
} else { |
319
|
4 |
|
$value = $result; |
320
|
|
|
} |
321
|
4 |
|
} elseif ($value === null) { |
322
|
6 |
|
unset($attributes[$key]); |
323
|
|
|
} |
324
|
|
|
} |
325
|
|
|
|
326
|
5 |
|
return $attributes; |
327
|
|
|
} |
328
|
|
|
} |
329
|
|
|
|
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.