Completed
Push — master ( e50616...a5acb0 )
by Raffael
28:40 queued 24:37
created

Factory::createOrUpdate()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 58

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 58
ccs 0
cts 51
cp 0
rs 8.9163
c 0
b 0
f 0
cc 3
nc 4
nop 5
crap 12

How to fix   Long Method   

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
 * tubee
7
 *
8
 * @copyright   Copryright (c) 2017-2019 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Tubee\DataObjectRelation;
13
14
use Generator;
15
use MongoDB\BSON\ObjectId;
16
use MongoDB\BSON\ObjectIdInterface;
17
use Tubee\DataObject\DataObjectInterface;
18
use Tubee\DataObjectRelation;
19
use Tubee\Resource\Factory as ResourceFactory;
20
use Tubee\ResourceNamespace\ResourceNamespaceInterface;
21
22
class Factory extends ResourceFactory
23
{
24
    /**
25
     * Collection name.
26
     */
27
    public const COLLECTION_NAME = 'relations';
28
29
    /**
30
     * Has resource.
31
     */
32
    public function has(ResourceNamespaceInterface $namespace, string $name): bool
33
    {
34
        return $this->db->{self::COLLECTION_NAME}->count([
35
            'namespace' => $namespace->getName(),
36
            'name' => $name,
37
        ]) > 0;
38
    }
39
40
    /**
41
     * Get one.
42
     */
43
    public function getOne(ResourceNamespaceInterface $namespace, string $name): DataObjectRelationInterface
44
    {
45
        $resource = $this->db->{self::COLLECTION_NAME}->findOne([
46
            'namespace' => $namespace->getName(),
47
            'name' => $name,
48
        ], [
49
            'projection' => ['history' => 0],
50
        ]);
51
52
        if ($resource === null) {
53
            throw new Exception\NotFound('relation '.$name.' was not found');
54
        }
55
56
        return $this->build($resource);
57
    }
58
59
    /**
60
     * Get one from object.
61
     */
62
    public function getOneFromObject(DataObjectInterface $object, string $name): DataObjectRelationInterface
63
    {
64
        $relation = [
65
            'namespace' => $object->getCollection()->getResourceNamespace()->getName(),
66
            'collection' => $object->getCollection()->getName(),
67
            'object' => $object->getName(),
68
        ];
69
70
        $filter = [
71
            'name' => $name,
72
            'data.relation.namespace' => $relation['namespace'],
73
            'data.relation.collection' => $relation['collection'],
74
            'data.relation.object' => $relation['object'],
75
        ];
76
77
        $resource = $this->db->{self::COLLECTION_NAME}->findOne($filter);
78
79
        if ($resource === null) {
80
            throw new Exception\NotFound('relation '.$name.' was not found');
81
        }
82
83
        $object_1 = array_shift($resource['data']['relation']);
84
        $object_2 = array_shift($resource['data']['relation']);
85
        $related = $object_1;
86
87
        if ($object_1 == $relation) {
88
            $related = $object_2;
89
        }
90
91
        $related = $object->getCollection()->getResourceNamespace()->switch($related['namespace'])->getCollection($related['collection'])->getObject(['name' => $related['object']]);
92
93
        return $this->build($resource, $related);
94
    }
95
96
    /**
97
     * Get all from object.
98
     */
99
    public function getAllFromObject(DataObjectInterface $object, ?array $query = null, ?int $offset = null, ?int $limit = null, ?array $sort = null): Generator
100
    {
101
        $relation = [
102
            'namespace' => $object->getCollection()->getResourceNamespace()->getName(),
103
            'collection' => $object->getCollection()->getName(),
104
            'object' => $object->getName(),
105
        ];
106
107
        $filter = [
108
            'data.relation.namespace' => $relation['namespace'],
109
            'data.relation.collection' => $relation['collection'],
110
            'data.relation.object' => $relation['object'],
111
        ];
112
113
        if (!empty($query)) {
114
            $filter = [
115
                '$and' => [$filter, $query],
116
            ];
117
        }
118
119
        return $this->getAllFrom($this->db->{self::COLLECTION_NAME}, $filter, $offset, $limit, $sort, function (array $resource) use ($object, $relation) {
120
            $object_1 = $resource['data']['relation'][0];
121
            $object_2 = $resource['data']['relation'][1];
122
            $related = $object_1;
123
124
            if ($object_1 == $relation) {
125
                $related = $object_2;
126
            }
127
128
            $related = $object->getCollection()->getResourceNamespace()->switch($related['namespace'])->getCollection($related['collection'])->getObject(['name' => $related['object']]);
129
130
            return $this->build($resource, $related);
131
        });
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137
    public function getAll(ResourceNamespaceInterface $namespace, ?array $query = null, ?int $offset = null, ?int $limit = null, ?array $sort = null): Generator
138
    {
139
        $filter = [
140
            'namespace' => $namespace->getName(),
141
        ];
142
143
        if (!empty($query)) {
144
            $filter = [
145
                '$and' => [$filter, $query],
146
            ];
147
        }
148
149
        return $this->getAllFrom($this->db->{self::COLLECTION_NAME}, $filter, $offset, $limit, $sort, function (array $resource) {
150
            return $this->build($resource);
151
        });
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157
    public function deleteFromObject(DataObjectInterface $object_1, DataObjectInterface $object_2, bool $simulate = false): bool
0 ignored issues
show
Unused Code introduced by
The parameter $simulate 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...
158
    {
159
        $relations = [
160
            [
161
                'data.relation.namespace' => $object_1->getCollection()->getResourceNamespace()->getName(),
162
                'data.relation.collection' => $object_1->getCollection()->getName(),
163
                'data.relation.object' => $object_1->getName(),
164
            ], [
165
                'data.relation.namespace' => $object_2->getCollection()->getResourceNamespace()->getName(),
166
                'data.relation.collection' => $object_2->getCollection()->getName(),
167
                'data.relation.object' => $object_2->getName(),
168
            ],
169
        ];
170
171
        $this->db->{self::COLLECTION_NAME}->remove([
172
            '$and' => $relations,
173
        ]);
174
175
        return true;
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function createOrUpdate(DataObjectInterface $object_1, DataObjectInterface $object_2, array $context = [], bool $simulate = false, ?array $endpoints = null): ObjectIdInterface
0 ignored issues
show
Unused Code introduced by
The parameter $simulate 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...
182
    {
183
        $relations = [
184
            [
185
                'data.relation.namespace' => $object_1->getCollection()->getResourceNamespace()->getName(),
186
                'data.relation.collection' => $object_1->getCollection()->getName(),
187
                'data.relation.object' => $object_1->getName(),
188
            ], [
189
                'data.relation.namespace' => $object_2->getCollection()->getResourceNamespace()->getName(),
190
                'data.relation.collection' => $object_2->getCollection()->getName(),
191
                'data.relation.object' => $object_2->getName(),
192
            ],
193
        ];
194
195
        $name = new ObjectId();
196
        $resource = [
197
            '_id' => $name,
198
            'name' => (string) $name,
199
            'data' => [
200
                'relation' => [
201
                    [
202
                        'namespace' => $relations[0]['data.relation.namespace'],
203
                        'collection' => $relations[0]['data.relation.collection'],
204
                        'object' => $relations[0]['data.relation.object'],
205
                    ],
206
                    [
207
                        'namespace' => $relations[1]['data.relation.namespace'],
208
                        'collection' => $relations[1]['data.relation.collection'],
209
                        'object' => $relations[1]['data.relation.object'],
210
                    ],
211
                ],
212
                'context' => $context,
213
            ],
214
            'namespace' => $object_1->getCollection()->getResourceNamespace()->getName(),
215
        ];
216
217
        $exists = $this->db->{self::COLLECTION_NAME}->findOne([
218
            '$and' => $relations,
219
        ]);
220
221
        if ($endpoints !== null) {
222
            $resource['endpoints'] = $endpoints;
223
        }
224
225
        if ($exists !== null) {
226
            $data = [
227
                'data' => $exists['data'],
228
                'endpoints' => array_replace_recursive($exists['endpoints'], $endpoints),
229
            ];
230
231
            $exists = $this->build($exists);
232
            $this->updateIn($this->db->{self::COLLECTION_NAME}, $exists, $data);
233
234
            return $exists->getId();
235
        }
236
237
        return $this->addTo($this->db->{self::COLLECTION_NAME}, $resource);
238
    }
239
240
    /**
241
     * Add.
242
     */
243
    public function add(ResourceNamespaceInterface $namespace, array $resource): ObjectIdInterface
244
    {
245
        $resource['kind'] = 'DataObjectRelation';
246
        $resource = $this->validate($resource);
247
248
        $resource['_id'] = new ObjectId();
249
        if (!isset($resource['name'])) {
250
            $resource['name'] = (string) $resource['_id'];
251
        }
252
253
        if ($this->has($namespace, $resource['name'])) {
254
            throw new Exception\NotUnique('relation '.$resource['name'].' does already exists');
255
        }
256
257
        $resource['namespace'] = $namespace->getName();
258
259
        return $this->addTo($this->db->{self::COLLECTION_NAME}, $resource);
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265
    public function update(DataObjectRelationInterface $resource, array $data): bool
266
    {
267
        $data['name'] = $resource->getName();
268
        $data['kind'] = $resource->getKind();
269
        $data = $this->validate($data);
270
271
        return $this->updateIn($this->db->{self::COLLECTION_NAME}, $resource, $data);
272
    }
273
274
    /**
275
     * {@inheritdoc}
276
     */
277
    public function deleteOne(DataObjectRelationInterface $relation, bool $simulate = false): bool
0 ignored issues
show
Unused Code introduced by
The parameter $simulate 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...
278
    {
279
        $this->logger->info('delete object relation ['.$relation->getId()().'] from ['.self::COLLECTION_NAME.']', [
280
            'category' => get_class($this),
281
        ]);
282
283
        $this->db->{self::COLLECTION_NAME}->deleteOne(['_id' => $relation->getId()]);
284
285
        return true;
286
    }
287
288
    /**
289
     * Change stream.
290
     */
291
    public function watch(ResourceNamespaceInterface $namespace, ?ObjectIdInterface $after = null, bool $existing = true, ?array $query = null, ?int $offset = null, ?int $limit = null, ?array $sort = null): Generator
0 ignored issues
show
Unused Code introduced by
The parameter $namespace 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...
292
    {
293
        return $this->watchFrom($this->db->{self::COLLECTION_NAME}, $after, $existing, $query, function (array $resource) {
294
            return $this->build($resource);
295
        }, $offset, $limit, $sort);
296
    }
297
298
    /**
299
     * Build.
300
     */
301
    public function build(array $resource, ?DataObjectInterface $object = null): DataObjectRelationInterface
302
    {
303
        return $this->initResource(new DataObjectRelation($resource, $object));
304
    }
305
}
306