Passed
Push — master ( 4753c3...bca814 )
by Gaetano
09:41
created

ObjectStateMatcher::matchObjectState()   C

Complexity

Conditions 13
Paths 23

Size

Total Lines 32
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 25.6195

Importance

Changes 0
Metric Value
cc 13
eloc 21
nc 23
nop 2
dl 0
loc 32
ccs 11
cts 19
cp 0.5789
crap 25.6195
rs 6.6166
c 0
b 0
f 0

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
namespace Kaliop\eZMigrationBundle\Core\Matcher;
4
5
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
6
use eZ\Publish\API\Repository\Values\ObjectState\ObjectState;
7
use eZ\Publish\Core\Base\Exceptions\NotFoundException as CoreNotFoundException;
8
use Kaliop\eZMigrationBundle\API\Collection\ObjectStateCollection;
9
use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException;
10
use Kaliop\eZMigrationBundle\API\KeyMatcherInterface;
11
12
class ObjectStateMatcher extends RepositoryMatcher implements KeyMatcherInterface
13
{
14
    use FlexibleKeyMatcherTrait;
15
16
    const MATCH_OBJECTSTATE_ID = 'object_state_id';
17
    const MATCH_OBJECTSTATE_IDENTIFIER = 'object_state_identifier';
18
19
    protected $allowedConditions = array(
20
        self::MATCH_ALL, self::MATCH_AND, self::MATCH_OR, self::MATCH_NOT,
21
        self::MATCH_OBJECTSTATE_ID, self::MATCH_OBJECTSTATE_IDENTIFIER,
22
        // aliases
23
        'id', 'identifier',
24
        // BC
25
        'objectstate_id', 'objectstate_identifier',
26
    );
27
    protected $returns = 'ObjectState';
28
29
    /**
30
     * @param array $conditions key: condition, value: int / string / int[] / string[]
31 5
     * @param bool $tolerateMisses
32
     * @return ObjectStateCollection
33 5
     * @throws InvalidMatchConditionsException
34
     * @throws NotFoundException
35
     */
36
    public function match(array $conditions, $tolerateMisses = false)
37
    {
38
        return $this->matchObjectState($conditions, $tolerateMisses);
39
    }
40
41 5
    /**
42
     * @param array $conditions key: condition, value: int / string / int[] / string[]
43 5
     * @param bool $tolerateMisses
44
     * @return ObjectStateCollection
45 5
     * @throws InvalidMatchConditionsException
46
     * @throws NotFoundException
47 5
     */
48 5
    public function matchObjectState(array $conditions, $tolerateMisses = false)
49
    {
50
        $this->validateConditions($conditions);
51
52 5
        foreach ($conditions as $key => $values) {
53 5
54 1
            if (!is_array($values)) {
55
                $values = array($values);
56 5
            }
57 5
58 2
            switch ($key) {
59
                case 'id':
60 3
                case 'objectstate_id':
61 3
                case self::MATCH_OBJECTSTATE_ID:
62
                   return new ObjectStateCollection($this->findObjectStatesById($values, $tolerateMisses));
63
64
                case 'identifier':
65
                case 'objectstate_identifier':
66
                case self::MATCH_OBJECTSTATE_IDENTIFIER:
67
                    return new ObjectStateCollection($this->findObjectStatesByIdentifier($values, $tolerateMisses));
68
69
                case self::MATCH_ALL:
70
                    return new ObjectStateCollection($this->findAllObjectStates());
71
72
                case self::MATCH_AND:
73
                    return $this->matchAnd($values, $tolerateMisses);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->matchAnd($values, $tolerateMisses) returns the type array which is incompatible with the documented return type Kaliop\eZMigrationBundle...n\ObjectStateCollection.
Loading history...
74
75 2
                case self::MATCH_OR:
76
                    return $this->matchOr($values, $tolerateMisses);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->matchOr($values, $tolerateMisses) returns the type array which is incompatible with the documented return type Kaliop\eZMigrationBundle...n\ObjectStateCollection.
Loading history...
77 2
78
                case self::MATCH_NOT:
79
                    return new ObjectStateCollection(array_diff_key($this->findAllObjectStates(), $this->matchObjectState($values, true)->getArrayCopy()));
80 2
            }
81
        }
82
    }
83
84
    protected function getConditionsFromKey($key)
85
    {
86
        if (is_int($key) || ctype_digit($key)) {
87 1
            return array(self::MATCH_OBJECTSTATE_ID => $key);
88
        }
89 1
        return array(self::MATCH_OBJECTSTATE_IDENTIFIER => $key);
90
    }
91 1
92
    /**
93 1
     * @param int[] $objectStateIds
94 1
     * @param bool $tolerateMisses
95
     * @return ObjectState[]
96
     * @throws NotFoundException
97 1
     */
98
    protected function findObjectStatesById(array $objectStateIds, $tolerateMisses = false)
99
    {
100
        $objectStates = [];
101
102
        foreach ($objectStateIds as $objectStateId) {
103
            try {
104
                // return unique contents
105 2
                $objectState = $this->repository->getObjectStateService()->loadObjectState($objectStateId);
106
                $objectStates[$objectState->id] = $objectState;
107
            } catch(NotFoundException $e) {
108 2
                if (!$tolerateMisses) {
109
                    throw $e;
110 2
                }
111
            }
112 2
        }
113 2
114
        return $objectStates;
115
    }
116
117 2
    /**
118
     * @param string[] $stateIdentifiers Accepts the state identifier if unique, otherwise "group-identifier/state-identifier"
119
     * @param bool $tolerateMisses
120 2
     * @return ObjectState[]
121
     * @throws NotFoundException
122
     */
123
    protected function findObjectStatesByIdentifier(array $stateIdentifiers, $tolerateMisses = false)
124
    {
125
        // we have to build this list, as the ObjectStateService does not allow to load a State by identifier...
126 3
        $statesList = $this->loadAvailableStates();
127
128 3
        $states = [];
129
130 3
        foreach ($stateIdentifiers as $stateIdentifier) {
131 3
            if (!isset($statesList[$stateIdentifier])) {
132 3
                if ($tolerateMisses) {
133
                    continue;
134
                }
135
                // a quick and dirty way of letting the user know that he/she might be using a non-unique identifier
136 3
                throw new CoreNotFoundException("ObjectState", $stateIdentifier . "' (either missing or non unique)");
137
            }
138
            $states[$statesList[$stateIdentifier]->id] = $statesList[$stateIdentifier];
139
        }
140
141
        return $states;
142 5
    }
143
144 5
    /**
145 5
     * @return ObjectState[] key: id
146
     */
147 5
    protected function findAllObjectStates()
148 5
    {
149 5
        $states = array();
150 5
151
        foreach ($this->loadAvailableStates() as $key => $state) {
152 5
            if (strpos($key, '/') !== false) {
153
                $states[$state->id] = $state;
154 5
            }
155
        }
156
157
        return $states;
158 5
    }
159 5
160
    /**
161
     * @return ObjectState[] key: the state identifier (for unique identifiers), group_identifier/state_identifier for all
162
     */
163
    protected function loadAvailableStates()
164
    {
165 5
        $statesList = array();
166
        $nonUniqueIdentifiers = array();
167
168
        $groups = $this->repository->getObjectStateService()->loadObjectStateGroups();
169
        foreach ($groups as $group) {
170
            $groupStates = $this->repository->getObjectStateService()->loadObjectStates($group);
171
            foreach ($groupStates as $groupState) {
172
                // we always add the states using 'group/state' identifiers
173
                $statesList[$group->identifier . '/' . $groupState->identifier] = $groupState;
174
                // we only add the state using plain identifier if it is unique
175
                if (isset($statesList[$groupState->identifier])) {
176
                    unset($statesList[$groupState->identifier]);
177
                    $nonUniqueIdentifiers[] = $groupState->identifier;
178
                } else {
179
                    if (!isset($nonUniqueIdentifiers[$groupState->identifier])) {
180
                        $statesList[$groupState->identifier] = $groupState;
181
                    }
182
                }
183
            }
184
        }
185
186
        return $statesList;
187
    }
188
}
189