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

LocationMatcher::matchLocation()   A

Complexity

Conditions 6
Paths 17

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6.0106

Importance

Changes 0
Metric Value
cc 6
eloc 14
nc 17
nop 4
dl 0
loc 22
ccs 14
cts 15
cp 0.9333
crap 6.0106
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Matcher;
4
5
use eZ\Publish\API\Repository\Values\Content\Query;
6
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
7
use eZ\Publish\API\Repository\Values\Content\Location;
8
use Kaliop\eZMigrationBundle\API\Collection\LocationCollection;
9
use Kaliop\eZMigrationBundle\API\SortingMatcherInterface;
10
use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchResultsNumberException;
11
use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException;
12
use Kaliop\eZMigrationBundle\API\Exception\InvalidSortConditionsException;
13
14
class LocationMatcher extends QueryBasedMatcher implements SortingMatcherInterface
15
{
16
    use FlexibleKeyMatcherTrait;
17
18
    const MATCH_DEPTH = 'depth';
19
    const MATCH_IS_MAIN_LOCATION = 'is_main_location';
20
    const MATCH_PRIORITY = 'priority';
21
22
    protected $allowedConditions = array(
23
        self::MATCH_AND, self::MATCH_OR, self::MATCH_NOT,
24
        self::MATCH_CONTENT_ID, self::MATCH_LOCATION_ID, self::MATCH_CONTENT_REMOTE_ID, self::MATCH_LOCATION_REMOTE_ID,
25
        self::MATCH_ATTRIBUTE, self::MATCH_CONTENT_TYPE_ID, self::MATCH_CONTENT_TYPE_IDENTIFIER, self::MATCH_GROUP,
26
        self::MATCH_CREATION_DATE, self::MATCH_MODIFICATION_DATE, self::MATCH_OBJECT_STATE, self::MATCH_OWNER,
27
        self::MATCH_PARENT_LOCATION_ID, self::MATCH_PARENT_LOCATION_REMOTE_ID, self::MATCH_SECTION, self::MATCH_SUBTREE,
28
        self::MATCH_VISIBILITY,
29
        // aliases
30
        'content_type', 'content_type_id', 'content_type_identifier',
31
        // location-only
32
        self::MATCH_DEPTH, self::MATCH_IS_MAIN_LOCATION, self::MATCH_PRIORITY,
33
    );
34
    protected $returns = 'Location';
35
36
    /**
37
     * @param array $conditions key: condition, value: int / string / int[] / string[]
38
     * @param array $sort
39
     * @param int $offset
40
     * @param int $limit
41
     * @return LocationCollection
42
     * @throws InvalidMatchConditionsException
43
     * @throws InvalidSortConditionsException
44
     */
45 12
    public function match(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
46
    {
47 12
        return $this->matchLocation($conditions, $sort, $offset, $limit);
48
    }
49
50
    /**
51
     * @param array $conditions
52
     * @param array $sort
53
     * @param int $offset
54
     * @return Location
55
     * @throws InvalidMatchConditionsException
56
     * @throws InvalidSortConditionsException
57
     * @throws InvalidMatchResultsNumberException
58
     */
59 12
    public function matchOne(array $conditions, array $sort = array(), $offset = 0)
60
    {
61 12
        $results = $this->match($conditions, $sort, $offset, 2);
62 12
        $count = count($results);
63 12
        if ($count !== 1) {
64
            throw new InvalidMatchResultsNumberException("Found $count " . $this->returns . " when expected exactly only one to match the conditions");
65
        }
66 12
        return reset($results);
0 ignored issues
show
Bug introduced by
$results of type Kaliop\eZMigrationBundle...tion\LocationCollection is incompatible with the type array expected by parameter $array of reset(). ( Ignorable by Annotation )

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

66
        return reset(/** @scrutinizer ignore-type */ $results);
Loading history...
67
    }
68
69
    /**
70
     * @param array $conditions key: condition, value: value: int / string / int[] / string[]
71
     * @param array $sort
72
     * @param int $offset
73
     * @param int $limit
74
     * @return LocationCollection
75
     * @throws InvalidMatchConditionsException
76
     * @throws InvalidSortConditionsException
77
     */
78 2
    public function matchLocation(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
79
    {
80 2
        $this->validateConditions($conditions);
81
82 2
        foreach ($conditions as $key => $values) {
83
84 2
            $query = new LocationQuery();
85 2
            $query->limit = $limit != 0 ? $limit : self::INT_MAX_16BIT;
86 2
            $query->offset = $offset;
87 2
            if (!empty($sort)) {
88
                $query->sortClauses = $this->getSortClauses($sort);
89
            }
90 2
            if (isset($query->performCount)) $query->performCount = false;
91 2
            $query->filter = $this->getQueryCriterion($key, $values);
92 2
            $results = $this->repository->getSearchService()->findLocations($query);
93
94 2
            $locations = [];
95 2
            foreach ($results->searchHits as $result) {
96 2
                $locations[$result->valueObject->id] = $result->valueObject;
97
            }
98
99 2
            return new LocationCollection($locations);
100
        }
101
    }
102
103
    /**
104
     * When matching by key, we accept location Id and remote Id only
105
     * @param int|string $key
106
     * @return array
107
     */
108 12
    protected function getConditionsFromKey($key)
109
    {
110 12
        if (is_int($key) || ctype_digit($key)) {
111 12
            return array(self::MATCH_LOCATION_ID => $key);
112
        }
113 1
        return array(self::MATCH_LOCATION_REMOTE_ID => $key);
114
    }
115
116 2
    protected function getQueryCriterion($key, $values)
117
    {
118 2
        if (!is_array($values)) {
119 2
            $values = array($values);
120
        }
121
122
        switch ($key) {
123 2
            case self::MATCH_DEPTH:
124 1
                $match = reset($values);
125 1
                $operator = key($values);
126 1
                if (!isset(self::$operatorsMap[$operator])) {
127
                    throw new InvalidMatchConditionsException("Can not use '$operator' as comparison operator for depth");
128
                }
129 1
                return new Query\Criterion\Location\Depth(self::$operatorsMap[$operator], $match);
130
131 2
            case self::MATCH_IS_MAIN_LOCATION:
132 2
            case 'is_main':
133
                /// @todo error/warning if there is more than 1 value...
134
                $value = reset($values);
135
                if ($value) {
136
                    return new Query\Criterion\Location\IsMainLocation(Query\Criterion\Location\IsMainLocation::MAIN);
137
                } else {
138
                    return new Query\Criterion\Location\IsMainLocation(Query\Criterion\Location\IsMainLocation::NOT_MAIN);
139
                }
140
141 2
            case self::MATCH_PRIORITY:
142 1
                $match = reset($values);
143 1
                $operator = key($values);
144 1
                if (!isset(self::$operatorsMap[$operator])) {
145
                    throw new InvalidMatchConditionsException("Can not use '$operator' as comparison operator for depth");
146
                }
147 1
                return new Query\Criterion\Location\Priority(self::$operatorsMap[$operator], $match);
148
        }
149
150 2
        return parent::getQueryCriterion($key, $values);
151
    }
152
153
    /**
154
     * Returns all locations of a set of objects
155
     *
156
     * @param int[] $contentIds
157
     * @return Location[]
158
     * @deprecated
159
     */
160
    protected function findLocationsByContentIds(array $contentIds)
161
    {
162
        $locations = [];
163
164
        foreach ($contentIds as $contentId) {
165
            $content = $this->repository->getContentService()->loadContent($contentId);
166
            foreach($this->repository->getLocationService()->loadLocations($content->contentInfo) as $location) {
167
                $locations[$location->id] = $location;
168
            }
169
        }
170
171
        return $locations;
172
    }
173
174
    /**
175
     * Returns all locations of a set of objects
176
     *
177
     * @param int[] $remoteContentIds
178
     * @return Location[]
179
     * @deprecated
180
     */
181
    protected function findLocationsByContentRemoteIds(array $remoteContentIds)
182
    {
183
        $locations = [];
184
185
        foreach ($remoteContentIds as $remoteContentId) {
186
            $content = $this->repository->getContentService()->loadContentByRemoteId($remoteContentId);
187
            foreach($this->repository->getLocationService()->loadLocations($content->contentInfo) as $location) {
188
                $locations[$location->id] = $location;
189
            }
190
        }
191
192
        return $locations;
193
    }
194
195
    /**
196
     * @param int[] $locationIds
197
     * @return Location[]
198
     * @deprecated
199
     */
200
    protected function findLocationsByLocationIds(array $locationIds)
201
    {
202
        $locations = [];
203
204
        foreach ($locationIds as $locationId) {
205
            $locations[$locationId] = $this->repository->getLocationService()->loadLocation($locationId);
206
        }
207
208
        return $locations;
209
    }
210
211
    /**
212
     * @param int[] $locationRemoteIds
213
     * @return Location[]
214
     * @deprecated
215
     */
216
    protected function findLocationsByLocationRemoteIds($locationRemoteIds)
217
    {
218
        $locations = [];
219
220
        foreach ($locationRemoteIds as $locationRemoteId) {
221
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($locationRemoteId);
222
            $locations[$location->id] = $location;
223
        }
224
225
        return $locations;
226
    }
227
228
    /**
229
     * @param int[] $parentLocationIds
230
     * @return Location[]
231
     * @deprecated
232
     */
233
    protected function findLocationsByParentLocationIds($parentLocationIds)
234
    {
235
        $query = new LocationQuery();
236
        $query->limit = self::INT_MAX_16BIT;
237
        if (isset($query->performCount)) $query->performCount = false;
238
        $query->filter = new Query\Criterion\ParentLocationId($parentLocationIds);
239
240
        $results = $this->repository->getSearchService()->findLocations($query);
241
242
        $locations = [];
243
244
        foreach ($results->searchHits as $result) {
245
            $locations[$result->valueObject->id] = $result->valueObject;
246
        }
247
248
        return $locations;
249
    }
250
251
    /**
252
     * @param int[] $parentLocationRemoteIds
253
     * @return Location[]
254
     * @deprecated
255
     */
256
    protected function findLocationsByParentLocationRemoteIds($parentLocationRemoteIds)
257
    {
258
        $locationIds = [];
259
260
        foreach ($parentLocationRemoteIds as $parentLocationRemoteId) {
261
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($parentLocationRemoteId);
262
            $locationIds[$location->id] = $location->id;
263
        }
264
265
        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

265
        return /** @scrutinizer ignore-deprecated */ $this->findLocationsByParentLocationIds($locationIds);
Loading history...
266
    }
267
}
268