Completed
Push — master ( 315dca...845f07 )
by Andreas
12s
created

Lookup::fromReference()   C

Complexity

Conditions 8
Paths 14

Size

Total Lines 47
Code Lines 32

Duplication

Lines 18
Ratio 38.3 %

Code Coverage

Tests 23
CRAP Score 8.2078

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 18
loc 47
ccs 23
cts 27
cp 0.8519
rs 5.7377
cc 8
eloc 32
nc 14
nop 1
crap 8.2078
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ODM\MongoDB\Aggregation\Stage;
21
22
use Doctrine\Common\Persistence\Mapping\MappingException as BaseMappingException;
23
use Doctrine\MongoDB\Aggregation\Stage as BaseStage;
24
use Doctrine\ODM\MongoDB\Aggregation\Builder;
25
use Doctrine\ODM\MongoDB\DocumentManager;
26
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
27
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo;
28
use Doctrine\ODM\MongoDB\Mapping\MappingException;
29
30
/**
31
 * Fluent interface for building aggregation pipelines.
32
 */
33
class Lookup extends BaseStage\Lookup
34
{
35
    /**
36
     * @var DocumentManager
37
     */
38
    private $dm;
39
40
    /**
41
     * @var ClassMetadata
42
     */
43
    private $class;
44
45
    /**
46
     * @param Builder $builder
47
     * @param string $from
48
     * @param DocumentManager $documentManager
49
     * @param ClassMetadata $class
50
     */
51 10
    public function __construct(Builder $builder, $from, DocumentManager $documentManager, ClassMetadata $class)
52
    {
53 10
        $this->dm = $documentManager;
54 10
        $this->class = $class;
55
56 10
        parent::__construct($builder, $from);
57 10
    }
58
59
    /**
60
     * @param string $from
61
     * @return $this
62
     */
63 10
    public function from($from)
64
    {
65
        // $from can either be
66
        // a) a field name indicating a reference to a different document. Currently, only REFERENCE_STORE_AS_ID is supported
67
        // b) a Class name
68
        // c) a collection name
69
        // In cases b) and c) the local and foreign fields need to be filled
70 10
        if ($this->class->hasReference($from)) {
71 8
            return $this->fromReference($from);
72
        }
73
74
        // Check if mapped class with given name exists
75
        try {
76 2
            $targetMapping = $this->dm->getClassMetadata($from);
77 1
            return parent::from($targetMapping->getCollection());
78 1
        } catch (BaseMappingException $e) {
79 1
            return parent::from($from);
80
        }
81
    }
82
83
    /**
84
     * @param string $fieldName
85
     * @return $this
86
     * @throws MappingException
87
     */
88 8
    private function fromReference($fieldName)
89
    {
90 8
        if (! $this->class->hasReference($fieldName)) {
91
            MappingException::referenceMappingNotFound($this->class->name, $fieldName);
92
        }
93
94 8
        $referenceMapping = $this->class->getFieldMapping($fieldName);
95 8
        $targetMapping = $this->dm->getClassMetadata($referenceMapping['targetDocument']);
96 8
        parent::from($targetMapping->getCollection());
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (from() instead of fromReference()). Are you sure this is correct? If so, you might want to change this to $this->from().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
97
98 8
        if ($referenceMapping['isOwningSide']) {
99 4 View Code Duplication
            switch ($referenceMapping['storeAs']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
100 4
                case ClassMetadataInfo::REFERENCE_STORE_AS_ID:
101 1
                case ClassMetadataInfo::REFERENCE_STORE_AS_REF:
102 4
                    $referencedFieldName = ClassMetadataInfo::getReferenceFieldName($referenceMapping['storeAs'], $referenceMapping['name']);
103 4
                    break;
104
105
                default:
106
                   throw MappingException::cannotLookupNonIdReference($this->class->name, $fieldName);
107
            }
108
109
            $this
110 4
                ->foreignField('_id')
111 4
                ->localField($referencedFieldName);
112
        } else {
113 4
            if (isset($referenceMapping['repositoryMethod'])) {
114
                throw MappingException::repositoryMethodLookupNotAllowed($this->class->name, $fieldName);
115
            }
116
117 4
            $mappedByMapping = $targetMapping->getFieldMapping($referenceMapping['mappedBy']);
118 4 View Code Duplication
            switch ($mappedByMapping['storeAs']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
119 4
                case ClassMetadataInfo::REFERENCE_STORE_AS_ID:
120 2
                case ClassMetadataInfo::REFERENCE_STORE_AS_REF:
121 4
                    $referencedFieldName = ClassMetadataInfo::getReferenceFieldName($mappedByMapping['storeAs'], $mappedByMapping['name']);
122 4
                    break;
123
124
                default:
125
                    throw MappingException::cannotLookupNonIdReference($this->class->name, $fieldName);
126
            }
127
128
            $this
129 4
                ->localField('_id')
130 4
                ->foreignField($referencedFieldName);
131
        }
132
133 8
        return $this;
134
    }
135
}
136