Completed
Push — master ( b97427...e235cc )
by Raffael
30:35 queued 26:08
created

AttributeDecorator::getAttributes()   D

Complexity

Conditions 16
Paths 1

Size

Total Lines 118

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 53
CRAP Score 25.8415

Importance

Changes 0
Metric Value
dl 0
loc 118
ccs 53
cts 80
cp 0.6625
rs 4.4532
c 0
b 0
f 0
cc 16
nc 1
nop 2
crap 25.8415

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
0 ignored issues
show
Unused Code introduced by
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...
228
    {
229
        return [
230 6
            'created' => function ($node) use ($attributes) {
0 ignored issues
show
Unused Code introduced by
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...
231 2
                return $attributes['created']->toDateTime()->format('c');
232 6
            },
233 6
            'changed' => function ($node) use ($attributes) {
0 ignored issues
show
Unused Code introduced by
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...
234 2
                return $attributes['changed']->toDateTime()->format('c');
235 6
            },
236 6
            'deleted' => function ($node) use ($attributes) {
0 ignored issues
show
Unused Code introduced by
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...
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) {
0 ignored issues
show
Unused Code introduced by
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...
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;
0 ignored issues
show
Unused Code introduced by
$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...
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) {
0 ignored issues
show
Unused Code introduced by
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...
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());
0 ignored issues
show
Bug introduced by
Consider using a different name than the imported variable $attributes, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

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...
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
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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