Completed
Push — master ( f0fe3a...13ea99 )
by Andreas
12s
created

DocumentRepository::find()   B

Complexity

Conditions 10
Paths 22

Size

Total Lines 48

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 20.9421

Importance

Changes 0
Metric Value
dl 0
loc 48
ccs 12
cts 23
cp 0.5217
rs 7.2678
c 0
b 0
f 0
cc 10
nc 22
nop 3
crap 20.9421

How to fix   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
namespace Doctrine\ODM\MongoDB\Repository;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\Common\Collections\Collection;
9
use Doctrine\Common\Collections\Criteria;
10
use Doctrine\Common\Collections\Selectable;
11
use Doctrine\Common\Persistence\ObjectRepository;
12
use Doctrine\ODM\MongoDB\Aggregation\Builder as AggregationBuilder;
13
use Doctrine\ODM\MongoDB\DocumentManager;
14
use Doctrine\ODM\MongoDB\LockException;
15
use Doctrine\ODM\MongoDB\LockMode;
16
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
17
use Doctrine\ODM\MongoDB\Mapping\MappingException;
18
use Doctrine\ODM\MongoDB\Query\Builder as QueryBuilder;
19
use Doctrine\ODM\MongoDB\Query\QueryExpressionVisitor;
20
use Doctrine\ODM\MongoDB\UnitOfWork;
21
use function is_array;
22
23
/**
24
 * A DocumentRepository serves as a repository for documents with generic as well as
25
 * business specific methods for retrieving documents.
26
 *
27
 * This class is designed for inheritance and users can subclass this class to
28
 * write their own repositories with business-specific methods to locate documents.
29
 *
30
 */
31
class DocumentRepository implements ObjectRepository, Selectable
32
{
33
    /** @var string */
34
    protected $documentName;
35
36
    /** @var DocumentManager */
37
    protected $dm;
38
39
    /** @var UnitOfWork */
40
    protected $uow;
41
42
    /** @var ClassMetadata */
43
    protected $class;
44
45
    /**
46
     * Initializes this instance with the specified document manager, unit of work and
47
     * class metadata.
48
     *
49
     * @param DocumentManager $dm            The DocumentManager to use.
50
     * @param UnitOfWork      $uow           The UnitOfWork to use.
51
     * @param ClassMetadata   $classMetadata The class metadata.
52
     */
53 336
    public function __construct(DocumentManager $dm, UnitOfWork $uow, ClassMetadata $classMetadata)
54
    {
55 336
        $this->documentName = $classMetadata->name;
56 336
        $this->dm = $dm;
57 336
        $this->uow = $uow;
58 336
        $this->class = $classMetadata;
59 336
    }
60
61
    /**
62
     * Creates a new Query\Builder instance that is preconfigured for this document name.
63
     *
64
     * @return QueryBuilder $qb
65
     */
66 16
    public function createQueryBuilder()
67
    {
68 16
        return $this->dm->createQueryBuilder($this->documentName);
69
    }
70
71
    /**
72
     * Creates a new Aggregation\Builder instance that is prepopulated for this document name.
73
     *
74
     * @return AggregationBuilder
75
     */
76
    public function createAggregationBuilder()
77
    {
78
        return $this->dm->createAggregationBuilder($this->documentName);
79
    }
80
81
    /**
82
     * Clears the repository, causing all managed documents to become detached.
83
     */
84
    public function clear()
85
    {
86
        $this->dm->clear($this->class->rootDocumentName);
87
    }
88
89
    /**
90
     * Finds a document matching the specified identifier. Optionally a lock mode and
91
     * expected version may be specified.
92
     *
93
     * @param mixed $id          Identifier.
94
     * @param int   $lockMode    Optional. Lock mode; one of the LockMode constants.
95
     * @param int   $lockVersion Optional. Expected version.
96
     * @throws MappingException
97
     * @throws LockException
98
     * @return object|null The document, if found, otherwise null.
99
     */
100 234
    public function find($id, $lockMode = LockMode::NONE, $lockVersion = null)
101
    {
102 234
        if ($id === null) {
103
            return null;
104
        }
105
106
        /* TODO: What if the ID object has a field with the same name as the
107
         * class' mapped identifier field name?
108
         */
109 234
        if (is_array($id)) {
110 2
            list($identifierFieldName) = $this->class->getIdentifierFieldNames();
111
112 2
            if (isset($id[$identifierFieldName])) {
113
                $id = $id[$identifierFieldName];
114
            }
115
        }
116
117
        // Check identity map first
118 234
        $document = $this->uow->tryGetById($id, $this->class);
119 234
        if ($document) {
120 21
            if ($lockMode !== LockMode::NONE) {
121
                $this->dm->lock($document, $lockMode, $lockVersion);
122
            }
123
124 21
            return $document; // Hit!
125
        }
126
127 228
        $criteria = ['_id' => $id];
128
129 228
        if ($lockMode === LockMode::NONE) {
130 228
            return $this->getDocumentPersister()->load($criteria);
131
        }
132
133
        if ($lockMode === LockMode::OPTIMISTIC) {
134
            if (! $this->class->isVersioned) {
135
                throw LockException::notVersioned($this->documentName);
136
            }
137
138
            $document = $this->getDocumentPersister()->load($criteria);
139
            if ($document) {
140
                $this->uow->lock($document, $lockMode, $lockVersion);
141
            }
142
143
            return $document;
144
        }
145
146
        return $this->getDocumentPersister()->load($criteria, null, [], $lockMode);
147
    }
148
149
    /**
150
     * Finds all documents in the repository.
151
     *
152
     * @return array
153
     */
154 10
    public function findAll()
155
    {
156 10
        return $this->findBy([]);
157
    }
158
159
    /**
160
     * Finds documents by a set of criteria.
161
     *
162
     * @param array    $criteria Query criteria
163
     * @param array    $sort     Sort array for Cursor::sort()
164
     * @param int|null $limit    Limit for Cursor::limit()
165
     * @param int|null $skip     Skip for Cursor::skip()
166
     *
167
     * @return array
168
     */
169 11
    public function findBy(array $criteria, ?array $sort = null, $limit = null, $skip = null)
170
    {
171 11
        return $this->getDocumentPersister()->loadAll($criteria, $sort, $limit, $skip)->toArray(false);
0 ignored issues
show
Unused Code introduced by
The call to Iterator::toArray() has too many arguments starting with false.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
172
    }
173
174
    /**
175
     * Finds a single document by a set of criteria.
176
     *
177
     * @param array $criteria
178
     * @return object
179
     */
180 79
    public function findOneBy(array $criteria)
181
    {
182 79
        return $this->getDocumentPersister()->load($criteria);
183
    }
184
185
    /**
186
     * @return string
187
     */
188 8
    public function getDocumentName()
189
    {
190 8
        return $this->documentName;
191
    }
192
193
    /**
194
     * @return DocumentManager
195
     */
196
    public function getDocumentManager()
197
    {
198
        return $this->dm;
199
    }
200
201
    /**
202
     * @return ClassMetadata
203
     */
204
    public function getClassMetadata()
205
    {
206
        return $this->class;
207
    }
208
209
    /**
210
     * @return string
211
     */
212 8
    public function getClassName()
213
    {
214 8
        return $this->getDocumentName();
215
    }
216
217
    /**
218
     * Selects all elements from a selectable that match the expression and
219
     * returns a new collection containing these elements.
220
     *
221
     * @see Selectable::matching()
222
     * @return Collection
223
     */
224 4
    public function matching(Criteria $criteria)
225
    {
226 4
        $visitor = new QueryExpressionVisitor($this->createQueryBuilder());
227 4
        $queryBuilder = $this->createQueryBuilder();
228
229 4
        if ($criteria->getWhereExpression() !== null) {
230 1
            $expr = $visitor->dispatch($criteria->getWhereExpression());
231 1
            $queryBuilder->setQueryArray($expr->getQuery());
232
        }
233
234 4
        if ($criteria->getMaxResults() !== null) {
235
            $queryBuilder->limit($criteria->getMaxResults());
236
        }
237
238 4
        if ($criteria->getFirstResult() !== null) {
239
            $queryBuilder->skip($criteria->getFirstResult());
240
        }
241
242 4
        if ($criteria->getOrderings() !== null) {
243 4
            $queryBuilder->sort($criteria->getOrderings());
244
        }
245
246
        // @TODO: wrap around a specialized Collection for efficient count on large collections
247 4
        return new ArrayCollection($queryBuilder->getQuery()->execute()->toArray());
248
    }
249
250 315
    protected function getDocumentPersister()
251
    {
252 315
        return $this->uow->getDocumentPersister($this->documentName);
253
    }
254
}
255