Completed
Push — master ( bc9a97...2c9e04 )
by Gaetano
12:29 queued 07:39
created

ReferenceMatcher   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 128
Duplicated Lines 12.5 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 62.5%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 3
dl 16
loc 128
ccs 25
cts 40
cp 0.625
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A validateConditions() 0 10 3
B match() 16 42 10
A getConstraint() 0 11 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Matcher;
4
5
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator;
6
use Symfony\Component\Validator\Validator\ValidatorInterface;
7
use Kaliop\eZMigrationBundle\API\ReferenceResolverInterface;
8
9
/**
10
 * We abuse a bit the 'matcher' framework to set up a 'constraint' matcher which is used to tell whether a reference
11
 * matches a given condition
12
 */
13
class ReferenceMatcher extends AbstractMatcher
14
{
15
    //const MATCH_REFERENCE = 'reference';
16
17
    protected $allowedConditions = array(
18
        self::MATCH_AND, self::MATCH_OR, self::MATCH_NOT,
19
        //self::MATCH_REFERENCE
20
    );
21
22
    // since this is used for recursive calls as well, we have to unlock it for now
23
    /// @todo allow this to be set in a more flexible way
24
    protected $maxConditions = 0;
25
26
    protected $validator;
27
    /** @var ReferenceResolverInterface $referenceResolver */
28
    protected $referenceResolver;
29
30
    /// @todo add more operators
31
    static protected $operatorsMap = array(
32
        'eq' => '\Symfony\Component\Validator\Constraints\EqualTo',
33
        'gt' => '\Symfony\Component\Validator\Constraints\GreaterThan',
34
        'gte' => '\Symfony\Component\Validator\Constraints\GreaterThanOrEqual',
35
        'lt' => '\Symfony\Component\Validator\Constraints\LessThan',
36
        'lte' => '\Symfony\Component\Validator\Constraints\LessThanOrEqual',
37
        'ne' => '\Symfony\Component\Validator\Constraints\NotEqualTo',
38
39
        'count' => '\Symfony\Component\Validator\Constraints\Count',
40
        'length' => '\Symfony\Component\Validator\Constraints\Length',
41
        'regex' => '\Symfony\Component\Validator\Constraints\Regex',
42
        'satisfies' => '\Symfony\Component\Validator\Constraints\Expression',
43
        //'in' => Operator::IN,
44
        //'between' => Operator::BETWEEN, => use count/length with min & max sub-members
45
        //'like' => Operator::LIKE, => use regex
46
        //'contains' => Operator::CONTAINS,
47
48
        Operator::EQ => '\Symfony\Component\Validator\Constraints\EqualTo',
49
        Operator::GT => '\Symfony\Component\Validator\Constraints\GreaterThan',
50
        Operator::GTE => '\Symfony\Component\Validator\Constraints\GreaterThanOrEqual',
51
        Operator::LT => '\Symfony\Component\Validator\Constraints\LessThan',
52
        Operator::LTE => '\Symfony\Component\Validator\Constraints\LessThanOrEqual',
53
        '!=' => '\Symfony\Component\Validator\Constraints\NotEqualTo',
54
        '<>' => '\Symfony\Component\Validator\Constraints\NotEqualTo',
55
    );
56
57 80
    public function __construct(ReferenceResolverInterface $referenceResolver, ValidatorInterface $validator)
58
    {
59 80
        $this->referenceResolver = $referenceResolver;
60 80
        $this->validator = $validator;
61 80
    }
62
63
    // q: what if we receive an array of conditions? it seems that it might be validated here, even though only the 1st
64
    //    condition would be taken into account...
65 2
    protected function validateConditions(array $conditions)
66
    {
67 2
        foreach ($conditions as $key => $val) {
68 2
            if ($this->referenceResolver->isReference($key)) {
69 2
                return true;
70
            }
71
        }
72
73
        return parent::validateConditions($conditions);
74
    }
75
76
    /**
77
     * @param array $conditions key: condition, value: int / string / int[] / string[]
78
     * @return array 1 element with the value true/false
79
     */
80 2
    public function match(array $conditions)
81
    {
82 2
        $this->validateConditions($conditions);
83
84 2
        foreach ($conditions as $key => $values) {
85
86
            switch ($key) {
87 2 View Code Duplication
                case self::MATCH_AND:
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...
88
                    foreach($values as $subCriterion) {
89
                        $value = $this->match($subCriterion);
90
                        if (!reset($value)) {
91
                            return $value;
92
                        }
93
                    }
94
                    return array(true);
95
96 2 View Code Duplication
                case self::MATCH_OR:
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...
97
                    foreach($values as $subCriterion) {
98
                        $value = $this->match($subCriterion);
99
                        if (reset($value)) {
100
                            return $value;
101
                        }
102
                    }
103
                    return array(false);
104
105 2
                case self::MATCH_NOT:
106
                    return array(!reset($this->match($values)));
0 ignored issues
show
Bug introduced by
$this->match($values) cannot be passed to reset() as the parameter $array expects a reference.
Loading history...
107
108
                default:
109
                    // we assume that all are refs because of the call to validate()
110 2
                    $currentValue = $this->referenceResolver->resolveReference($key);
111 2
                    $targetValue = reset($values);
112
                    // q: what about resolving refs in teh target value, too ?
113 2
                    $constraint = key($values);
114 2
                    $errorList = $this->validator->validate($currentValue, $this->getConstraint($constraint, $targetValue));
115 2
                    if (0 === count($errorList)) {
116 1
                        return array(true);
117
                    }
118 2
                    return array(false);
119
            }
120
        }
121
    }
122
123
    /**
124
     * @param string $constraint
125
     * @param $targetValue
126
     * @return mixed
127
     * @throws \Exception for unsupported keys
128
     */
129 2
    protected function getConstraint($constraint, $targetValue)
130
    {
131 2
        if (!isset(self::$operatorsMap[$constraint])) {
132
            throw new \Exception("Matching condition '$constraint' is not supported. Supported conditions are: " .
133
                implode(', ', array_keys(self::$operatorsMap))
134
            );
135
        }
136
137 2
        $class = self::$operatorsMap[$constraint];
138 2
        return new $class($targetValue);
139
    }
140
}
141