These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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\App\Api\v1; |
||
13 | |||
14 | use Balloon\App\Api\Controller; |
||
15 | use Balloon\App\Api\v1\AttributeDecorator\DeltaDecorator; |
||
16 | use Balloon\App\Api\v1\AttributeDecorator\EventDecorator; |
||
17 | use Balloon\App\Api\v1\AttributeDecorator\NodeDecorator; |
||
18 | use Balloon\App\Api\v1\Collection as ApiCollection; |
||
19 | use Balloon\App\Api\v1\File as ApiFile; |
||
20 | use Balloon\Filesystem; |
||
21 | use Balloon\Filesystem\Exception; |
||
22 | use Balloon\Filesystem\Node\Collection; |
||
0 ignored issues
–
show
|
|||
23 | use Balloon\Filesystem\Node\File; |
||
0 ignored issues
–
show
This use statement conflicts with another class in this namespace,
Balloon\App\Api\v1\File .
Let’s assume that you have a directory layout like this: .
|-- OtherDir
| |-- Bar.php
| `-- Foo.php
`-- SomeDir
`-- Foo.php
and let’s assume the following content of // Bar.php
namespace OtherDir;
use SomeDir\Foo; // This now conflicts the class OtherDir\Foo
If both files PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as // Bar.php
namespace OtherDir;
use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
|
|||
24 | use Balloon\Filesystem\Node\NodeInterface; |
||
25 | use Balloon\Helper; |
||
26 | use Balloon\Server; |
||
27 | use Balloon\Server\User; |
||
0 ignored issues
–
show
This use statement conflicts with another class in this namespace,
Balloon\App\Api\v1\User .
Let’s assume that you have a directory layout like this: .
|-- OtherDir
| |-- Bar.php
| `-- Foo.php
`-- SomeDir
`-- Foo.php
and let’s assume the following content of // Bar.php
namespace OtherDir;
use SomeDir\Foo; // This now conflicts the class OtherDir\Foo
If both files PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as // Bar.php
namespace OtherDir;
use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
|
|||
28 | use Closure; |
||
29 | use Generator; |
||
30 | use Micro\Http\Response; |
||
31 | use MongoDB\BSON\UTCDateTime; |
||
32 | use MongoDB\Database; |
||
33 | use Psr\Log\LoggerInterface; |
||
34 | use ZipStream\ZipStream; |
||
35 | |||
36 | class Node extends Controller |
||
37 | { |
||
38 | /** |
||
39 | * Filesystem. |
||
40 | * |
||
41 | * @var Filesystem |
||
42 | */ |
||
43 | protected $fs; |
||
44 | |||
45 | /** |
||
46 | * LoggerInterface. |
||
47 | * |
||
48 | * @var LoggerInterface |
||
49 | */ |
||
50 | protected $logger; |
||
51 | |||
52 | /** |
||
53 | * Server. |
||
54 | * |
||
55 | * @var Server |
||
56 | */ |
||
57 | protected $server; |
||
58 | |||
59 | /** |
||
60 | * User. |
||
61 | * |
||
62 | * @var User |
||
63 | */ |
||
64 | protected $user; |
||
65 | |||
66 | /** |
||
67 | * Decorator. |
||
68 | * |
||
69 | * @var NodeDecorator |
||
70 | */ |
||
71 | protected $node_decorator; |
||
72 | |||
73 | /** |
||
74 | * Database. |
||
75 | * |
||
76 | * @var Database |
||
77 | */ |
||
78 | protected $db; |
||
79 | |||
80 | /** |
||
81 | * Initialize. |
||
82 | */ |
||
83 | public function __construct(Server $server, NodeDecorator $decorator, LoggerInterface $logger, Database $db) |
||
84 | { |
||
85 | $this->fs = $server->getFilesystem(); |
||
86 | $this->user = $server->getIdentity(); |
||
87 | $this->server = $server; |
||
88 | $this->node_decorator = $decorator; |
||
89 | $this->logger = $logger; |
||
90 | $this->db = $db; |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * @api {head} /api/v1/node?id=:id Node exists? |
||
95 | * @apiVersion 1.0.0 |
||
96 | * @apiName head |
||
97 | * @apiGroup Node |
||
98 | * @apiPermission none |
||
99 | * @apiDescription Check if a node exists. Per default deleted nodes are ignore which means it will |
||
100 | * return a 404 if a deleted node is requested. You can change this behaviour via the deleted parameter. |
||
101 | * @apiUse _getNode |
||
102 | * |
||
103 | * @apiExample (cURL) example: |
||
104 | * curl -XHEAD "https://SERVER/api/v1/node?id=544627ed3c58891f058b4686" |
||
105 | * curl -XHEAD "https://SERVER/api/v1/node/544627ed3c58891f058b4686" |
||
106 | * curl -XHEAD "https://SERVER/api/v1/node?p=/absolute/path/to/my/node" |
||
107 | * |
||
108 | * @apiParam (GET Parameter) {number} [deleted=0] Wherever include deleted node or not, possible values:</br> |
||
109 | * - 0 Exclude deleted</br> |
||
110 | * - 1 Only deleted</br> |
||
111 | * - 2 Include deleted</br> |
||
112 | * |
||
113 | * @apiSuccessExample {json} Success-Response (Node does exist): |
||
114 | * HTTP/1.1 200 OK |
||
115 | * |
||
116 | * @apiSuccessExample {json} Success-Response (Node does not exist): |
||
117 | * HTTP/1.1 404 Not Found |
||
118 | * |
||
119 | * @param string $id |
||
120 | * @param string $p |
||
121 | */ |
||
122 | public function head(?string $id = null, ?string $p = null, int $deleted = 0): Response |
||
123 | { |
||
124 | try { |
||
125 | $result = $this->_getNode($id, $p, null, false, false, $deleted); |
||
126 | |||
127 | $response = (new Response()) |
||
128 | ->setHeader('Content-Length', (string) $result->getSize()) |
||
129 | ->setHeader('Content-Type', $result->getContentType()) |
||
130 | ->setCode(200); |
||
131 | |||
132 | return $response; |
||
133 | } catch (\Exception $e) { |
||
134 | return (new Response())->setCode(404); |
||
135 | } |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * @api {post} /api/v1/node/undelete?id=:id Undelete node |
||
140 | * @apiVersion 1.0.0 |
||
141 | * @apiName postUndelete |
||
142 | * @apiGroup Node |
||
143 | * @apiPermission none |
||
144 | * @apiDescription Undelete (Apiore from trash) a single node or multiple ones. |
||
145 | * @apiUse _getNodes |
||
146 | * @apiUse _conflictNode |
||
147 | * @apiUse _multiError |
||
148 | * @apiUse _writeAction |
||
149 | * |
||
150 | * @apiExample (cURL) example: |
||
151 | * curl -XPOST "https://SERVER/api/v1/node/undelete?id[]=544627ed3c58891f058b4686&id[]=544627ed3c58891f058b46865&pretty" |
||
152 | * curl -XPOST "https://SERVER/api/v1/node/undelete?id=544627ed3c58891f058b4686?pretty" |
||
153 | * curl -XPOST "https://SERVER/api/v1/node/544627ed3c58891f058b4686/undelete?conflict=2" |
||
154 | * curl -XPOST "https://SERVER/api/v1/node/undelete?p=/absolute/path/to/my/node&conflict=0&move=1&destid=544627ed3c58891f058b46889" |
||
155 | * |
||
156 | * @apiParam (GET Parameter) {string} [destid] Either destid or destp (path) of the new parent collection node must be given. |
||
157 | * @apiParam (GET Parameter) {string} [destp] Either destid or destp (path) of the new parent collection node must be given. |
||
158 | * |
||
159 | * @apiSuccessExample {json} Success-Response: |
||
160 | * HTTP/1.1 204 No Content |
||
161 | * |
||
162 | * @apiSuccessExample {json} Success-Response (conflict=1): |
||
163 | * HTTP/1.1 200 OK |
||
164 | * { |
||
165 | * "status":200, |
||
166 | * "data": "renamed (xy23)" |
||
167 | * } |
||
168 | * } |
||
169 | * |
||
170 | * @param array|string $id |
||
171 | * @param array|string $p |
||
172 | * @param string $destid |
||
173 | * @param string $destp |
||
174 | */ |
||
175 | public function postUndelete( |
||
176 | $id = null, |
||
177 | $p = null, |
||
178 | bool $move = false, |
||
179 | ?string $destid = null, |
||
180 | ?string $destp = null, |
||
181 | int $conflict = 0 |
||
182 | ): Response { |
||
183 | $parent = null; |
||
184 | if (true === $move) { |
||
185 | try { |
||
186 | $parent = $this->_getNode($destid, $destp, 'Collection', false, true); |
||
187 | } catch (Exception\NotFound $e) { |
||
188 | throw new Exception\NotFound( |
||
189 | 'destination collection was not found or is not a collection', |
||
190 | Exception\NotFound::DESTINATION_NOT_FOUND |
||
191 | ); |
||
192 | } |
||
193 | } |
||
194 | |||
195 | return $this->bulk($id, $p, function ($node) use ($parent, $conflict, $move) { |
||
0 ignored issues
–
show
It seems like
$id defined by parameter $id on line 176 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
It seems like
$p defined by parameter $p on line 177 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
196 | if (true === $move) { |
||
197 | $node = $node->setParent($parent, $conflict); |
||
198 | } |
||
199 | |||
200 | if ($node->isDeleted()) { |
||
201 | $node->undelete($conflict); |
||
202 | } |
||
203 | |||
204 | if (true === $move && NodeInterface::CONFLICT_RENAME === $conflict) { |
||
205 | return [ |
||
206 | 'status' => 200, |
||
207 | 'data' => [ |
||
208 | ], |
||
209 | ]; |
||
210 | } |
||
211 | |||
212 | return ['status' => 204]; |
||
213 | }); |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * @api {get} /api/v1/node?id=:id Download stream |
||
218 | * @apiVersion 1.0.0 |
||
219 | * @apiName get |
||
220 | * @apiGroup Node |
||
221 | * @apiPermission none |
||
222 | * @apiDescription Download node contents. Collections (Folder) are converted into |
||
223 | * a zip file in realtime. |
||
224 | * @apiUse _getNode |
||
225 | * |
||
226 | * @apiParam (GET Parameter) {number} [offset=0] Get content from a specific offset in bytes |
||
227 | * @apiParam (GET Parameter) {number} [length=0] Get content with until length in bytes reached |
||
228 | * @apiParam (GET Parameter) {string} [encode] Can be set to base64 to encode content as base64. |
||
229 | * @apiParam (GET Parameter) {boolean} [download=false] Force download file (Content-Disposition: attachment HTTP header) |
||
230 | * |
||
231 | * @apiExample (cURL) example: |
||
232 | * curl -XGET "https://SERVER/api/v1/node?id=544627ed3c58891f058b4686" > myfile.txt |
||
233 | * curl -XGET "https://SERVER/api/v1/node/544627ed3c58891f058b4686" > myfile.txt |
||
234 | * curl -XGET "https://SERVER/api/v1/node?p=/absolute/path/to/my/collection" > folder.zip |
||
235 | * |
||
236 | * @apiSuccessExample {string} Success-Response (encode=base64): |
||
237 | * HTTP/1.1 200 OK |
||
238 | * |
||
239 | * @apiSuccessExample {binary} Success-Response: |
||
240 | * HTTP/1.1 200 OK |
||
241 | * |
||
242 | * @apiErrorExample {json} Error-Response (Invalid offset): |
||
243 | * HTTP/1.1 400 Bad Request |
||
244 | * { |
||
245 | * "status": 400, |
||
246 | * "data": { |
||
247 | * "error": "Balloon\\Exception\\Conflict", |
||
248 | * "message": "invalid offset requested", |
||
249 | * "code": 277 |
||
250 | * } |
||
251 | * } |
||
252 | * |
||
253 | * @param array|string $id |
||
254 | * @param array|string $p |
||
255 | * @param string $encode |
||
256 | */ |
||
257 | public function get( |
||
258 | $id = null, |
||
259 | $p = null, |
||
260 | int $offset = 0, |
||
261 | int $length = 0, |
||
262 | ?string $encode = null, |
||
263 | bool $download = false, |
||
264 | string $name = 'selected' |
||
265 | ): ?Response { |
||
266 | if (is_array($id) || is_array($p)) { |
||
267 | return $this->combine($id, $p, $name); |
||
0 ignored issues
–
show
It seems like
$id defined by parameter $id on line 258 can also be of type array ; however, Balloon\App\Api\v1\Node::combine() does only seem to accept string|null , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
It seems like
$p defined by parameter $p on line 259 can also be of type array ; however, Balloon\App\Api\v1\Node::combine() does only seem to accept string|null , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
268 | } |
||
269 | |||
270 | $node = $this->_getNode($id, $p); |
||
271 | if ($node instanceof Collection) { |
||
272 | return (new Response())->setBody(function () use ($node) { |
||
273 | $node->getZip(); |
||
274 | }); |
||
275 | } |
||
276 | |||
277 | $response = new Response(); |
||
278 | |||
279 | if (true === $download) { |
||
280 | $response->setHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\''.rawurlencode($name)); |
||
281 | $response->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'); |
||
282 | $response->setHeader('Content-Type', 'application/octet-stream'); |
||
283 | $response->setHeader('Content-Length', (string) $node->getSize()); |
||
284 | $response->setHeader('Content-Transfer-Encoding', 'binary'); |
||
285 | } else { |
||
286 | $response->setHeader('Content-Disposition', 'inline; filename*=UTF-8\'\''.rawurlencode($name)); |
||
287 | } |
||
288 | |||
289 | return $response->setOutputFormat(null) |
||
290 | ->setBody(function () use ($node, $encode, $offset, $length) { |
||
291 | $mime = $node->getContentType(); |
||
292 | $stream = $node->get(); |
||
293 | $name = $node->getName(); |
||
0 ignored issues
–
show
$name is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
294 | |||
295 | if (null === $stream) { |
||
296 | return; |
||
297 | } |
||
298 | |||
299 | if (0 !== $offset) { |
||
300 | if (fseek($stream, $offset) === -1) { |
||
301 | throw new Exception\Conflict( |
||
302 | 'invalid offset requested', |
||
303 | Exception\Conflict::INVALID_OFFSET |
||
304 | ); |
||
305 | } |
||
306 | } |
||
307 | |||
308 | $read = 0; |
||
309 | header('Content-Type: '.$mime.''); |
||
310 | if ('base64' === $encode) { |
||
311 | header('Content-Encoding: base64'); |
||
312 | while (!feof($stream)) { |
||
313 | if (0 !== $length && $read + 8192 > $length) { |
||
314 | echo base64_encode(fread($stream, $length - $read)); |
||
315 | exit(); |
||
316 | } |
||
317 | |||
318 | echo base64_encode(fread($stream, 8192)); |
||
319 | $read += 8192; |
||
320 | } |
||
321 | } else { |
||
322 | while (!feof($stream)) { |
||
323 | if (0 !== $length && $read + 8192 > $length) { |
||
324 | echo fread($stream, $length - $read); |
||
325 | exit(); |
||
326 | } |
||
327 | |||
328 | echo fread($stream, 8192); |
||
329 | $read += 8192; |
||
330 | } |
||
331 | } |
||
332 | }); |
||
333 | } |
||
334 | |||
335 | /** |
||
336 | * @api {post} /api/v1/node/readonly?id=:id Mark node as readonly |
||
337 | * @apiVersion 1.0.0 |
||
338 | * @apiName postReadonly |
||
339 | * @apiGroup Node |
||
340 | * @apiPermission none |
||
341 | * @apiDescription Mark (or unmark) node as readonly |
||
342 | * @apiUse _getNodes |
||
343 | * @apiUse _multiError |
||
344 | * @apiUse _writeAction |
||
345 | * |
||
346 | * @apiExample (cURL) example: |
||
347 | * curl -XPOST "https://SERVER/api/v1/node/readonly?id[]=544627ed3c58891f058b4686&id[]=544627ed3c58891f058b46865&readonly=1" |
||
348 | * curl -XPOST "https://SERVER/api/v1/node/544627ed3c58891f058b4686/readonly?readonly=0" |
||
349 | * curl -XPOST "https://SERVER/api/v1/node/readonly?p=/absolute/path/to/my/node" |
||
350 | * |
||
351 | * @apiParam (GET Parameter) {bool} [readonly=true] Set readonly to false to make node writeable again |
||
352 | * |
||
353 | * @apiSuccessExample {json} Success-Response: |
||
354 | * HTTP/1.1 204 No Content |
||
355 | * |
||
356 | * @param array|string $id |
||
357 | * @param array|string $p |
||
358 | */ |
||
359 | public function postReadonly($id = null, $p = null, bool $readonly = true): Response |
||
360 | { |
||
361 | return $this->bulk($id, $p, function ($node) use ($readonly) { |
||
0 ignored issues
–
show
It seems like
$id defined by parameter $id on line 359 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
It seems like
$p defined by parameter $p on line 359 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
362 | $node->setReadonly($readonly); |
||
363 | |||
364 | return ['status' => 204]; |
||
365 | }); |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * @apiDefine _nodeAttributes |
||
370 | * |
||
371 | * @apiSuccess (200 OK) {number} status Status Code |
||
372 | * @apiSuccess (200 OK) {object} data Attributes |
||
373 | * @apiSuccess (200 OK) {string} data.id Unique node id |
||
374 | * @apiSuccess (200 OK) {string} data.name Name |
||
375 | * @apiSuccess (200 OK) {string} data.hash MD5 content checksum (file node only) |
||
376 | * @apiSuccess (200 OK) {object} data.meta Extended meta attributes |
||
377 | * @apiSuccess (200 OK) {string} data.meta.description UTF-8 Text Description |
||
378 | * @apiSuccess (200 OK) {string} data.meta.color Color Tag (HEX) (Like: #000000) |
||
379 | * @apiSuccess (200 OK) {string} data.meta.author Author |
||
380 | * @apiSuccess (200 OK) {string} data.meta.mail Mail contact address |
||
381 | * @apiSuccess (200 OK) {string} data.meta.license License |
||
382 | * @apiSuccess (200 OK) {string} data.meta.copyright Copyright string |
||
383 | * @apiSuccess (200 OK) {string[]} data.meta.tags Search Tags |
||
384 | * @apiSuccess (200 OK) {number} data.size Size in bytes (Only file node), number of children if collection |
||
385 | * @apiSuccess (200 OK) {string} data.mime Mime type |
||
386 | * @apiSuccess (200 OK) {boolean} data.sharelink Is node shared? |
||
387 | * @apiSuccess (200 OK) {number} data.version File version (file node only) |
||
388 | * @apiSuccess (200 OK) {mixed} data.deleted Is boolean false if not deleted, if deleted it contains a deleted timestamp |
||
389 | * @apiSuccess (200 OK) {number} data.deleted.sec Unix timestamp |
||
390 | * @apiSuccess (200 OK) {number} data.deleted.usec Additional Microsecconds to Unix timestamp |
||
391 | * @apiSuccess (200 OK) {object} data.changed Changed timestamp |
||
392 | * @apiSuccess (200 OK) {number} data.changed.sec Unix timestamp |
||
393 | * @apiSuccess (200 OK) {number} data.changed.usec Additional Microsecconds to Unix timestamp |
||
394 | * @apiSuccess (200 OK) {object} data.created Created timestamp |
||
395 | * @apiSuccess (200 OK) {number} data.created.sec Unix timestamp |
||
396 | * @apiSuccess (200 OK) {number} data.created.usec Additional Microsecconds to Unix timestamp |
||
397 | * @apiSuccess (200 OK) {boolean} data.share Node is shared |
||
398 | * @apiSuccess (200 OK) {boolean} data.directory Is node a collection or a file? |
||
399 | * |
||
400 | * @apiSuccess (200 OK - additional attributes) {string} data.thumbnail Id of preview (file node only) |
||
401 | * @apiSuccess (200 OK - additional attributes) {string} data.access Access if node is shared, one of r/rw/w |
||
402 | * @apiSuccess (200 OK - additional attributes) {string} data.shareowner Username of the share owner |
||
403 | * @apiSuccess (200 OK - additional attributes) {string} data.parent ID of the parent node |
||
404 | * @apiSuccess (200 OK - additional attributes) {string} data.path Absolute node path |
||
405 | * @apiSuccess (200 OK - additional attributes) {boolean} data.filtered Node is filtered (usually only a collection) |
||
406 | * @apiSuccess (200 OK - additional attributes) {boolean} data.readonly Node is readonly |
||
407 | * |
||
408 | * @apiParam (GET Parameter) {string[]} [attributes] Filter attributes, per default not all attributes would be returned |
||
409 | * |
||
410 | * @param null|mixed $id |
||
411 | * @param null|mixed $p |
||
412 | */ |
||
413 | |||
414 | /** |
||
415 | * @api {get} /api/v1/node/attributes?id=:id Get attributes |
||
416 | * @apiVersion 1.0.0 |
||
417 | * @apiName getAttributes |
||
418 | * @apiGroup Node |
||
419 | * @apiPermission none |
||
420 | * @apiDescription Get attributes from one or multiple nodes |
||
421 | * @apiUse _getNode |
||
422 | * @apiUse _nodeAttributes |
||
423 | * |
||
424 | * @apiParam (GET Parameter) {string[]} [attributes] Filter attributes, per default only a bunch of attributes would be returned, if you |
||
425 | * need other attributes you have to request them (for example "path") |
||
426 | * |
||
427 | * @apiExample (cURL) example: |
||
428 | * curl -XGET "https://SERVER/api/v1/node/attributes?id=544627ed3c58891f058b4686&pretty" |
||
429 | * curl -XGET "https://SERVER/api/v1/node/attributes?id=544627ed3c58891f058b4686&attributes[0]=name&attributes[1]=deleted&pretty" |
||
430 | * curl -XGET "https://SERVER/api/v1/node/544627ed3c58891f058b4686/attributes?pretty" |
||
431 | * curl -XGET "https://SERVER/api/v1/node/attributes?p=/absolute/path/to/my/node&pretty" |
||
432 | * |
||
433 | * @apiSuccessExample {json} Success-Response: |
||
434 | * HTTP/1.1 200 OK |
||
435 | * { |
||
436 | * "status": 200, |
||
437 | * "data": { |
||
438 | * "id": "544627ed3c58891f058b4686", |
||
439 | * "name": "api.php", |
||
440 | * "hash": "a77f23ed800fd7a600a8c2cfe8cc370b", |
||
441 | * "meta": { |
||
442 | * "license": "GPLv3" |
||
443 | * }, |
||
444 | * "size": 178, |
||
445 | * "mime": "text\/plain", |
||
446 | * "sharelink": true, |
||
447 | * "version": 1, |
||
448 | * "deleted": false, |
||
449 | * "changed": { |
||
450 | * "sec": 1413883885, |
||
451 | * "usec": 869000 |
||
452 | * }, |
||
453 | * "created": { |
||
454 | * "sec": 1413883885, |
||
455 | * "usec": 869000 |
||
456 | * }, |
||
457 | * "share": false, |
||
458 | * "directory": false |
||
459 | * } |
||
460 | * } |
||
461 | * |
||
462 | * @param array|string $id |
||
463 | * @param array|string $p |
||
464 | */ |
||
465 | public function getAttributes($id = null, $p = null, array $attributes = []): Response |
||
466 | { |
||
467 | if (is_array($id) || is_array($p)) { |
||
468 | $nodes = []; |
||
469 | foreach ($this->_getNodes($id, $p) as $node) { |
||
0 ignored issues
–
show
It seems like
$id defined by parameter $id on line 465 can also be of type array ; however, Balloon\App\Api\v1\Node::_getNodes() does only seem to accept string|null , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
It seems like
$p defined by parameter $p on line 465 can also be of type array ; however, Balloon\App\Api\v1\Node::_getNodes() does only seem to accept string|null , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
470 | $nodes[] = $this->node_decorator->decorate($node, $attributes); |
||
471 | } |
||
472 | |||
473 | return (new Response())->setCode(200)->setBody([ |
||
474 | 'status' => 200, |
||
475 | 'data' => $nodes, |
||
476 | ]); |
||
477 | } |
||
478 | |||
479 | $result = $this->node_decorator->decorate($this->_getNode($id, $p), $attributes); |
||
480 | |||
481 | return (new Response())->setCode(200)->setBody([ |
||
482 | 'status' => 200, |
||
483 | 'data' => $result, |
||
484 | ]); |
||
485 | } |
||
486 | |||
487 | /** |
||
488 | * @api {get} /api/v1/node/parents?id=:id Get parent nodes |
||
489 | * @apiVersion 1.0.0 |
||
490 | * @apiName getParents |
||
491 | * @apiGroup Node |
||
492 | * @apiPermission none |
||
493 | * @apiDescription Get system attributes of all parent nodes. The hirarchy of all parent nodes is ordered in a |
||
494 | * single level array beginning with the collection on the highest level. |
||
495 | * @apiUse _getNode |
||
496 | * @apiUse _nodeAttributes |
||
497 | * @apiSuccess (200 OK) {object[]} data Nodes |
||
498 | * |
||
499 | * @apiParam (GET Parameter) {boolean} [self=true] Include requested collection itself at the end of the list (Will be ignored if the requested node is a file) |
||
500 | * |
||
501 | * @apiExample (cURL) example: |
||
502 | * curl -XGET "https://SERVER/api/v1/node/parents?id=544627ed3c58891f058b4686&pretty" |
||
503 | * curl -XGET "https://SERVER/api/v1/node/parents?id=544627ed3c58891f058b4686&attributes[0]=name&attributes[1]=deleted&pretty" |
||
504 | * curl -XGET "https://SERVER/api/v1/node/544627ed3c58891f058b4686/parents?pretty&self=1" |
||
505 | * curl -XGET "https://SERVER/api/v1/node/parents?p=/absolute/path/to/my/node&self=1" |
||
506 | * |
||
507 | * @apiSuccessExample {json} Success-Response: |
||
508 | * HTTP/1.1 200 OK |
||
509 | * { |
||
510 | * "status": 200, |
||
511 | * "data": [ |
||
512 | * { |
||
513 | * "id": "544627ed3c58891f058bbbaa", |
||
514 | * "name": "rootdir", |
||
515 | * "meta": {}, |
||
516 | * "size": 1, |
||
517 | * "mime": "inode\/directory", |
||
518 | * "deleted": false, |
||
519 | * "changed": { |
||
520 | * "sec": 1413883880, |
||
521 | * "usec": 869001 |
||
522 | * }, |
||
523 | * }, |
||
524 | * "created": { |
||
525 | * "sec": 1413883880, |
||
526 | * "usec": 869001 |
||
527 | * }, |
||
528 | * "share": false, |
||
529 | * "directory": true |
||
530 | * }, |
||
531 | * { |
||
532 | * "id": "544627ed3c58891f058b46cc", |
||
533 | * "name": "parentdir", |
||
534 | * "meta": {}, |
||
535 | * "size": 3, |
||
536 | * "mime": "inode\/directory", |
||
537 | * "deleted": false, |
||
538 | * "changed": { |
||
539 | * "sec": 1413883885, |
||
540 | * "usec": 869000 |
||
541 | * }, |
||
542 | * "created": { |
||
543 | * "sec": 1413883885, |
||
544 | * "usec": 869000 |
||
545 | * }, |
||
546 | * "share": false, |
||
547 | * "directory": true |
||
548 | * } |
||
549 | * ] |
||
550 | * } |
||
551 | * |
||
552 | * @param string $id |
||
553 | * @param string $p |
||
554 | */ |
||
555 | public function getParents(?string $id = null, ?string $p = null, array $attributes = [], bool $self = false): Response |
||
556 | { |
||
557 | $request = $this->_getNode($id, $p); |
||
558 | $parents = $request->getParents(); |
||
559 | $result = []; |
||
560 | |||
561 | if (true === $self && $request instanceof Collection) { |
||
562 | $result[] = $this->node_decorator->decorate($request, $attributes); |
||
563 | } |
||
564 | |||
565 | foreach ($parents as $node) { |
||
566 | $result[] = $this->node_decorator->decorate($node, $attributes); |
||
567 | } |
||
568 | |||
569 | return (new Response())->setCode(200)->setBody([ |
||
570 | 'status' => 200, |
||
571 | 'data' => $result, |
||
572 | ]); |
||
573 | } |
||
574 | |||
575 | /** |
||
576 | * @api {post} /api/v1/node/meta-attributes?id=:id Change meta attributes |
||
577 | * @apiVersion 1.0.0 |
||
578 | * @apiName postMetaAttributes |
||
579 | * @apiGroup Node |
||
580 | * @apiPermission none |
||
581 | * @apiDescription Change meta attributes of a node |
||
582 | * @apiUse _getNodes |
||
583 | * @apiUse _multiError |
||
584 | * |
||
585 | * @apiParam (GET Parameter) {string} [attributes.description] UTF-8 Text Description - Can contain anything as long as it is a string |
||
586 | * @apiParam (GET Parameter) {string} [attributes.color] Color Tag - Can contain anything as long as it is a string |
||
587 | * @apiParam (GET Parameter) {string} [attributes.author] Author - Can contain anything as long as it is a string |
||
588 | * @apiParam (GET Parameter) {string} [attributes.mail] Mail contact address - Can contain anything as long as it is a string |
||
589 | * @apiParam (GET Parameter) {string} [attributes.license] License - Can contain anything as long as it is a string |
||
590 | * @apiParam (GET Parameter) {string} [attributes.copyright] Copyright string - Can contain anything as long as it is a string |
||
591 | * @apiParam (GET Parameter) {string[]} [attributes.tags] Tags - Must be an array full of strings |
||
592 | * |
||
593 | * @apiExample (cURL) example: |
||
594 | * curl -XPOST "https://SERVER/api/v1/node/meta-attributes?id=544627ed3c58891f058b4686&author=peter.meier" |
||
595 | * curl -XPOST "https://SERVER/api/v1/node/544627ed3c58891f058b4686/meta-attributes?author=example" |
||
596 | * curl -XPOST "https://SERVER/api/v1/node/meta-attributes?p=/absolute/path/to/my/node?license=GPL-3.0" |
||
597 | * |
||
598 | * @apiSuccessExample {json} Success-Response: |
||
599 | * HTTP/1.1 204 No Content |
||
600 | * |
||
601 | * @param array|string $id |
||
602 | * @param array|string $p |
||
603 | */ |
||
604 | public function postMetaAttributes(?string $id = null, ?string $p = null): Response |
||
605 | { |
||
606 | return $this->bulk($id, $p, function ($node) { |
||
0 ignored issues
–
show
It seems like
$id defined by parameter $id on line 604 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
It seems like
$p defined by parameter $p on line 604 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
607 | $node->setMetaAttributes($_POST); |
||
608 | |||
609 | return ['status' => 204]; |
||
610 | }); |
||
611 | } |
||
612 | |||
613 | /** |
||
614 | * @api {post} /api/v1/node/name?id=:id Rename node |
||
615 | * @apiVersion 1.0.0 |
||
616 | * @apiName postName |
||
617 | * @apiGroup Node |
||
618 | * @apiPermission none |
||
619 | * @apiDescription Rename a node. The characters (\ < > : " / * ? |) (without the "()") are not allowed to use within a node name. |
||
620 | * @apiUse _getNode |
||
621 | * @apiUse _writeAction |
||
622 | * |
||
623 | * @apiParam (GET Parameter) {string} [name] The new name of the node |
||
624 | * @apiError (Error 400) Exception name contains invalid characters |
||
625 | * |
||
626 | * @apiExample (cURL) example: |
||
627 | * curl -XPOST "https://SERVER/api/v1/node/name?id=544627ed3c58891f058b4686&name=newname.txt" |
||
628 | * curl -XPOST "https://SERVER/api/v1/node/544627ed3c58891f058b4677/name?name=newdir" |
||
629 | * curl -XPOST "https://SERVER/api/v1/node/name?p=/absolute/path/to/my/node&name=newname.txt" |
||
630 | * |
||
631 | * @apiSuccessExample {json} Success-Response: |
||
632 | * HTTP/1.1 204 No Content |
||
633 | * |
||
634 | * @param string $id |
||
635 | * @param string $p |
||
636 | */ |
||
637 | public function postName(string $name, ?string $id = null, ?string $p = null): Response |
||
638 | { |
||
639 | $this->_getNode($id, $p)->setName($name); |
||
640 | |||
641 | return (new Response())->setCode(204); |
||
642 | } |
||
643 | |||
644 | /** |
||
645 | * @api {post} /api/v1/node/clone?id=:id Clone node |
||
646 | * @apiVersion 1.0.0 |
||
647 | * @apiName postClone |
||
648 | * @apiGroup Node |
||
649 | * @apiPermission none |
||
650 | * @apiDescription Clone a node |
||
651 | * @apiUse _getNode |
||
652 | * @apiUse _conflictNode |
||
653 | * @apiUse _multiError |
||
654 | * @apiUse _writeAction |
||
655 | * |
||
656 | * @apiParam (GET Parameter) {string} [destid] Either destid or destp (path) of the new parent collection node must be given. |
||
657 | * @apiParam (GET Parameter) {string} [destp] Either destid or destp (path) of the new parent collection node must be given. |
||
658 | * |
||
659 | * @apiExample (cURL) example: |
||
660 | * curl -XPOST "https://SERVER/api/v1/node/clone?id=544627ed3c58891f058b4686&dest=544627ed3c58891f058b4676" |
||
661 | * curl -XPOST "https://SERVER/api/v1/node/544627ed3c58891f058b4686/clone?dest=544627ed3c58891f058b4676&conflict=2" |
||
662 | * curl -XPOST "https://SERVER/api/v1/node/clone?p=/absolute/path/to/my/node&conflict=0&destp=/new/parent" |
||
663 | * |
||
664 | * @apiSuccessExample {json} Success-Response: |
||
665 | * HTTP/1.1 204 No Content |
||
666 | * |
||
667 | * @param array|string $id |
||
668 | * @param array|string $p |
||
669 | * @param string $destid |
||
670 | * @param string $destp |
||
671 | */ |
||
672 | public function postClone( |
||
673 | $id = null, |
||
674 | $p = null, |
||
675 | ?string $destid = null, |
||
676 | ?string $destp = null, |
||
677 | int $conflict = 0 |
||
678 | ): Response { |
||
679 | try { |
||
680 | $parent = $this->_getNode($destid, $destp, Collection::class, false, true); |
||
681 | } catch (Exception\NotFound $e) { |
||
682 | throw new Exception\NotFound( |
||
683 | 'destination collection was not found or is not a collection', |
||
684 | Exception\NotFound::DESTINATION_NOT_FOUND |
||
685 | ); |
||
686 | } |
||
687 | |||
688 | return $this->bulk($id, $p, function ($node) use ($parent, $conflict) { |
||
0 ignored issues
–
show
It seems like
$id defined by parameter $id on line 673 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
It seems like
$p defined by parameter $p on line 674 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
689 | $result = $node->copyTo($parent, $conflict); |
||
690 | |||
691 | return [ |
||
692 | 'status' => 201, |
||
693 | 'data' => $result, |
||
694 | ]; |
||
695 | }); |
||
696 | } |
||
697 | |||
698 | /** |
||
699 | * @api {post} /api/v1/node/move?id=:id Move node |
||
700 | * @apiVersion 1.0.0 |
||
701 | * @apiName postMove |
||
702 | * @apiGroup Node |
||
703 | * @apiPermission none |
||
704 | * @apiDescription Move node |
||
705 | * @apiUse _getNodes |
||
706 | * @apiUse _conflictNode |
||
707 | * @apiUse _multiError |
||
708 | * @apiUse _writeAction |
||
709 | * |
||
710 | * @apiParam (GET Parameter) {string} [destid] Either destid or destp (path) of the new parent collection node must be given. |
||
711 | * @apiParam (GET Parameter) {string} [destp] Either destid or destp (path) of the new parent collection node must be given. |
||
712 | * |
||
713 | * @apiExample (cURL) example: |
||
714 | * curl -XPOST "https://SERVER/api/v1/node/move?id=544627ed3c58891f058b4686?destid=544627ed3c58891f058b4655" |
||
715 | * curl -XPOST "https://SERVER/api/v1/node/544627ed3c58891f058b4686/move?destid=544627ed3c58891f058b4655" |
||
716 | * curl -XPOST "https://SERVER/api/v1/node/move?p=/absolute/path/to/my/node&destp=/new/parent&conflict=1 |
||
717 | * |
||
718 | * @apiSuccessExample {json} Success-Response: |
||
719 | * HTTP/1.1 204 No Content |
||
720 | * |
||
721 | * @apiSuccessExample {json} Success-Response (conflict=1): |
||
722 | * HTTP/1.1 200 OK |
||
723 | * { |
||
724 | * "status":200, |
||
725 | * "data": "renamed (xy23)" |
||
726 | * } |
||
727 | * |
||
728 | * @param array|string $id |
||
729 | * @param array|string $p |
||
730 | * @param string $destid |
||
731 | * @param string $destp |
||
732 | */ |
||
733 | public function postMove( |
||
734 | $id = null, |
||
735 | $p = null, |
||
736 | ?string $destid = null, |
||
737 | ?string $destp = null, |
||
738 | int $conflict = 0 |
||
739 | ): Response { |
||
740 | try { |
||
741 | $parent = $this->_getNode($destid, $destp, Collection::class, false, true); |
||
742 | } catch (Exception\NotFound $e) { |
||
743 | throw new Exception\NotFound( |
||
744 | 'destination collection was not found or is not a collection', |
||
745 | Exception\NotFound::DESTINATION_NOT_FOUND |
||
746 | ); |
||
747 | } |
||
748 | |||
749 | return $this->bulk($id, $p, function ($node) use ($parent, $conflict) { |
||
0 ignored issues
–
show
It seems like
$id defined by parameter $id on line 734 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
It seems like
$p defined by parameter $p on line 735 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
750 | $result = $node->setParent($parent, $conflict); |
||
0 ignored issues
–
show
$result is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
751 | if (NodeInterface::CONFLICT_RENAME === $conflict) { |
||
752 | return [ |
||
753 | 'status' => 200, |
||
754 | 'data' => $node->getName(), |
||
755 | ]; |
||
756 | } |
||
757 | |||
758 | return [ |
||
759 | 'status' => 204, |
||
760 | ]; |
||
761 | }); |
||
762 | } |
||
763 | |||
764 | /** |
||
765 | * @api {delete} /api/v1/node?id=:id Delete node |
||
766 | * @apiVersion 1.0.0 |
||
767 | * @apiName delete |
||
768 | * @apiGroup Node |
||
769 | * @apiPermission none |
||
770 | * @apiDescription Delete node |
||
771 | * @apiUse _getNodes |
||
772 | * @apiUse _multiError |
||
773 | * @apiUse _writeAction |
||
774 | * |
||
775 | * @apiParam (GET Parameter) {boolean} [force=false] Force flag need to be set to delete a node from trash (node must have the deleted flag) |
||
776 | * @apiParam (GET Parameter) {boolean} [ignore_flag=false] If both ignore_flag and force_flag were set, the node will be deleted completely |
||
777 | * @apiParam (GET Parameter) {number} [at] Has to be a valid unix timestamp if so the node will destroy itself at this specified time instead immediatly |
||
778 | * |
||
779 | * @apiExample (cURL) example: |
||
780 | * curl -XDELETE "https://SERVER/api/v1/node?id=544627ed3c58891f058b4686" |
||
781 | * curl -XDELETE "https://SERVER/api/v1/node/544627ed3c58891f058b4686?force=1&ignore_flag=1" |
||
782 | * curl -XDELETE "https://SERVER/api/v1/node?p=/absolute/path/to/my/node" |
||
783 | * |
||
784 | * @apiSuccessExample {json} Success-Response: |
||
785 | * HTTP/1.1 204 No Content |
||
786 | * |
||
787 | * @param array|string $id |
||
788 | * @param array|string $p |
||
789 | * @param int $at |
||
790 | */ |
||
791 | public function delete( |
||
792 | $id = null, |
||
793 | $p = null, |
||
794 | bool $force = false, |
||
795 | bool $ignore_flag = false, |
||
796 | ?string $at = null |
||
797 | ): Response { |
||
798 | $failures = []; |
||
0 ignored issues
–
show
$failures is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
799 | |||
800 | if (null !== $at && '0' !== $at) { |
||
0 ignored issues
–
show
|
|||
801 | $at = $this->_verifyAttributes(['destroy' => $at])['destroy']; |
||
802 | } |
||
803 | |||
804 | return $this->bulk($id, $p, function ($node) use ($force, $ignore_flag, $at) { |
||
0 ignored issues
–
show
It seems like
$id defined by parameter $id on line 792 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
It seems like
$p defined by parameter $p on line 793 can also be of type null ; however, Balloon\App\Api\v1\Node::bulk() does only seem to accept array|string , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
805 | if (null === $at) { |
||
806 | $node->delete($force && $node->isDeleted() || $force && $ignore_flag); |
||
807 | } else { |
||
808 | if ('0' === $at) { |
||
809 | $at = null; |
||
0 ignored issues
–
show
Consider using a different name than the imported variable
$at , or did you forget to import by reference?
It seems like you are assigning to a variable which was imported through a For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope. Change not visible in outer-scope$x = 1;
$callable = function() use ($x) {
$x = 2; // Not visible in outer scope. If you would like this, how
// about using a different variable name than $x?
};
$callable();
var_dump($x); // integer(1)
Change visible in outer-scope$x = 1;
$callable = function() use (&$x) {
$x = 2;
};
$callable();
var_dump($x); // integer(2)
Loading history...
|
|||
810 | } |
||
811 | $node->setDestroyable($at); |
||
812 | } |
||
813 | |||
814 | return [ |
||
815 | 'status' => 204, |
||
816 | ]; |
||
817 | }); |
||
818 | } |
||
819 | |||
820 | /** |
||
821 | * @api {get} /api/v1/node/query Custom query |
||
822 | * @apiVersion 1.0.0 |
||
823 | * @apiName getQuery |
||
824 | * @apiGroup Node |
||
825 | * @apiPermission none |
||
826 | * @apiDescription A custom query is similar requet to children. You do not have to provide any parent node (id or p) |
||
827 | * but you have to provide a filter therefore you can collect any nodes which do match the provided filter. It is a form of a search |
||
828 | * (search) but does not use the search engine like GET /node/search does. You can also create a persistent query collection, just look at |
||
829 | * POST /collection, there you can attach a filter option to the attributes paramater which would be the same as a custom query but just persistent. |
||
830 | * Since query parameters can only be strings and you perhaps would like to filter other data types, you have to send json as parameter to the server. |
||
831 | * @apiUse _nodeAttributes |
||
832 | * |
||
833 | * @apiExample (cURL) example: |
||
834 | * curl -XGET https://SERVER/api/v1/node/query?{%22filter%22:{%22shared%22:true,%22reference%22:{%22$exists%22:0}}} |
||
835 | * |
||
836 | * @apiParam (GET Parameter) {string[]} [attributes] Filter node attributes |
||
837 | * @apiParam (GET Parameter) {string[]} [filter] Filter nodes |
||
838 | * @apiParam (GET Parameter) {number} [deleted=0] Wherever include deleted nodes or not, possible values:</br> |
||
839 | * - 0 Exclude deleted</br> |
||
840 | * - 1 Only deleted</br> |
||
841 | * - 2 Include deleted</br> |
||
842 | * |
||
843 | * @apiSuccess (200 OK) {number} status Status Code |
||
844 | * @apiSuccess (200 OK) {object[]} data Children |
||
845 | * @apiSuccessExample {json} Success-Response: |
||
846 | * HTTP/1.1 200 OK |
||
847 | * { |
||
848 | * "status":200, |
||
849 | * "data": [{..}, {...}] //Shorted |
||
850 | * } |
||
851 | */ |
||
852 | public function getQuery(int $deleted = 0, array $filter = [], array $attributes = []): Response |
||
853 | { |
||
854 | $children = []; |
||
855 | $nodes = $this->fs->findNodesByFilterUser($deleted, $filter); |
||
856 | |||
857 | foreach ($nodes as $node) { |
||
858 | $child = $this->node_decorator->decorate($node, $attributes); |
||
859 | $children[] = $child; |
||
860 | } |
||
861 | |||
862 | return (new Response())->setCode(200)->setBody([ |
||
863 | 'status' => 200, |
||
864 | 'data' => $children, |
||
865 | ]); |
||
866 | } |
||
867 | |||
868 | /** |
||
869 | * @api {get} /api/v1/node/trash Get trash |
||
870 | * @apiName getTrash |
||
871 | * @apiVersion 1.0.0 |
||
872 | * @apiGroup Node |
||
873 | * @apiPermission none |
||
874 | * @apiDescription A similar endpoint to /api/v1/node/query filer={'deleted': {$type: 9}] but instead returning all deleted |
||
875 | * nodes (including children which are deleted as well) this enpoint only returns the first deleted node from every subtree) |
||
876 | * @apiUse _nodeAttributes |
||
877 | * |
||
878 | * @apiExample (cURL) example: |
||
879 | * curl -XGET https://SERVER/api/v1/node/trash?pretty |
||
880 | * |
||
881 | * @apiParam (GET Parameter) {string[]} [attributes] Filter node attributes |
||
882 | * |
||
883 | * @apiSuccess (200 OK) {number} status Status Code |
||
884 | * @apiSuccess (200 OK) {object[]} data Children |
||
885 | * @apiSuccessExample {json} Success-Response: |
||
886 | * HTTP/1.1 200 OK |
||
887 | * { |
||
888 | * "status":200, |
||
889 | * "data": [{..}, {...}] //Shorted |
||
890 | * } |
||
891 | */ |
||
892 | public function getTrash(array $attributes = []): Response |
||
893 | { |
||
894 | $children = []; |
||
895 | $nodes = $this->fs->findNodesByFilterUser(NodeInterface::DELETED_ONLY, ['deleted' => ['$type' => 9]]); |
||
896 | |||
897 | foreach ($nodes as $node) { |
||
898 | try { |
||
899 | $parent = $node->getParent(); |
||
900 | if (null !== $parent && $parent->isDeleted()) { |
||
901 | continue; |
||
902 | } |
||
903 | } catch (\Exception $e) { |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
904 | } |
||
905 | |||
906 | $child = $this->node_decorator->decorate($node, $attributes); |
||
907 | $children[] = $child; |
||
908 | } |
||
909 | |||
910 | return (new Response())->setCode(200)->setBody([ |
||
911 | 'status' => 200, |
||
912 | 'data' => array_values($children), |
||
913 | ]); |
||
914 | } |
||
915 | |||
916 | /** |
||
917 | * @api {get} /api/v1/node/delta Get delta |
||
918 | * @apiVersion 1.0.0 |
||
919 | * @apiName getDelta |
||
920 | * @apiGroup Node |
||
921 | * @apiPermission none |
||
922 | * @apiUse _getNode |
||
923 | * |
||
924 | * @apiDescription Use this method to request a delta feed with all changes on the server (or) a snapshot of the server state. |
||
925 | * since the state of the submited cursor. If no cursor was submited the server will create one which can than be used to request any further deltas. |
||
926 | * If has_more is TRUE you need to request /delta immediatly again to |
||
927 | * receive the next bunch of deltas. If has_more is FALSE you should wait at least 120s seconds before any further requests to the |
||
928 | * api endpoint. You can also specify additional node attributes with the $attributes paramter or request the delta feed only for a specific node (see Get Attributes for that). |
||
929 | * If reset is TRUE you have to clean your local state because you will receive a snapshot of the server state, it is the same as calling the /delta endpoint |
||
930 | * without a cursor. reset could be TRUE if there was an account maintenance or a simialar case. |
||
931 | * You can request a different limit as well but be aware that the number of nodes could be slighty different from your requested limit. |
||
932 | * If requested with parameter id or p the delta gets generated recursively from the node given. |
||
933 | * |
||
934 | * @apiParam (GET Parameter) {number} [limit=250] Limit the number of delta entries, if too low you have to call this endpoint more often since has_more would be true more often |
||
935 | * @apiParam (GET Parameter) {string[]} [attributes] Filter attributes, per default not all attributes would be returned |
||
936 | * @apiParam (GET Parameter) {string} [cursor=null] Set a cursor to rquest next nodes within delta processing |
||
937 | * |
||
938 | * @apiExample (cURL) example: |
||
939 | * curl -XGET "https://SERVER/api/v1/node/delta?pretty" |
||
940 | * |
||
941 | * @apiSuccess (200 OK) {number} status Status Code |
||
942 | * @apiSuccess (200 OK) {object} data Delta feed |
||
943 | * @apiSuccess (200 OK) {boolean} data.reset If true the local state needs to be reseted, is alway TRUE during |
||
944 | * the first request to /delta without a cursor or in special cases like server or account maintenance |
||
945 | * @apiSuccess (200 OK) {string} data.cursor The cursor needs to be stored and reused to request further deltas |
||
946 | * @apiSuccess (200 OK) {boolean} data.has_more If has_more is TRUE /delta can be requested immediatly after the last request |
||
947 | * to receive further delta. If it is FALSE we should wait at least 120 seconds before any further delta requests to the api endpoint |
||
948 | * @apiSuccess (200 OK) {object[]} data.nodes Node list to process |
||
949 | * @apiSuccess (200 OK) {string} data.nodes.id Node ID |
||
950 | * @apiSuccess (200 OK) {string} data.nodes.deleted Is node deleted? |
||
951 | * @apiSuccess (200 OK) {object} data.nodes.changed Changed timestamp |
||
952 | * @apiSuccess (200 OK) {number} data.nodes.changed.sec Unix timestamp |
||
953 | * @apiSuccess (200 OK) {number} data.nodes.changed.usec Additional Microsecconds to Unix timestamp |
||
954 | * @apiSuccess (200 OK) {object} data.nodes.created Created timestamp (If data.nodes[].deleted is TRUE, created will be NULL) |
||
955 | * @apiSuccess (200 OK) {number} data.nodes.created.sec Unix timestamp |
||
956 | * @apiSuccess (200 OK) {number} data.nodes.created.usec Additional Microsecconds to Unix timestamp |
||
957 | * @apiSuccess (200 OK) {string} data.nodes.path The full absolute path to the node |
||
958 | * @apiSuccess (200 OK) {string} data.nodes.directory Is true if node is a directory |
||
959 | * @apiSuccessExample {json} Success-Response: |
||
960 | * HTTP/1.1 200 OK |
||
961 | * { |
||
962 | * "status": 200, |
||
963 | * "data": { |
||
964 | * "reset": false, |
||
965 | * "cursor": "aW5pdGlhbHwxMDB8NTc1YTlhMGIzYzU4ODkwNTE0OGI0NTZifDU3NWE5YTBiM2M1ODg5MDUxNDhiNDU2Yw==", |
||
966 | * "has_more": false, |
||
967 | * "nodes": [ |
||
968 | * { |
||
969 | * "id": "581afa783c5889ad7c8b4572", |
||
970 | * "deleted": true, |
||
971 | * "created": null, |
||
972 | * "changed": { |
||
973 | * "sec": 1478163064, |
||
974 | * "usec": 31.0.0 |
||
975 | * }, |
||
976 | * "path": "\/AAA\/AL", |
||
977 | * "directory": true |
||
978 | * }, |
||
979 | * { |
||
980 | * "id": "581afa783c5889ad7c8b3dcf", |
||
981 | * "deleted": false, |
||
982 | * "created": { |
||
983 | * "sec": 1478163048, |
||
984 | * "usec": 101000 |
||
985 | * }, |
||
986 | * "changed": { |
||
987 | * "sec": 1478163048, |
||
988 | * "usec": 101000 |
||
989 | * }, |
||
990 | * "path": "\/AL", |
||
991 | * "directory": true |
||
992 | * } |
||
993 | * ] |
||
994 | * } |
||
995 | * } |
||
996 | * |
||
997 | * @param string $id |
||
998 | * @param string $p |
||
999 | * @param string $cursor |
||
1000 | */ |
||
1001 | public function getDelta( |
||
1002 | DeltaDecorator $delta_decorator, |
||
1003 | ?string $id = null, |
||
1004 | ?string $p = null, |
||
1005 | ?string $cursor = null, |
||
1006 | int $limit = 250, |
||
1007 | array $attributes = [] |
||
1008 | ): Response { |
||
1009 | if (null !== $id || null !== $p) { |
||
1010 | $node = $this->_getNode($id, $p); |
||
1011 | } else { |
||
1012 | $node = null; |
||
1013 | } |
||
1014 | |||
1015 | $result = $this->fs->getDelta()->getDeltaFeed($cursor, $limit, $node); |
||
1016 | |||
1017 | $default = ['id', 'deleted', 'created', 'changed', 'path', 'directory']; |
||
1018 | $attributes = array_merge($default, $attributes); |
||
1019 | |||
1020 | foreach ($result['nodes'] as &$node) { |
||
1021 | if ($node instanceof NodeInterface) { |
||
1022 | $node = $this->node_decorator->decorate($node, $attributes); |
||
1023 | } else { |
||
1024 | $node = $delta_decorator->decorate($node, $attributes); |
||
1025 | } |
||
1026 | } |
||
1027 | |||
1028 | return (new Response())->setCode(200)->setBody([ |
||
1029 | 'status' => 200, |
||
1030 | 'data' => $result, |
||
1031 | ]); |
||
1032 | } |
||
1033 | |||
1034 | /** |
||
1035 | * @api {get} /api/v1/node/event-log?id=:id Event log |
||
1036 | * @apiVersion 1.0.0 |
||
1037 | * @apiName getEventLog |
||
1038 | * @apiGroup Node |
||
1039 | * @apiPermission none |
||
1040 | * @apiUse _getNode |
||
1041 | * @apiDescription Get detailed event log |
||
1042 | * Request all modifications which are made by the user himself or share members. |
||
1043 | * Possible operations are the follwing: |
||
1044 | * - deleteCollectionReference |
||
1045 | * - deleteCollectionShare |
||
1046 | * - deleteCollection |
||
1047 | * - addCollection |
||
1048 | * - addFile |
||
1049 | * - addCollectionShare |
||
1050 | * - addCollectionReference |
||
1051 | * - undeleteFile |
||
1052 | * - undeleteCollectionReference |
||
1053 | * - undeleteCollectionShare |
||
1054 | * - restoreFile |
||
1055 | * - renameFile |
||
1056 | * - renameCollection |
||
1057 | * - renameCollectionShare |
||
1058 | * - renameCollectionRFeference |
||
1059 | * - copyFile |
||
1060 | * - copyCollection |
||
1061 | * - copyCollectionShare |
||
1062 | * - copyCollectionRFeference |
||
1063 | * - moveFile |
||
1064 | * - moveCollection |
||
1065 | * - moveCollectionReference |
||
1066 | * - moveCollectionShare |
||
1067 | * |
||
1068 | * @apiExample (cURL) example: |
||
1069 | * curl -XGET "https://SERVER/api/v1/node/event-log?pretty" |
||
1070 | * curl -XGET "https://SERVER/api/v1/node/event-log?id=544627ed3c58891f058b4686&pretty" |
||
1071 | * curl -XGET "https://SERVER/api/v1/node/544627ed3c58891f058b4686/event-log?pretty&limit=10" |
||
1072 | * curl -XGET "https://SERVER/api/v1/node/event-log?p=/absolute/path/to/my/node&pretty" |
||
1073 | * |
||
1074 | * @apiParam (GET Parameter) {number} [limit=100] Sets limit of events to be returned |
||
1075 | * @apiParam (GET Parameter) {number} [skip=0] How many events are skiped (useful for paging) |
||
1076 | * |
||
1077 | * @apiSuccess (200 OK) {number} status Status Code |
||
1078 | * @apiSuccess (200 OK) {object[]} data Events |
||
1079 | * @apiSuccess (200 OK) {number} data.event Event ID |
||
1080 | * @apiSuccess (200 OK) {object} data.timestamp event timestamp |
||
1081 | * @apiSuccess (200 OK) {number} data.timestamp.sec Event timestamp timestamp in Unix time |
||
1082 | * @apiSuccess (200 OK) {number} data.timestamp.usec Additional microseconds to changed Unix timestamp |
||
1083 | * @apiSuccess (200 OK) {string} data.operation event operation (like addCollection, deleteFile, ...) |
||
1084 | * @apiSuccess (200 OK) {string} data.parent ID of the parent node at the time of the event |
||
1085 | * @apiSuccess (200 OK) {object} data.previous Previous state of actual data which has been modified during an event, can contain either version, name or parent |
||
1086 | * @apiSuccess (200 OK) {number} data.previous.version Version at the time before the event |
||
1087 | * @apiSuccess (200 OK) {string} data.previous.name Name at the time before the event |
||
1088 | * @apiSuccess (200 OK) {string} data.previous.parent Parent node at the time before the event |
||
1089 | * @apiSuccess (200 OK) {string} data.share If of the shared folder at the time of the event |
||
1090 | * @apiSuccess (200 OK) {string} data.name Name of the node at the time of the event |
||
1091 | * @apiSuccess (200 OK) {object} data.node Current data of the node (Not from the time of the event!) |
||
1092 | * @apiSuccess (200 OK) {boolean} data.node.deleted True if the node is deleted, false otherwise |
||
1093 | * @apiSuccess (200 OK) {string} data.node.id Actual ID of the node |
||
1094 | * @apiSuccess (200 OK) {string} data.node.name Current name of the node |
||
1095 | * @apiSuccess (200 OK) {object} data.user Data which contains information about the user who executed an event |
||
1096 | * @apiSuccess (200 OK) {string} data.user.id Actual user ID |
||
1097 | * @apiSuccess (200 OK) {string} data.user.username Current username of executed event |
||
1098 | * |
||
1099 | * @apiSuccessExample {json} Success-Response: |
||
1100 | * HTTP/1.1 200 OK |
||
1101 | * { |
||
1102 | * "status": 200, |
||
1103 | * "data": [ |
||
1104 | * { |
||
1105 | * "event": "57628e523c5889026f8b4570", |
||
1106 | * "timestamp": { |
||
1107 | * "sec": 1466076753, |
||
1108 | * "usec": 988000 |
||
1109 | * }, |
||
1110 | * "operation": "restoreFile", |
||
1111 | * "name": "file.txt", |
||
1112 | * "previous": { |
||
1113 | * "version": 16 |
||
1114 | * }, |
||
1115 | * "node": { |
||
1116 | * "id": "558c0b273c588963078b457a", |
||
1117 | * "name": "3dddsceheckfile.txt", |
||
1118 | * "deleted": false |
||
1119 | * }, |
||
1120 | * "parent": null, |
||
1121 | * "user": { |
||
1122 | * "id": "54354cb63c58891f058b457f", |
||
1123 | * "username": "gradmin.bzu" |
||
1124 | * }, |
||
1125 | * "share": null |
||
1126 | * } |
||
1127 | * ] |
||
1128 | * } |
||
1129 | * |
||
1130 | * @param string $id |
||
1131 | * @param string $p |
||
1132 | */ |
||
1133 | public function getEventLog(EventDecorator $event_decorator, ?string $id = null, ?string $p = null, int $skip = 0, int $limit = 100): Response |
||
1134 | { |
||
1135 | if (null !== $id || null !== $p) { |
||
1136 | $node = $this->_getNode($id, $p); |
||
1137 | } else { |
||
1138 | $node = null; |
||
1139 | } |
||
1140 | |||
1141 | $result = $this->fs->getDelta()->getEventLog($limit, $skip, $node); |
||
1142 | $body = []; |
||
1143 | foreach ($result as $event) { |
||
1144 | $body[] = $event_decorator->decorate($event); |
||
1145 | } |
||
1146 | |||
1147 | return (new Response())->setCode(200)->setBody([ |
||
1148 | 'status' => 200, |
||
1149 | 'data' => $body, |
||
1150 | ]); |
||
1151 | } |
||
1152 | |||
1153 | /** |
||
1154 | * @api {get} /api/v1/node/last-cursor Get last Cursor |
||
1155 | * @apiVersion 1.0.0 |
||
1156 | * @apiName geLastCursor |
||
1157 | * @apiGroup Node |
||
1158 | * @apiUse _getNode |
||
1159 | * @apiPermission none |
||
1160 | * @apiDescription Use this method to request the latest cursor if you only need to now |
||
1161 | * if there are changes on the server. This method will not return any other data than the |
||
1162 | * newest cursor. To request a feed with all deltas request /delta. |
||
1163 | * |
||
1164 | * @apiExample (cURL) example: |
||
1165 | * curl -XGET "https://SERVER/api/v1/node/last-cursor?pretty" |
||
1166 | * |
||
1167 | * @apiSuccess (200 OK) {number} status Status Code |
||
1168 | * @apiSuccess (200 OK) {string} data Newest cursor |
||
1169 | * @apiSuccessExample {json} Success-Response: |
||
1170 | * HTTP/1.1 200 OK |
||
1171 | * { |
||
1172 | * "status": 200, |
||
1173 | * "data": "aW5pdGlhbHwxMDB8NTc1YTlhMGIzYzU4ODkwNTE0OGI0NTZifDU3NWE5YTBiM2M1ODg5MDUxNDhiNDU2Yw==" |
||
1174 | * } |
||
1175 | * |
||
1176 | * @param string $id |
||
1177 | * @param string $p |
||
1178 | */ |
||
1179 | public function getLastCursor(?string $id = null, ?string $p = null): Response |
||
1180 | { |
||
1181 | if (null !== $id || null !== $p) { |
||
1182 | $node = $this->_getNode($id, $p); |
||
0 ignored issues
–
show
$node is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
1183 | } else { |
||
1184 | $node = null; |
||
0 ignored issues
–
show
$node is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
1185 | } |
||
1186 | |||
1187 | $result = $this->fs->getDelta()->getLastCursor(); |
||
1188 | |||
1189 | return (new Response())->setCode(200)->setBody([ |
||
1190 | 'status' => 200, |
||
1191 | 'data' => $result, |
||
1192 | ]); |
||
1193 | } |
||
1194 | |||
1195 | /** |
||
1196 | * Do bulk operations. |
||
1197 | * |
||
1198 | * @param array|string $id |
||
1199 | * @param array|string $p |
||
1200 | */ |
||
1201 | protected function bulk($id, $p, Closure $action): Response |
||
1202 | { |
||
1203 | if (is_array($id) || is_array($p)) { |
||
1204 | $errors = []; |
||
1205 | $body = []; |
||
1206 | |||
1207 | foreach ($this->_getNodes($id, $p) as $node) { |
||
0 ignored issues
–
show
It seems like
$id defined by parameter $id on line 1201 can also be of type array ; however, Balloon\App\Api\v1\Node::_getNodes() does only seem to accept string|null , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
It seems like
$p defined by parameter $p on line 1201 can also be of type array ; however, Balloon\App\Api\v1\Node::_getNodes() does only seem to accept string|null , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
1208 | try { |
||
1209 | $body[] = $action->call($this, $node); |
||
1210 | } catch (\Exception $e) { |
||
1211 | $errors[] = [ |
||
1212 | 'error' => get_class($e), |
||
1213 | 'message' => $e->getMessage(), |
||
1214 | 'status' => $e->getCode(), |
||
1215 | ]; |
||
1216 | } |
||
1217 | } |
||
1218 | |||
1219 | if (!empty($errors)) { |
||
1220 | return (new Response())->setCode(400)->setBody([ |
||
1221 | 'status' => 400, |
||
1222 | 'data' => $errors, |
||
1223 | ]); |
||
1224 | } |
||
1225 | if (empty($body)) { |
||
1226 | return (new Response())->setCode(204); |
||
1227 | } |
||
1228 | $body = array_shift($body); |
||
1229 | $response = (new Response())->setCode($body['status']); |
||
1230 | |||
1231 | if (isset($body['data'])) { |
||
1232 | $response->setBody([ |
||
1233 | 'status' => $body['status'], |
||
1234 | 'data' => $body['data'], |
||
1235 | ]); |
||
1236 | } |
||
1237 | |||
1238 | return $response; |
||
1239 | } |
||
1240 | |||
1241 | $body = $action->call($this, $this->_getNode($id, $p)); |
||
1242 | $response = (new Response())->setCode($body['status']); |
||
1243 | |||
1244 | if (isset($body['data'])) { |
||
1245 | $response->setBody([ |
||
1246 | 'status' => $body['status'], |
||
1247 | 'data' => $body['data'], |
||
1248 | ]); |
||
1249 | } |
||
1250 | |||
1251 | return $response; |
||
1252 | } |
||
1253 | |||
1254 | /** |
||
1255 | * Get node. |
||
1256 | * |
||
1257 | * @param string $id |
||
1258 | * @param string $path |
||
1259 | * @param string $class Force set node type |
||
1260 | * @param bool $multiple Allow $id to be an array |
||
1261 | * @param bool $allow_root Allow instance of root collection |
||
1262 | * @param bool $deleted How to handle deleted node |
||
1263 | */ |
||
1264 | protected function _getNode( |
||
1265 | ?string $id = null, |
||
1266 | ?string $path = null, |
||
1267 | ?string $class = null, |
||
1268 | bool $multiple = false, |
||
1269 | bool $allow_root = false, |
||
1270 | int $deleted = 2 |
||
1271 | ): NodeInterface { |
||
1272 | if (null === $class) { |
||
1273 | switch (get_class($this)) { |
||
1274 | case ApiFile::class: |
||
1275 | $class = File::class; |
||
1276 | |||
1277 | break; |
||
1278 | case ApiCollection::class: |
||
1279 | $class = Collection::class; |
||
1280 | |||
1281 | break; |
||
1282 | } |
||
1283 | } |
||
1284 | |||
1285 | return $this->fs->getNode($id, $path, $class, $multiple, $allow_root, $deleted); |
||
1286 | } |
||
1287 | |||
1288 | /** |
||
1289 | * Get nodes. |
||
1290 | * |
||
1291 | * @param string $id |
||
1292 | * @param string $path |
||
1293 | * @param string $class Force set node type |
||
1294 | * @param bool $deleted How to handle deleted node |
||
1295 | */ |
||
1296 | protected function _getNodes( |
||
1297 | $id = null, |
||
1298 | $path = null, |
||
1299 | ?string $class = null, |
||
1300 | int $deleted = 2 |
||
1301 | ): Generator { |
||
1302 | if (null === $class) { |
||
1303 | switch (get_class($this)) { |
||
1304 | case ApiFile::class: |
||
1305 | $class = File::class; |
||
1306 | |||
1307 | break; |
||
1308 | case ApiCollection::class: |
||
1309 | $class = Collection::class; |
||
1310 | |||
1311 | break; |
||
1312 | } |
||
1313 | } |
||
1314 | |||
1315 | return $this->fs->getNodes($id, $path, $class, $deleted); |
||
1316 | } |
||
1317 | |||
1318 | /** |
||
1319 | * Merge multiple nodes into one zip archive. |
||
1320 | * |
||
1321 | * @param string $id |
||
1322 | * @param string $path |
||
1323 | */ |
||
1324 | protected function combine($id = null, $path = null, string $name = 'selected') |
||
1325 | { |
||
1326 | $archive = new ZipStream($name.'.zip'); |
||
1327 | |||
1328 | foreach ($this->_getNodes($id, $path) as $node) { |
||
1329 | try { |
||
1330 | $node->zip($archive); |
||
1331 | } catch (\Exception $e) { |
||
1332 | $this->logger->debug('failed zip node in multi node request ['.$node->getId().']', [ |
||
1333 | 'category' => get_class($this), |
||
1334 | 'exception' => $e, |
||
1335 | ]); |
||
1336 | } |
||
1337 | } |
||
1338 | |||
1339 | $archive->finish(); |
||
1340 | } |
||
1341 | |||
1342 | /** |
||
1343 | * Check custom node attributes which have to be written. |
||
1344 | */ |
||
1345 | protected function _verifyAttributes(array $attributes): array |
||
1346 | { |
||
1347 | $valid_attributes = [ |
||
1348 | 'changed', |
||
1349 | 'destroy', |
||
1350 | 'created', |
||
1351 | 'meta', |
||
1352 | 'readonly', |
||
1353 | ]; |
||
1354 | |||
1355 | if ($this instanceof ApiCollection) { |
||
1356 | $valid_attributes[] = 'filter'; |
||
1357 | } |
||
1358 | |||
1359 | $check = array_merge(array_flip($valid_attributes), $attributes); |
||
1360 | |||
1361 | if ($this instanceof ApiCollection && count($check) > 6) { |
||
1362 | throw new Exception\InvalidArgument('Only changed, created, destroy timestamp, filter, readonly and/or meta attributes may be overwritten'); |
||
1363 | } |
||
1364 | if ($this instanceof ApiFile && count($check) > 5) { |
||
1365 | throw new Exception\InvalidArgument('Only changed, created, destroy timestamp, readonly and/or meta attributes may be overwritten'); |
||
1366 | } |
||
1367 | |||
1368 | foreach ($attributes as $attribute => $value) { |
||
1369 | switch ($attribute) { |
||
1370 | case 'filter': |
||
1371 | $attributes['filter'] = json_encode((array) $attributes['filter']); |
||
1372 | |||
1373 | break; |
||
1374 | case 'destroy': |
||
1375 | if (!Helper::isValidTimestamp($value)) { |
||
1376 | throw new Exception\InvalidArgument($attribute.' Changed timestamp must be valid unix timestamp'); |
||
1377 | } |
||
1378 | $attributes[$attribute] = new UTCDateTime($value.'000'); |
||
1379 | |||
1380 | break; |
||
1381 | case 'changed': |
||
1382 | case 'created': |
||
1383 | if (!Helper::isValidTimestamp($value)) { |
||
1384 | throw new Exception\InvalidArgument($attribute.' Changed timestamp must be valid unix timestamp'); |
||
1385 | } |
||
1386 | if ((int) $value > time()) { |
||
1387 | throw new Exception\InvalidArgument($attribute.' timestamp can not be set greater than the server time'); |
||
1388 | } |
||
1389 | $attributes[$attribute] = new UTCDateTime($value.'000'); |
||
1390 | |||
1391 | break; |
||
1392 | case 'readonly': |
||
1393 | $attributes['readonly'] = (bool) $attributes['readonly']; |
||
1394 | |||
1395 | break; |
||
1396 | } |
||
1397 | } |
||
1398 | |||
1399 | return $attributes; |
||
1400 | } |
||
1401 | } |
||
1402 |
Let’s assume that you have a directory layout like this:
and let’s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/Foo.php
are loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as
OtherDir/Foo.php
does not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php
, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: