Completed
Push — master ( 8c5037...eed80c )
by Gaetano
07:22
created

ContentMatcher::matchContent()   C

Complexity

Conditions 18
Paths 79

Size

Total Lines 54
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 25.5557

Importance

Changes 0
Metric Value
dl 0
loc 54
c 0
b 0
f 0
ccs 20
cts 28
cp 0.7143
rs 6.6386
cc 18
eloc 33
nc 79
nop 1
crap 25.5557

How to fix   Long Method    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\Values\Content\Content;
6
use eZ\Publish\API\Repository\Values\Content\Query;
7
use Kaliop\eZMigrationBundle\API\Collection\ContentCollection;
8
9
/**
10
 * @todo extend to allow matching by visibility, subtree, depth, object state, section, creation/modification date...
11
 * @todo optimize the matches on multiple conditions (and, or) by compiling them in a single query
12
 */
13
class ContentMatcher extends RepositoryMatcher
14
{
15
    use FlexibleKeyMatcherTrait;
16
17
    const MATCH_CONTENT_ID = 'content_id';
18
    const MATCH_LOCATION_ID = 'location_id';
19
    const MATCH_CONTENT_REMOTE_ID = 'content_remote_id';
20
    const MATCH_LOCATION_REMOTE_ID = 'location_remote_id';
21
    const MATCH_PARENT_LOCATION_ID = 'parent_location_id';
22
    const MATCH_PARENT_LOCATION_REMOTE_ID = 'parent_location_remote_id';
23
    const MATCH_CONTENT_TYPE_ID = 'contenttype_id';
24
    const MATCH_CONTENT_TYPE_IDENTIFIER = 'contenttype_identifier';
25
26
    protected $allowedConditions = array(
27
        self::MATCH_AND, self::MATCH_OR,
28
        self::MATCH_CONTENT_ID, self::MATCH_LOCATION_ID, self::MATCH_CONTENT_REMOTE_ID, self::MATCH_LOCATION_REMOTE_ID,
29
        self::MATCH_PARENT_LOCATION_ID, self::MATCH_PARENT_LOCATION_REMOTE_ID, self::MATCH_CONTENT_TYPE_IDENTIFIER,
30
        // aliases
31
        'content_type', 'content_type_id', 'content_type_identifier'
32
    );
33 3
    protected $returns = 'Content';
34
35 3
    /**
36
     * @param array $conditions key: condition, value: int / string / int[] / string[]
37
     * @return ContentCollection
38
     */
39
    public function match(array $conditions)
40
    {
41
        return $this->matchContent($conditions);
42 3
    }
43
44 3
    /**
45
     * @param array $conditions key: condition, value: int / string / int[] / string[]
46 3
     * @return ContentCollection
47
     */
48 3
    public function matchContent(array $conditions)
49 3
    {
50 3
        $this->validateConditions($conditions);
51
52
        foreach ($conditions as $key => $values) {
53 3
54 3
            if (!is_array($values)) {
55
                $values = array($values);
56 2
            }
57 1
58
            // BC support
59 2
            if ($key == 'content_type') {
60
                if (is_int($values[0]) || ctype_digit($values[0])) {
61
                    $key = self::MATCH_CONTENT_TYPE_ID;
62 2
                } else {
63
                    $key = self::MATCH_CONTENT_TYPE_IDENTIFIER;
64
                }
65 2
            }
66
67
            switch ($key) {
68 2
                case self::MATCH_CONTENT_ID:
69
                   return new ContentCollection($this->findContentsByContentIds($values));
70
71 2
                case self::MATCH_LOCATION_ID:
72 2
                    return new ContentCollection($this->findContentsByLocationIds($values));
73
74
                case self::MATCH_CONTENT_REMOTE_ID:
75
                    return new ContentCollection($this->findContentsByContentRemoteIds($values));
76
77
                case self::MATCH_LOCATION_REMOTE_ID:
78
                    return new ContentCollection($this->findContentsByLocationRemoteIds($values));
79
80
                case self::MATCH_PARENT_LOCATION_ID:
81 3
                    return new ContentCollection($this->findContentsByParentLocationIds($values));
82
83 3
                case self::MATCH_PARENT_LOCATION_REMOTE_ID:
84
                    return new ContentCollection($this->findContentsByParentLocationRemoteIds($values));
85 3
86
                case 'content_type_id':
87 3
                case self::MATCH_CONTENT_TYPE_ID:
88 3
                    return new ContentCollection($this->findContentsByContentTypeIds($values));
89 3
90
                case 'content_type_identifier':
91 3
                case self::MATCH_CONTENT_TYPE_IDENTIFIER:
92
                    return new ContentCollection($this->findContentsByContentTypeIdentifiers($values));
93
94
                case self::MATCH_AND:
95
                    return $this->matchAnd($values);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->matchAnd($values); of type object|array adds the type array to the return on line 95 which is incompatible with the return type documented by Kaliop\eZMigrationBundle...ntMatcher::matchContent of type Kaliop\eZMigrationBundle...\ContentCollection|null.
Loading history...
96
97
                case self::MATCH_OR:
98
                    return $this->matchOr($values);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->matchOr($values); of type object|array adds the type array to the return on line 98 which is incompatible with the return type documented by Kaliop\eZMigrationBundle...ntMatcher::matchContent of type Kaliop\eZMigrationBundle...\ContentCollection|null.
Loading history...
99
            }
100
        }
101
    }
102
103
    /**
104
     * When matching by key, we accept content Id and remote Id only
105
     * @param int|string $key
106
     * @return array
107
     */
108
    protected function getConditionsFromKey($key)
109
    {
110
        if (is_int($key) || ctype_digit($key)) {
111
            return array(self::MATCH_CONTENT_ID => $key);
112
        }
113
        return array(self::MATCH_CONTENT_REMOTE_ID => $key);
114
    }
115 1
116
    /**
117 1
     * @param int[] $contentIds
118
     * @return Content[]
119 1
     */
120 1 View Code Duplication
    protected function findContentsByContentIds(array $contentIds)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
121
    {
122 1
        $contents = [];
123 1
124
        foreach ($contentIds as $contentId) {
125 1
            // return unique contents
126
            $content = $this->repository->getContentService()->loadContent($contentId);
127
            $contents[$content->contentInfo->id] = $content;
128
        }
129
130
        return $contents;
131
    }
132
133
    /**
134
     * @param string[] $remoteContentIds
135
     * @return Content[]
136
     */
137 View Code Duplication
    protected function findContentsByContentRemoteIds(array $remoteContentIds)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
138
    {
139
        $contents = [];
140
141
        foreach ($remoteContentIds as $remoteContentId) {
142
            // return unique contents
143
            $content = $this->repository->getContentService()->loadContentByRemoteId($remoteContentId);
144
            $contents[$content->contentInfo->id] = $content;
145
        }
146
147
        return $contents;
148
    }
149
150
    /**
151
     * @param int[] $locationIds
152
     * @return Content[]
153
     */
154 View Code Duplication
    protected function findContentsByLocationIds(array $locationIds)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
155
    {
156
        $contentIds = [];
157
158
        foreach ($locationIds as $locationId) {
159
            $location = $this->repository->getLocationService()->loadLocation($locationId);
160
            // return unique ids
161
            $contentIds[$location->contentId] = $location->contentId;
162
        }
163
164
        return $this->findContentsByContentIds($contentIds);
165
    }
166
167
    /**
168
     * @param string[] $remoteLocationIds
169
     * @return Content[]
170
     */
171 View Code Duplication
    protected function findContentsByLocationRemoteIds($remoteLocationIds)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
172
    {
173
        $contentIds = [];
174
175
        foreach ($remoteLocationIds as $remoteLocationId) {
176
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($remoteLocationId);
177
            // return unique ids
178
            $contentIds[$location->contentId] = $location->contentId;
179
        }
180
181
        return $this->findContentsByContentIds($contentIds);
182
    }
183
184
    /**
185
     * @param int[] $parentLocationIds
186 2
     * @return Content[]
187
     */
188 2
    protected function findContentsByParentLocationIds($parentLocationIds)
189 2
    {
190 2
        $query = new Query();
191
        $query->limit = PHP_INT_MAX;
192
        $query->filter = new Query\Criterion\ParentLocationId($parentLocationIds);
193 2
        $results = $this->repository->getSearchService()->findContent($query);
194 2
195
        $contents = [];
196 2
        foreach ($results->searchHits as $result) {
197 2
            // make sure we return every object only once
198
            $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
199 2
        }
200 2
201
        return $contents;
202 2
    }
203
204
    /**
205
     * @param string[] $remoteParentLocationIds
206
     * @return Content[]
207
     */
208 View Code Duplication
    protected function findContentsByParentLocationRemoteIds($remoteParentLocationIds)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
209
    {
210
        $locationIds = [];
211
212
        foreach ($remoteParentLocationIds as $remoteParentLocationId) {
213
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($remoteParentLocationId);
214
            // unique locations
215
            $locationIds[$location->id] = $location->id;
216
        }
217
218
        return $this->findContentsByParentLocationIds($locationIds);
219
    }
220
221
    /**
222
     * @param string[] $contentTypeIdentifiers
223
     * @return Content[]
224
     */
225 View Code Duplication
    protected function findContentsByContentTypeIdentifiers(array $contentTypeIdentifiers)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
226
    {
227
        $query = new Query();
228
        $query->limit = PHP_INT_MAX;
229
        $query->filter = new Query\Criterion\ContentTypeIdentifier($contentTypeIdentifiers);
230
        // sort objects by depth, lower to higher, so that deleting them has less chances of failure
231
        // NB: we only do this in eZP versions that allow depth sorting on content queries
232
        if (class_exists('eZ\Publish\API\Repository\Values\Content\Query\SortClause\LocationDepth')) {
233
            $query->sortClauses = array(new Query\SortClause\LocationDepth(Query::SORT_DESC));
0 ignored issues
show
Deprecated Code introduced by
The class eZ\Publish\API\Repositor...ortClause\LocationDepth has been deprecated with message: Since 5.3, use Location search instead

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
234
        }
235
236
        $results = $this->repository->getSearchService()->findContent($query);
237
238
        $contents = [];
239
        foreach ($results->searchHits as $result) {
240
            // make sure we return every object only once
241
            $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
242
        }
243
244
        return $contents;
245
    }
246
247
    /**
248
     * @param int[] $contentTypeIds
249
     * @return Content[]
250
     */
251 View Code Duplication
    protected function findContentsByContentTypeIds(array $contentTypeIds)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
252
    {
253
        $query = new Query();
254
        $query->limit = PHP_INT_MAX;
255
        $query->filter = new Query\Criterion\ContentTypeId($contentTypeIds);
256
        // sort objects by depth, lower to higher, so that deleting them has less chances of failure
257
        // NB: we only do this in eZP versions that allow depth sorting on content queries
258
        if (class_exists('eZ\Publish\API\Repository\Values\Content\Query\SortClause\LocationDepth')) {
259
            $query->sortClauses = array(new Query\SortClause\LocationDepth(Query::SORT_DESC));
0 ignored issues
show
Deprecated Code introduced by
The class eZ\Publish\API\Repositor...ortClause\LocationDepth has been deprecated with message: Since 5.3, use Location search instead

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
260
        }
261
        $results = $this->repository->getSearchService()->findContent($query);
262
263
        $contents = [];
264
        foreach ($results->searchHits as $result) {
265
            // make sure we return every object only once
266
            $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
267
        }
268
269
        return $contents;
270
    }
271
}
272