Completed
Push — master ( 287393...7ff50d )
by Raffael
18:27 queued 14:12
created

v1/AttributeDecorator/NodeDecorator.php (7 issues)

Upgrade to new PHP Analysis Engine

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\AttributeDecorator;
13
14
use Balloon\Filesystem;
15
use Balloon\Filesystem\Acl;
16
use Balloon\Filesystem\Node\Collection;
17
use Balloon\Filesystem\Node\File;
18
use Balloon\Filesystem\Node\NodeInterface;
19
use Balloon\Server;
20
use Closure;
21
use MongoDB\BSON\UTCDateTime;
22
use stdClass;
23
24
class NodeDecorator
25
{
26
    /**
27
     * Server.
28
     *
29
     * @var Server
30
     */
31
    protected $server;
32
33
    /**
34
     * Filesystem.
35
     *
36
     * @var Filesystem
37
     */
38
    protected $fs;
39
40
    /**
41
     * Acl.
42
     *
43
     * @var Acl
44
     */
45
    protected $acl;
46
47
    /**
48
     * Custom attributes.
49
     *
50
     * @var array
51
     */
52
    protected $custom = [];
53
54
    /**
55
     * Init.
56
     */
57
    public function __construct(Server $server, Acl $acl)
58
    {
59
        $this->server = $server;
60
        $this->acl = $acl;
61
    }
62
63
    /**
64
     * Decorate attributes.
65
     */
66
    public function decorate(NodeInterface $node, array $attributes = []): array
67
    {
68
        $requested = $this->parseAttributes($attributes);
69
        $attributes = $node->getAttributes();
70
71
        $attrs = array_merge(
72
            $this->getAttributes($node, $attributes),
73
            $this->getTimeAttributes($node, $attributes),
74
            $this->getTypeAttributes($node, $attributes),
75
            $this->custom
76
        );
77
78
        if (0 === count($requested)) {
79
            return $this->translateAttributes($node, $attrs);
80
        }
81
82
        return $this->translateAttributes($node, array_intersect_key($attrs, array_flip($requested)));
83
    }
84
85
    /**
86
     * Add decorator.
87
     *
88
     *
89
     * @return AttributeDecorator
90
     */
91
    public function addDecorator(string $attribute, Closure $decorator): self
92
    {
93
        $this->custom[$attribute] = $decorator;
94
95
        return $this;
96
    }
97
98
    /**
99
     * Parse v1 attribute filter requests.
100
     *
101
     * @param array
102
     */
103
    protected function parseAttributes(array $attributes): array
104
    {
105
        foreach ($attributes as &$attribute) {
106
            $parts = explode('.', $attribute);
107
            $attribute = $parts[0];
108
        }
109
110
        return $attributes;
111
    }
112
113
    /**
114
     * Get Attributes.
115
     */
116
    protected function getAttributes(NodeInterface $node, array $attributes): array
117
    {
118
        $acl = $this->acl;
119
        $server = $this->server;
120
        $fs = $this->server->getFilesystem();
121
122
        return [
123
            'id' => (string) $attributes['_id'],
124
            'name' => (string) $attributes['name'],
125
            'mime' => (string) $attributes['mime'],
126
            'readonly' => (bool) $attributes['readonly'],
127
            'directory' => $node instanceof Collection,
128
            'meta' => function ($node) {
129
                return (object) $node->getMetaAttributes();
130
            },
131
            'size' => function ($node) {
132
                return $node->getSize();
133
            },
134
            'path' => function ($node) {
135
                try {
136
                    return $node->getPath();
137
                } catch (\Exception $e) {
138
                    return null;
139
                }
140
            },
141
            'parent' => function ($node) {
142
                $parent = $node->getParent();
143
144
                if (null === $parent || $parent->isRoot()) {
145
                    return null;
146
                }
147
148
                return (string) $parent->getId();
149
            },
150
            'access' => function ($node) use ($acl) {
151
                return $acl->getAclPrivilege($node);
152
            },
153
            'share' => function ($node) {
154
                if (!$node->isShared() && !$node->isSpecial()) {
155
                    return false;
156
                }
157
158
                try {
159
                    return $node->getShareNode()->getShareName();
160
                } catch (\Exception $e) {
161
                    return false;
162
                }
163
            },
164
            'shareowner' => function ($node) use ($server, $fs) {
165
                if (!$node->isSpecial()) {
166
                    return null;
167
                }
168
169
                try {
170
                    return $server->getUserById($fs->findRawNode($node->getShareId())['owner'])->getUsername();
171
                } catch (\Exception $e) {
172
                    return null;
173
                }
174
            },
175
        ];
176
    }
177
178
    /**
179
     * Convert UTCDateTime to unix ts.
180
     *
181
     * @param UTCDateTime $date
182
     *
183
     * @return stdClass
184
     */
185
    protected function dateTimeToUnix(?UTCDateTime $date): ?stdClass
186
    {
187
        if (null === $date) {
188
            return null;
189
        }
190
191
        $date = $date->toDateTime();
192
        $ts = new stdClass();
193
        $ts->sec = $date->format('U');
194
        $ts->usec = $date->format('u');
195
196
        return $ts;
197
    }
198
199
    /**
200
     * Get Attributes.
201
     *
202
     * @param NodeInterface
203
     */
204
    protected function getTimeAttributes(NodeInterface $node, array $attributes): array
0 ignored issues
show
The parameter $node is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
205
    {
206
        return [
207
            'created' => function ($node) use ($attributes) {
0 ignored issues
show
The parameter $node is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
208
                return $this->dateTimeToUnix($attributes['created']);
209
            },
210
            'changed' => function ($node) use ($attributes) {
0 ignored issues
show
The parameter $node is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
211
                return $this->dateTimeToUnix($attributes['changed']);
212
            },
213
            'deleted' => function ($node) use ($attributes) {
0 ignored issues
show
The parameter $node is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
214
                if (false === $attributes['deleted']) {
215
                    return false;
216
                }
217
218
                return $this->dateTimeToUnix($attributes['deleted']);
219
            },
220
            'destroy' => function ($node) use ($attributes) {
0 ignored issues
show
The parameter $node is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
221
                if (null === $attributes['destroy']) {
222
                    return null;
223
                }
224
225
                return $this->dateTimeToUnix($attributes['destroy']);
226
            },
227
        ];
228
    }
229
230
    /**
231
     * Get Attributes.
232
     *
233
     * @param NodeInterface
234
     */
235
    protected function getTypeAttributes(NodeInterface $node, array $attributes): array
236
    {
237
        $server = $this->server;
0 ignored issues
show
$server 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 $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
238
        $fs = $this->server->getFilesystem();
0 ignored issues
show
$fs 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 $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
239
240
        if ($node instanceof File) {
241
            return [
242
                'version' => $attributes['version'],
243
                'hash' => $attributes['hash'],
244
            ];
245
        }
246
247
        return [
248
            'shared' => $node->isShared(),
249
            'reference' => $node->isReference(),
250
            'filtered' => $node->isFiltered(),
251
        ];
252
    }
253
254
    /**
255
     * Execute closures.
256
     *
257
     * @param NodeInterface
258
     */
259
    protected function translateAttributes(NodeInterface $node, array $attributes): array
260
    {
261
        foreach ($attributes as $key => &$value) {
262
            if ($value instanceof Closure) {
263
                $result = $value->call($this, $node);
264
                if ($result === null && $key !== 'destroy') {
265
                    unset($attributes[$key]);
266
                } else {
267
                    $value = $result;
268
                }
269
            }
270
        }
271
272
        return $attributes;
273
    }
274
}
275