Completed
Push — master ( 519f76...318dd5 )
by Raffael
24:13 queued 15:29
created

Factory::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 2
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\DataObject;
13
14
use Generator;
15
use MongoDB\BSON\ObjectId;
16
use MongoDB\BSON\ObjectIdInterface;
17
use MongoDB\Database;
18
use Psr\Log\LoggerInterface;
19
use Tubee\Collection\CollectionInterface;
20
use Tubee\DataObject;
21
use Tubee\DataObjectRelation\Factory as DataObjectRelationFactory;
22
use Tubee\Resource\Factory as ResourceFactory;
23
24
class Factory
25
{
26
    /**
27
     * Database.
28
     *
29
     * @var Database
30
     */
31
    protected $db;
32
33
    /**
34
     * Resource factory.
35
     *
36
     * @var ResourceFactory
37
     */
38
    protected $resource_factory;
39
40
    /**
41
     * Data object relation factory.
42
     *
43
     * @var DataObjectRelationFactory
44
     */
45
    protected $relation_factory;
46
47
    /**
48
     * Logger.
49
     *
50
     * @var LoggerInterface
51
     */
52
    protected $logger;
53
54
    /**
55
     * Initialize.
56
     */
57
    public function __construct(Database $db, ResourceFactory $resource_factory, DataObjectRelationFactory $relation_factory, LoggerInterface $logger)
58
    {
59
        $this->db = $db;
60
        $this->resource_factory = $resource_factory;
61
        $this->relation_factory = $relation_factory;
62
        $this->logger = $logger;
63
    }
64
65
    /**
66
     * Count objects.
67
     */
68
    public function count(CollectionInterface $collection, array $query = []): int
69
    {
70
        return $this->db->{$collection->getCollection()}->count($query);
71
    }
72
73
    /**
74
     * /**
75
     * Has object.
76
     */
77
    public function has(CollectionInterface $collection, string $name): bool
78
    {
79
        return $this->db->{$collection->getCollection()}->count([
80
            'name' => $name,
81
        ]) > 0;
82
    }
83
84
    /**
85
     * Get object history.
86
     */
87
    public function getObjectHistory(CollectionInterface $collection, ObjectIdInterface $id, ?array $filter = null, ?int $offset = null, ?int $limit = null): Generator
88
    {
89
        $pipeline = [
90
            ['$match' => ['_id' => $id]],
91
            ['$unwind' => '$history'],
92
        ];
93
94
        $count = $pipeline;
95
96
        if ($filter !== null) {
97
            $pipeline[] = ['$match' => $filter];
98
        }
99
100
        if ($offset !== null) {
101
            $pipeline[] = ['$skip' => $offset];
102
        }
103
104
        if ($limit !== null) {
105
            $pipeline[] = ['$limit' => $limit];
106
        }
107
108
        $current = $this->getOne($collection, ['_id' => $id]);
109
        yield $current;
110
111
        foreach ($this->db->{$collection->getCollection()}->aggregate($pipeline) as $version) {
112
            yield $version['version'] => $this->build(array_merge($current->toArray(), $version['history']), $collection);
113
        }
114
115
        $count[] = ['$count' => 'count'];
116
117
        return 1;
118
    }
119
120
    /**
121
     * Get one.
122
     */
123
    public function getOne(CollectionInterface $collection, array $filter, bool $include_dataset = true, int $version = 0): DataObjectInterface
0 ignored issues
show
Unused Code introduced by
The parameter $include_dataset 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...
Unused Code introduced by
The parameter $version 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...
124
    {
125
        $this->logger->debug('find one object with query [{query}] from ['.$collection->getCollection().']', [
126
            'category' => get_class($this),
127
            'query' => json_encode($filter),
128
        ]);
129
130
        $cursor = $this->db->{$collection->getCollection()}->find($filter, [
131
            'projection' => ['history' => 0],
132
        ]);
133
134
        $objects = iterator_to_array($cursor);
135
136
        if (count($objects) === 0) {
137
            throw new Exception\NotFound('data object '.json_encode($filter).' not found in collection '.$collection->getCollection());
138
        }
139
        if (count($objects) > 1) {
140
            throw new Exception\MultipleFound('multiple data objects found with filter '.json_encode($filter).' in collection '.$collection->getCollection());
141
        }
142
143
        return $this->build(array_shift($objects), $collection);
144
    }
145
146
    /**
147
     * Get all.
148
     */
149
    public function getAll(CollectionInterface $collection, ?array $query = null, bool $include_dataset = true, ?int $offset = 0, ?int $limit = 0, ?array $sort = null): Generator
0 ignored issues
show
Unused Code introduced by
The parameter $include_dataset 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...
150
    {
151
        $that = $this;
152
153
        return $this->resource_factory->getAllFrom($this->db->{$collection->getCollection()}, $query, $offset, $limit, $sort, function (array $resource) use ($collection, $that) {
154
            return $that->build($resource, $collection);
155
        });
156
    }
157
158
    /**
159
     * Create.
160
     */
161
    public function create(CollectionInterface $collection, array $object, bool $simulate = false, ?array $endpoints = null): ObjectIdInterface
162
    {
163
        $collection->getSchema()->validate((array) $object['data']);
164
165
        $object['_id'] = new ObjectId();
166
167
        if (!isset($object['name'])) {
168
            $object['name'] = (string) $object['_id'];
169
        }
170
171
        if ($this->has($collection, $object['name'])) {
172
            throw new Exception\NotUnique('data object '.$object['name'].' does already exists');
173
        }
174
175
        $object = [
176
            '_id' => $object['_id'],
177
            'name' => $object['name'],
178
            'data' => $object['data'],
179
            'endpoints' => $endpoints,
180
        ];
181
182
        return $this->resource_factory->addTo($this->db->{$collection->getCollection()}, $object, $simulate);
183
    }
184
185
    /**
186
     * Update.
187
     */
188
    public function update(CollectionInterface $collection, DataObjectInterface $object, array $data, bool $simulate = false, ?array $endpoints = null): bool
189
    {
190
        $collection->getSchema()->validate((array) $data['data']);
191
192
        if ($endpoints !== null) {
193
            $existing = $object->getEndpoints();
194
            $data['endpoints'] = array_replace_recursive($existing, $endpoints);
195
        }
196
197
        return $this->resource_factory->updateIn($this->db->{$collection->getCollection()}, $object, $data, $simulate);
198
    }
199
200
    /**
201
     * Delete one.
202
     */
203
    public function deleteOne(CollectionInterface $collection, string $name, bool $simulate = false): bool
204
    {
205
        $resource = $this->getOne($collection, ['name' => $name]);
206
207
        return $this->resource_factory->deleteFrom($this->db->{$collection->getCollection()}, $resource->getId(), $simulate);
208
    }
209
210
    /**
211
     * Delete all.
212
     */
213
    public function deleteAll(CollectionInterface $collection, bool $simulate = false): bool
214
    {
215
        $this->logger->info('flush collection ['.$collection->getIdentifier().']', [
216
            'category' => get_class($this),
217
        ]);
218
219
        if ($simulate === false) {
220
            $this->db->{$collection->getCollection()}->deleteMany([]);
221
        }
222
223
        return true;
224
    }
225
226
    /**
227
     * Change stream.
228
     */
229
    public function watch(CollectionInterface $collection, ?ObjectIdInterface $after = null, bool $existing = true, ?array $query = null, ?int $offset = null, ?int $limit = null, ?array $sort = null): Generator
230
    {
231
        $that = $this;
232
233
        return $this->resource_factory->watchFrom($this->db->{$collection->getCollection()}, $after, $existing, $query, function (array $resource) use ($collection, $that) {
234
            return $that->build($resource, $collection);
235
        }, $offset, $limit, $sort);
236
    }
237
238
    /**
239
     * Build.
240
     */
241
    public function build(array $resource, CollectionInterface $collection): DataObjectInterface
242
    {
243
        return $this->resource_factory->initResource(new DataObject($resource, $collection, $this->relation_factory));
244
    }
245
}
246