Completed
Pull Request — master (#1749)
by Gabriel
23:17 queued 21:08
created

DocumentRepository::find()   C

Complexity

Conditions 10
Paths 22

Size

Total Lines 48
Code Lines 23

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 5.3454
c 0
b 0
f 0
cc 10
eloc 23
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;
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\Mapping\ClassMetadata;
13
use Doctrine\ODM\MongoDB\Query\QueryExpressionVisitor;
14
use function is_array;
15
16
/**
17
 * A DocumentRepository serves as a repository for documents with generic as well as
18
 * business specific methods for retrieving documents.
19
 *
20
 * This class is designed for inheritance and users can subclass this class to
21
 * write their own repositories with business-specific methods to locate documents.
22
 *
23
 */
24
class DocumentRepository implements ObjectRepository, Selectable
25
{
26
    /** @var string */
27
    protected $documentName;
28
29
    /** @var DocumentManager */
30
    protected $dm;
31
32
    /** @var UnitOfWork */
33
    protected $uow;
34
35
    /** @var ClassMetadata */
36
    protected $class;
37
38
    /**
39
     * Initializes this instance with the specified document manager, unit of work and
40
     * class metadata.
41
     *
42
     * @param DocumentManager $dm            The DocumentManager to use.
43
     * @param UnitOfWork      $uow           The UnitOfWork to use.
44
     * @param ClassMetadata   $classMetadata The class metadata.
45
     */
46 324
    public function __construct(DocumentManager $dm, UnitOfWork $uow, ClassMetadata $classMetadata)
47
    {
48 324
        $this->documentName = $classMetadata->name;
49 324
        $this->dm = $dm;
50 324
        $this->uow = $uow;
51 324
        $this->class = $classMetadata;
52 324
    }
53
54
    /**
55
     * Creates a new Query\Builder instance that is preconfigured for this document name.
56
     *
57
     * @return Query\Builder $qb
58
     */
59 16
    public function createQueryBuilder()
60
    {
61 16
        return $this->dm->createQueryBuilder($this->documentName);
62
    }
63
64
    /**
65
     * Creates a new Aggregation\Builder instance that is prepopulated for this document name.
66
     *
67
     * @return Aggregation\Builder
68
     */
69
    public function createAggregationBuilder()
70
    {
71
        return $this->dm->createAggregationBuilder($this->documentName);
72
    }
73
74
    /**
75
     * Clears the repository, causing all managed documents to become detached.
76
     */
77
    public function clear()
78
    {
79
        $this->dm->clear($this->class->rootDocumentName);
80
    }
81
82
    /**
83
     * Finds a document matching the specified identifier. Optionally a lock mode and
84
     * expected version may be specified.
85
     *
86
     * @param mixed $id          Identifier.
87
     * @param int   $lockMode    Optional. Lock mode; one of the LockMode constants.
88
     * @param int   $lockVersion Optional. Expected version.
89
     * @throws Mapping\MappingException
90
     * @throws LockException
91
     * @return object|null The document, if found, otherwise null.
92
     */
93 230
    public function find($id, $lockMode = LockMode::NONE, $lockVersion = null)
94
    {
95 230
        if ($id === null) {
96
            return null;
97
        }
98
99
        /* TODO: What if the ID object has a field with the same name as the
100
         * class' mapped identifier field name?
101
         */
102 230
        if (is_array($id)) {
103 2
            list($identifierFieldName) = $this->class->getIdentifierFieldNames();
104
105 2
            if (isset($id[$identifierFieldName])) {
106
                $id = $id[$identifierFieldName];
107
            }
108
        }
109
110
        // Check identity map first
111 230
        $document = $this->uow->tryGetById($id, $this->class);
112 230
        if ($document) {
113 21
            if ($lockMode !== LockMode::NONE) {
114
                $this->dm->lock($document, $lockMode, $lockVersion);
115
            }
116
117 21
            return $document; // Hit!
118
        }
119
120 224
        $criteria = ['_id' => $id];
121
122 224
        if ($lockMode === LockMode::NONE) {
123 224
            return $this->getDocumentPersister()->load($criteria);
124
        }
125
126
        if ($lockMode === LockMode::OPTIMISTIC) {
127
            if (! $this->class->isVersioned) {
128
                throw LockException::notVersioned($this->documentName);
129
            }
130
131
            $document = $this->getDocumentPersister()->load($criteria);
132
            if ($document) {
133
                $this->uow->lock($document, $lockMode, $lockVersion);
134
            }
135
136
            return $document;
137
        }
138
139
        return $this->getDocumentPersister()->load($criteria, null, [], $lockMode);
140
    }
141
142
    /**
143
     * Finds all documents in the repository.
144
     *
145
     * @return array
146
     */
147 10
    public function findAll()
148
    {
149 10
        return $this->findBy([]);
150
    }
151
152
    /**
153
     * Finds documents by a set of criteria.
154
     *
155
     * @param array    $criteria Query criteria
156
     * @param array    $sort     Sort array for Cursor::sort()
157
     * @param int|null $limit    Limit for Cursor::limit()
158
     * @param int|null $skip     Skip for Cursor::skip()
159
     *
160
     * @return array
161
     */
162 11
    public function findBy(array $criteria, ?array $sort = null, $limit = null, $skip = null)
163
    {
164 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...
165
    }
166
167
    /**
168
     * Finds a single document by a set of criteria.
169
     *
170
     * @param array $criteria
171
     * @return object
172
     */
173 74
    public function findOneBy(array $criteria)
174
    {
175 74
        return $this->getDocumentPersister()->load($criteria);
176
    }
177
178
    /**
179
     * @return string
180
     */
181
    public function getDocumentName()
182
    {
183
        return $this->documentName;
184
    }
185
186
    /**
187
     * @return DocumentManager
188
     */
189
    public function getDocumentManager()
190
    {
191
        return $this->dm;
192
    }
193
194
    /**
195
     * @return Mapping\ClassMetadata
196
     */
197
    public function getClassMetadata()
198
    {
199
        return $this->class;
200
    }
201
202
    /**
203
     * @return string
204
     */
205
    public function getClassName()
206
    {
207
        return $this->getDocumentName();
208
    }
209
210
    /**
211
     * Selects all elements from a selectable that match the expression and
212
     * returns a new collection containing these elements.
213
     *
214
     * @see Selectable::matching()
215
     * @return Collection
216
     */
217 4
    public function matching(Criteria $criteria)
218
    {
219 4
        $visitor = new QueryExpressionVisitor($this->createQueryBuilder());
220 4
        $queryBuilder = $this->createQueryBuilder();
221
222 4
        if ($criteria->getWhereExpression() !== null) {
223 1
            $expr = $visitor->dispatch($criteria->getWhereExpression());
224 1
            $queryBuilder->setQueryArray($expr->getQuery());
225
        }
226
227 4
        if ($criteria->getMaxResults() !== null) {
228
            $queryBuilder->limit($criteria->getMaxResults());
229
        }
230
231 4
        if ($criteria->getFirstResult() !== null) {
232
            $queryBuilder->skip($criteria->getFirstResult());
233
        }
234
235 4
        if ($criteria->getOrderings() !== null) {
236 4
            $queryBuilder->sort($criteria->getOrderings());
237
        }
238
239
        // @TODO: wrap around a specialized Collection for efficient count on large collections
240 4
        return new ArrayCollection($queryBuilder->getQuery()->execute()->toArray());
241
    }
242
243 306
    protected function getDocumentPersister()
244
    {
245 306
        return $this->uow->getDocumentPersister($this->documentName);
246
    }
247
}
248