Completed
Push — master ( 97fb46...770b11 )
by Gaetano
15:34 queued 07:06
created

AbstractMatcher::matchOne()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

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

127
        return reset(/** @scrutinizer ignore-type */ $results);
Loading history...
128
    }
129
130
    /**
131
     * @param array $conditions
132
     * @return array|\ArrayObject the keys must be a unique identifier of the matched entities
133
     * @throws \Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException
134
     */
135
    abstract public function match(array $conditions);
136
}
137