Completed
Branch master (e35419)
by Gaetano
06:40
created

AbstractMatcher::validateConditions()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 8.8142

Importance

Changes 0
Metric Value
cc 7
eloc 8
nc 5
nop 1
dl 0
loc 14
ccs 6
cts 9
cp 0.6667
crap 8.8142
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Matcher;
4
5
use Kaliop\eZMigrationBundle\API\MatcherInterface;
6
use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchResultsNumberException;
7
use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException;
8
9
abstract class AbstractMatcher implements MatcherInterface
10
{
11
    /** @var string[] $allowedConditions the keywords we allow to be used for matching on*/
12
    protected $allowedConditions = array();
13
    /** @var  string $returns user-readable name of the type of object returned */
14
    protected $returns;
15
    /** @var int $maxConditions the maximum number of conditions we allow to match on for a single match request */
16
    protected $maxConditions = 1;
17
    /** @var int $minConditions the minimum number of conditions we allow to match on for a single match request. It could be replaced with an array of mandatory conditions, really... */
18
    protected $minConditions = 1;
19
20
    /**
21
     * @param array $conditions
22
     * @throws InvalidMatchConditionsException
23
     */
24 48
    protected function validateConditions(array $conditions)
25
    {
26 48
        if ($this->minConditions > 0 && count($conditions) < $this->minConditions) {
27
            throw new InvalidMatchConditionsException($this->returns . ' can not be matched because the matching conditions are empty');
28
        }
29
30 48
        if ($this->maxConditions > 0 && count($conditions) > $this->maxConditions) {
31
            throw new InvalidMatchConditionsException($this->returns . " can not be matched because multiple matching conditions are specified. Only {$this->maxConditions} condition(s) are supported");
32
        }
33
34 48
        foreach ($conditions as $key => $value) {
35 48
            if (!in_array((string)$key, $this->allowedConditions)) {
36
                throw new InvalidMatchConditionsException($this->returns . " can not be matched because matching condition '$key' is not supported. Supported conditions are: " .
37 48
                    implode(', ', $this->allowedConditions));
38
            }
39
        }
40 48
    }
41
42
    /**
43
     * @param $conditionsArray
44
     * @return array|\ArrayObject
45
     * @throws InvalidMatchConditionsException
46
     */
47 1
    protected function matchAnd($conditionsArray)
48
    {
49
        /// @todo introduce proper re-validation of all child conditions
50 1
        if (!is_array($conditionsArray) || !count($conditionsArray)) {
51
            throw new InvalidMatchConditionsException($this->returns . " can not be matched because no matching conditions found for 'and' clause.");
52
        }
53
54 1
        $class = null;
55 1
        foreach ($conditionsArray as $conditions) {
56 1
            $out = $this->match($conditions);
57 1
            if ($out instanceof \ArrayObject) {
58 1
                $class = get_class($out);
59 1
                $out = $out->getArrayCopy();
60
            }
61 1
            if (!isset($results)) {
62 1
                $results = $out;
63
            } else {
64 1
                $results = array_intersect_key($results, $out);
65
            }
66
        }
67
68 1
        if ($class) {
69 1
            $results = new $class($results);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $results seems to be defined by a foreach iteration on line 55. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
70
        }
71
72 1
        return $results;
73
    }
74
75
    /**
76
     * @param $conditionsArray
77
     * @return array
78
     * @throws InvalidMatchConditionsException
79
     */
80 1
    protected function matchOr($conditionsArray)
81
    {
82
        /// @todo introduce proper re-validation of all child conditions
83 1
        if (!is_array($conditionsArray) || !count($conditionsArray)) {
84
            throw new InvalidMatchConditionsException($this->returns . " can not be matched because no matching conditions found for 'or' clause.");
85
        }
86
87 1
        $class = null;
88 1
        $results = array();
89 1
        foreach ($conditionsArray as $conditions) {
90 1
            $out = $this->match($conditions);
91 1
            if ($out instanceof \ArrayObject) {
92 1
                $class = get_class($out);
93 1
                $out = $out->getArrayCopy();
94
            }
95 1
            $results = array_replace($results, $out);
96
        }
97
98 1
        if ($class) {
99 1
            $results = new $class($results);
100
        }
101
102 1
        return $results;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $results also could return the type object which is incompatible with the documented return type array.
Loading history...
103
    }
104
105
    /**
106
     * @param array $conditions
107
     * @return mixed
108
     * @throws InvalidMatchConditionsException
109
     * @throws InvalidMatchResultsNumberException
110
     */
111 20
    public function matchOne(array $conditions)
112
    {
113 20
        $results = $this->match($conditions);
114 20
        $count = count($results);
115 20
        if ($count !== 1) {
116
            throw new InvalidMatchResultsNumberException("Found $count " . $this->returns . " when expected exactly only one to match the conditions");
117
        }
118 20
        return reset($results);
0 ignored issues
show
Bug introduced by
It seems like $results can also be of type ArrayObject; however, parameter $array of reset() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

118
        return reset(/** @scrutinizer ignore-type */ $results);
Loading history...
119
    }
120
121
    /**
122
     * @param array $conditions
123
     * @return array|\ArrayObject the keys must be a unique identifier of the matched entities
124
     * @throws \Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException
125
     */
126
    abstract public function match(array $conditions);
127
}
128