Completed
Pull Request — master (#1803)
by Andreas
16:48 queued 09:05
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\Criteria;
9
use Doctrine\Common\Collections\Selectable;
10
use Doctrine\Common\Persistence\ObjectRepository;
11
use Doctrine\ODM\MongoDB\Aggregation\Builder as AggregationBuilder;
12
use Doctrine\ODM\MongoDB\DocumentManager;
13
use Doctrine\ODM\MongoDB\Iterator\Iterator;
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\Persisters\DocumentPersister;
19
use Doctrine\ODM\MongoDB\Query\Builder as QueryBuilder;
20
use Doctrine\ODM\MongoDB\Query\QueryExpressionVisitor;
21
use Doctrine\ODM\MongoDB\UnitOfWork;
22
use function assert;
23
use function count;
24
use function is_array;
25
26
/**
27
 * A DocumentRepository serves as a repository for documents with generic as well as
28
 * business specific methods for retrieving documents.
29
 *
30
 * This class is designed for inheritance and users can subclass this class to
31
 * write their own repositories with business-specific methods to locate documents.
32
 */
33
class DocumentRepository implements ObjectRepository, Selectable
34
{
35
    /** @var string */
36
    protected $documentName;
37
38
    /** @var DocumentManager */
39
    protected $dm;
40
41
    /** @var UnitOfWork */
42
    protected $uow;
43
44
    /** @var ClassMetadata */
45
    protected $class;
46
47
    /**
48
     * Initializes this instance with the specified document manager, unit of work and
49
     * class metadata.
50
     *
51
     * @param DocumentManager $dm            The DocumentManager to use.
52
     * @param UnitOfWork      $uow           The UnitOfWork to use.
53
     * @param ClassMetadata   $classMetadata The class metadata.
54
     */
55 350
    public function __construct(DocumentManager $dm, UnitOfWork $uow, ClassMetadata $classMetadata)
56
    {
57 350
        $this->documentName = $classMetadata->name;
58 350
        $this->dm           = $dm;
59 350
        $this->uow          = $uow;
60 350
        $this->class        = $classMetadata;
61 350
    }
62
63
    /**
64
     * Creates a new Query\Builder instance that is preconfigured for this document name.
65
     */
66 15
    public function createQueryBuilder() : QueryBuilder
67
    {
68 15
        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
    public function createAggregationBuilder() : AggregationBuilder
75
    {
76
        return $this->dm->createAggregationBuilder($this->documentName);
77
    }
78
79
    /**
80
     * Clears the repository, causing all managed documents to become detached.
81
     */
82
    public function clear() : void
83
    {
84
        $this->dm->clear($this->class->rootDocumentName);
85
    }
86
87
    /**
88
     * Finds a document matching the specified identifier. Optionally a lock mode and
89
     * expected version may be specified.
90
     *
91
     * @param mixed $id Identifier.
92
     *
93
     * @throws MappingException
94
     * @throws LockException
95
     */
96 237
    public function find($id, int $lockMode = LockMode::NONE, ?int $lockVersion = null) : ?object
97
    {
98 237
        if ($id === null) {
99
            return null;
100
        }
101
102
        /* TODO: What if the ID object has a field with the same name as the
103
         * class' mapped identifier field name?
104
         */
105 237
        if (is_array($id)) {
106 2
            [$identifierFieldName] = $this->class->getIdentifierFieldNames();
0 ignored issues
show
Bug introduced by
The variable $identifierFieldName does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
107
108 2
            if (isset($id[$identifierFieldName])) {
109
                $id = $id[$identifierFieldName];
110
            }
111
        }
112
113
        // Check identity map first
114 237
        $document = $this->uow->tryGetById($id, $this->class);
115 237
        if ($document) {
116 21
            if ($lockMode !== LockMode::NONE) {
117
                $this->dm->lock($document, $lockMode, $lockVersion);
118
            }
119
120 21
            return $document; // Hit!
121
        }
122
123 230
        $criteria = ['_id' => $id];
124
125 230
        if ($lockMode === LockMode::NONE) {
126 230
            return $this->getDocumentPersister()->load($criteria);
127
        }
128
129
        if ($lockMode === LockMode::OPTIMISTIC) {
130
            if (! $this->class->isVersioned) {
131
                throw LockException::notVersioned($this->documentName);
132
            }
133
134
            $document = $this->getDocumentPersister()->load($criteria);
135
            if ($document) {
136
                $this->uow->lock($document, $lockMode, $lockVersion);
137
            }
138
139
            return $document;
140
        }
141
142
        return $this->getDocumentPersister()->load($criteria, null, [], $lockMode);
143
    }
144
145
    /**
146
     * Finds all documents in the repository.
147
     */
148 10
    public function findAll() : array
149
    {
150 10
        return $this->findBy([]);
151
    }
152
153
    /**
154
     * Finds documents by a set of criteria.
155
     *
156
     * @param int|null $limit
157
     * @param int|null $skip
158
     */
159 11
    public function findBy(array $criteria, ?array $sort = null, $limit = null, $skip = null) : array
160
    {
161 11
        return $this->getDocumentPersister()->loadAll($criteria, $sort, $limit, $skip)->toArray();
162
    }
163
164
    /**
165
     * Finds a single document by a set of criteria.
166
     */
167 90
    public function findOneBy(array $criteria) : ?object
168
    {
169 90
        return $this->getDocumentPersister()->load($criteria);
170
    }
171
172 8
    public function getDocumentName() : string
173
    {
174 8
        return $this->documentName;
175
    }
176
177
    public function getDocumentManager() : DocumentManager
178
    {
179
        return $this->dm;
180
    }
181
182
    public function getClassMetadata() : ClassMetadata
183
    {
184
        return $this->class;
185
    }
186
187 8
    public function getClassName() : string
188
    {
189 8
        return $this->getDocumentName();
190
    }
191
192
    /**
193
     * Selects all elements from a selectable that match the expression and
194
     * returns a new collection containing these elements.
195
     *
196
     * @see Selectable::matching()
197
     */
198 4
    public function matching(Criteria $criteria) : ArrayCollection
199
    {
200 4
        $visitor      = new QueryExpressionVisitor($this->createQueryBuilder());
201 4
        $queryBuilder = $this->createQueryBuilder();
202
203 4
        if ($criteria->getWhereExpression() !== null) {
204 1
            $expr = $visitor->dispatch($criteria->getWhereExpression());
205 1
            $queryBuilder->setQueryArray($expr->getQuery());
206
        }
207
208 4
        if ($criteria->getMaxResults() !== null) {
209
            $queryBuilder->limit($criteria->getMaxResults());
210
        }
211
212 4
        if ($criteria->getFirstResult() !== null) {
213
            $queryBuilder->skip($criteria->getFirstResult());
214
        }
215
216 4
        if (count($criteria->getOrderings())) {
217
            $queryBuilder->sort($criteria->getOrderings());
218
        }
219
220
        // @TODO: wrap around a specialized Collection for efficient count on large collections
221 4
        $iterator = $queryBuilder->getQuery()->execute();
222 4
        assert($iterator instanceof Iterator);
223 4
        return new ArrayCollection($iterator->toArray());
224
    }
225
226 328
    protected function getDocumentPersister() : DocumentPersister
227
    {
228 328
        return $this->uow->getDocumentPersister($this->documentName);
229
    }
230
}
231