Passed
Push — master ( bca814...405448 )
by Gaetano
09:09 queued 17s
created

LocationMatcher   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 271
Duplicated Lines 0 %

Test Coverage

Coverage 45.05%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
eloc 102
dl 0
loc 271
ccs 41
cts 91
cp 0.4505
rs 9.36
c 3
b 1
f 0
wmc 38

11 Methods

Rating   Name   Duplication   Size   Complexity  
A match() 0 3 1
A matchOne() 0 13 3
A findLocationsByParentLocationIds() 0 16 3
A findLocationsByParentLocationRemoteIds() 0 10 2
A findLocationsByContentRemoteIds() 0 12 3
A getConditionsFromKey() 0 6 3
A findLocationsByLocationIds() 0 9 2
B getQueryCriterion() 0 35 9
A findLocationsByLocationRemoteIds() 0 10 2
B matchLocation() 0 29 7
A findLocationsByContentIds() 0 12 3
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Matcher;
4
5
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException;
6
use eZ\Publish\API\Repository\Values\Content\Query;
7
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
8
use eZ\Publish\API\Repository\Values\Content\Location;
9
use Kaliop\eZMigrationBundle\API\Collection\LocationCollection;
10
use Kaliop\eZMigrationBundle\API\SortingMatcherInterface;
11
use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchResultsNumberException;
12
use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException;
13
use Kaliop\eZMigrationBundle\API\Exception\InvalidSortConditionsException;
14
15
class LocationMatcher extends QueryBasedMatcher implements SortingMatcherInterface
16
{
17
    use FlexibleKeyMatcherTrait;
18
19
    const MATCH_DEPTH = 'depth';
20
    const MATCH_IS_MAIN_LOCATION = 'is_main_location';
21
    const MATCH_PRIORITY = 'priority';
22
23
    protected $allowedConditions = array(
24
        self::MATCH_AND, self::MATCH_OR, self::MATCH_NOT,
25
        self::MATCH_CONTENT_ID, self::MATCH_LOCATION_ID, self::MATCH_CONTENT_REMOTE_ID, self::MATCH_LOCATION_REMOTE_ID,
26
        self::MATCH_ATTRIBUTE, self::MATCH_CONTENT_TYPE_ID, self::MATCH_CONTENT_TYPE_IDENTIFIER, self::MATCH_GROUP,
27
        self::MATCH_CREATION_DATE, self::MATCH_MODIFICATION_DATE, self::MATCH_OBJECT_STATE, self::MATCH_OWNER,
28
        self::MATCH_PARENT_LOCATION_ID, self::MATCH_PARENT_LOCATION_REMOTE_ID, self::MATCH_QUERY_TYPE, self::MATCH_SECTION,
29
        self::MATCH_SUBTREE, self::MATCH_VISIBILITY,
30
        // aliases
31
        'content_type',
32
        // BC
33
        'contenttype_id', 'contenttype_identifier',
34
        // location-only
35
        self::MATCH_DEPTH, self::MATCH_IS_MAIN_LOCATION, self::MATCH_PRIORITY,
36
    );
37
    protected $returns = 'Location';
38
39
    /**
40
     * @param array $conditions key: condition, value: int / string / int[] / string[]
41
     * @param array $sort
42
     * @param int $offset
43
     * @param int $limit
44
     * @param bool $tolerateMisses
45 12
     * @return LocationCollection
46
     * @throws InvalidArgumentException
47 12
     * @throws InvalidMatchConditionsException
48
     * @throws InvalidSortConditionsException
49
     */
50
    public function match(array $conditions, array $sort = array(), $offset = 0, $limit = 0, $tolerateMisses = false)
51
    {
52
        return $this->matchLocation($conditions, $sort, $offset, $limit, $tolerateMisses);
53
    }
54
55
    /**
56
     * @param array $conditions
57
     * @param array $sort
58
     * @param int $offset
59 12
     * @return Location
60
     * @throws InvalidArgumentException
61 12
     * @throws InvalidMatchConditionsException
62 12
     * @throws InvalidSortConditionsException
63 12
     * @throws InvalidMatchResultsNumberException
64
     */
65
    public function matchOne(array $conditions, array $sort = array(), $offset = 0)
66 12
    {
67
        $results = $this->match($conditions, $sort, $offset, 2);
68
        $count = count($results);
69
        if ($count !== 1) {
70
            throw new InvalidMatchResultsNumberException("Found $count " . $this->returns . " when expected exactly only one to match the conditions");
71
        }
72
73
        if ($results instanceof \ArrayObject) {
0 ignored issues
show
introduced by
$results is always a sub-type of ArrayObject.
Loading history...
74
            $results = $results->getArrayCopy();
75
        }
76
77
        return reset($results);
78 2
    }
79
80 2
    /**
81
     * @param array $conditions key: condition, value: value: int / string / int[] / string[]
82 2
     * @param array $sort
83
     * @param int $offset
84 2
     * @param int $limit
85 2
     * @param bool $tolerateMisses
86 2
     * @return LocationCollection
87 2
     * @throws InvalidArgumentException
88
     * @throws InvalidMatchConditionsException
89
     * @throws InvalidSortConditionsException
90 2
     */
91 2
    public function matchLocation(array $conditions, array $sort = array(), $offset = 0, $limit = 0, $tolerateMisses = false)
92 2
    {
93
        $this->validateConditions($conditions);
94 2
95 2
        foreach ($conditions as $key => $values) {
96 2
97
            if ($key == self::MATCH_QUERY_TYPE) {
98
                $query = $this->getQueryByQueryType($values);
99 2
            } else {
100
                $query = new LocationQuery();
101
                $query->filter = $this->getQueryCriterion($key, $values);
102
            }
103
104
            // q: when getting a query via QueryType, should we always inject offset/limit?
105
            $query->limit = $limit != 0 ? $limit : self::INT_MAX_16BIT;
106
            $query->offset = $offset;
107
            if (!empty($sort)) {
108 12
                $query->sortClauses = $this->getSortClauses($sort);
109
            }
110 12
            if (isset($query->performCount)) $query->performCount = false;
111 12
112
            $results = $this->getSearchService()->findLocations($query);
113 1
114
            $locations = [];
115
            foreach ($results->searchHits as $result) {
116 2
                $locations[$result->valueObject->id] = $result->valueObject;
117
            }
118 2
119 2
            return new LocationCollection($locations);
120
        }
121
    }
122
123 2
    /**
124 1
     * When matching by key, we accept location Id and remote Id only
125 1
     * @param int|string $key
126 1
     * @return array
127
     */
128
    protected function getConditionsFromKey($key)
129 1
    {
130
        if (is_int($key) || ctype_digit($key)) {
131 2
            return array(self::MATCH_LOCATION_ID => $key);
132 2
        }
133
        return array(self::MATCH_LOCATION_REMOTE_ID => $key);
134
    }
135
136
    protected function getQueryCriterion($key, $values)
137
    {
138
        if (!is_array($values)) {
139
            $values = array($values);
140
        }
141 2
142 1
        switch ($key) {
143 1
            case self::MATCH_DEPTH:
144 1
                $match = reset($values);
145
                $operator = key($values);
146
                if (!isset(self::$operatorsMap[$operator])) {
147 1
                    throw new InvalidMatchConditionsException("Can not use '$operator' as comparison operator for depth");
148
                }
149
                return new Query\Criterion\Location\Depth(self::$operatorsMap[$operator], $match);
150 2
151
            case self::MATCH_IS_MAIN_LOCATION:
152
            case 'is_main':
153
                /// @todo error/warning if there is more than 1 value...
154
                $value = reset($values);
155
                if ($value) {
156
                    return new Query\Criterion\Location\IsMainLocation(Query\Criterion\Location\IsMainLocation::MAIN);
157
                } else {
158
                    return new Query\Criterion\Location\IsMainLocation(Query\Criterion\Location\IsMainLocation::NOT_MAIN);
159
                }
160
161
            case self::MATCH_PRIORITY:
162
                $match = reset($values);
163
                $operator = key($values);
164
                if (!isset(self::$operatorsMap[$operator])) {
165
                    throw new InvalidMatchConditionsException("Can not use '$operator' as comparison operator for depth");
166
                }
167
                return new Query\Criterion\Location\Priority(self::$operatorsMap[$operator], $match);
168
        }
169
170
        return parent::getQueryCriterion($key, $values);
171
    }
172
173
    /**
174
     * Returns all locations of a set of objects
175
     *
176
     * @param int[] $contentIds
177
     * @return Location[]
178
     * @deprecated
179
     */
180
    protected function findLocationsByContentIds(array $contentIds)
181
    {
182
        $locations = [];
183
184
        foreach ($contentIds as $contentId) {
185
            $content = $this->repository->getContentService()->loadContent($contentId);
186
            foreach ($this->repository->getLocationService()->loadLocations($content->contentInfo) as $location) {
187
                $locations[$location->id] = $location;
188
            }
189
        }
190
191
        return $locations;
192
    }
193
194
    /**
195
     * Returns all locations of a set of objects
196
     *
197
     * @param int[] $remoteContentIds
198
     * @return Location[]
199
     * @deprecated
200
     */
201
    protected function findLocationsByContentRemoteIds(array $remoteContentIds)
202
    {
203
        $locations = [];
204
205
        foreach ($remoteContentIds as $remoteContentId) {
206
            $content = $this->repository->getContentService()->loadContentByRemoteId($remoteContentId);
207
            foreach ($this->repository->getLocationService()->loadLocations($content->contentInfo) as $location) {
208
                $locations[$location->id] = $location;
209
            }
210
        }
211
212
        return $locations;
213
    }
214
215
    /**
216
     * @param int[] $locationIds
217
     * @return Location[]
218
     * @deprecated
219
     */
220
    protected function findLocationsByLocationIds(array $locationIds)
221
    {
222
        $locations = [];
223
224
        foreach ($locationIds as $locationId) {
225
            $locations[$locationId] = $this->repository->getLocationService()->loadLocation($locationId);
226
        }
227
228
        return $locations;
229
    }
230
231
    /**
232
     * @param int[] $locationRemoteIds
233
     * @return Location[]
234
     * @deprecated
235
     */
236
    protected function findLocationsByLocationRemoteIds($locationRemoteIds)
237
    {
238
        $locations = [];
239
240
        foreach ($locationRemoteIds as $locationRemoteId) {
241
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($locationRemoteId);
242
            $locations[$location->id] = $location;
243
        }
244
245
        return $locations;
246
    }
247
248
    /**
249
     * @param int[] $parentLocationIds
250
     * @return Location[]
251
     * @deprecated
252
     */
253
    protected function findLocationsByParentLocationIds($parentLocationIds)
254
    {
255
        $query = new LocationQuery();
256
        $query->limit = self::INT_MAX_16BIT;
257
        if (isset($query->performCount)) $query->performCount = false;
258
        $query->filter = new Query\Criterion\ParentLocationId($parentLocationIds);
259
260
        $results = $this->getSearchService()->findLocations($query);
261
262
        $locations = [];
263
264
        foreach ($results->searchHits as $result) {
265
            $locations[$result->valueObject->id] = $result->valueObject;
266
        }
267
268
        return $locations;
269
    }
270
271
    /**
272
     * @param int[] $parentLocationRemoteIds
273
     * @return Location[]
274
     * @deprecated
275
     */
276
    protected function findLocationsByParentLocationRemoteIds($parentLocationRemoteIds)
277
    {
278
        $locationIds = [];
279
280
        foreach ($parentLocationRemoteIds as $parentLocationRemoteId) {
281
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($parentLocationRemoteId);
282
            $locationIds[$location->id] = $location->id;
283
        }
284
285
        return $this->findLocationsByParentLocationIds($locationIds);
0 ignored issues
show
Deprecated Code introduced by
The function Kaliop\eZMigrationBundle...nsByParentLocationIds() has been deprecated. ( Ignorable by Annotation )

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

285
        return /** @scrutinizer ignore-deprecated */ $this->findLocationsByParentLocationIds($locationIds);
Loading history...
286
    }
287
}
288