Completed
Push — master ( b2c38b...f910d1 )
by Gaetano
07:22
created

ContentMatcher::matchContent()   F

Complexity

Conditions 20
Paths 127

Size

Total Lines 77

Duplication

Lines 22
Ratio 28.57 %

Code Coverage

Tests 21
CRAP Score 45.6

Importance

Changes 0
Metric Value
dl 22
loc 77
c 0
b 0
f 0
ccs 21
cts 35
cp 0.6
rs 3.9416
cc 20
nc 127
nop 4
crap 45.6

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
use Kaliop\eZMigrationBundle\API\SortingMatcherInterface;
9
10
class ContentMatcher extends QueryBasedMatcher implements SortingMatcherInterface
11
{
12
    use FlexibleKeyMatcherTrait;
13
14
    const MATCH_RELATES_TO = 'relates_to';
15
    const MATCH_RELATED_FROM = 'related_from';
16
17
    protected $allowedConditions = array(
18
        self::MATCH_AND, self::MATCH_OR, self::MATCH_NOT,
19
        self::MATCH_CONTENT_ID, self::MATCH_LOCATION_ID, self::MATCH_CONTENT_REMOTE_ID, self::MATCH_LOCATION_REMOTE_ID,
20
        self::MATCH_ATTRIBUTE, self::MATCH_CONTENT_TYPE_ID, self::MATCH_CONTENT_TYPE_IDENTIFIER, self::MATCH_GROUP,
21
        self::MATCH_CREATION_DATE, self::MATCH_MODIFICATION_DATE, self::MATCH_OBJECT_STATE, self::MATCH_OWNER,
22
        self::MATCH_PARENT_LOCATION_ID, self::MATCH_PARENT_LOCATION_REMOTE_ID, self::MATCH_SECTION, self::MATCH_SUBTREE,
23
        self::MATCH_VISIBILITY,
24
        // aliases
25
        'content_type', 'content_type_id', 'content_type_identifier',
26
        // content-only
27
        self::MATCH_RELATES_TO, self::MATCH_RELATED_FROM
28
    );
29
    protected $returns = 'Content';
30
31
    /**
32
     * @param array $conditions key: condition, value: int / string / int[] / string[]
33
     * @param array $sort
34 16
     * @param int $offset
35
     * @param int $limit
36 16
     * @return ContentCollection
37
     */
38
    public function match(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
39
    {
40
        return $this->matchContent($conditions, $sort, $offset, $limit);
41
    }
42
43 13 View Code Duplication
    public function matchOne(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
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...
44
    {
45 13
        $results = $this->match($conditions, $sort, $offset, $limit);
46
        $count = count($results);
47 13
        if ($count !== 1) {
48
            throw new \Exception("Found $count " . $this->returns . " when expected exactly only one to match the conditions");
49
        }
50
        return reset($results);
51 13
    }
52
53
    /**
54
     * @param array $conditions key: condition, value: int / string / int[] / string[]
55
     * @param array $sort
56
     * @param int $offset
57
     * @param int $limit
58
     * @return ContentCollection
59
     */
60
    public function matchContent(array $conditions, array $sort = array(), $offset = 0, $limit = 0)
61
    {
62
        $this->validateConditions($conditions);
63 13
64
        foreach ($conditions as $key => $values) {
65
66
            switch($key) {
67
68 View Code Duplication
                case self::MATCH_RELATES_TO:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
69
                    $contentService = $this->repository->getContentService();
70
                    $contents = array();
71
                    // allow to specify the objects to relate to using different ways
72
                    $relatedContents = $this->match($values);
73
                    foreach($relatedContents as $relatedContent) {
0 ignored issues
show
Bug introduced by
The expression $relatedContents of type object<Kaliop\eZMigratio...ContentCollection>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
74
                        foreach($contentService->loadReverseRelations($relatedContent->contentInfo) as $relatingContent) {
75
                            $contents[$relatingContent->contentInfo->id] = $relatingContent;
0 ignored issues
show
Bug introduced by
The property contentInfo does not seem to exist. Did you mean destinationContentInfo?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
76
                        }
77
                    }
78 13
                    break;
79 5
80 View Code Duplication
                case self::MATCH_RELATED_FROM:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
81
                    $contentService = $this->repository->getContentService();
82 5
                    $contents = array();
83
                    // allow to specify the objects we relate to using different ways
84
                    $relatingContents = $this->match($values);
85
                    foreach($relatingContents as $relatingContent) {
0 ignored issues
show
Bug introduced by
The expression $relatingContents of type object<Kaliop\eZMigratio...ContentCollection>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
86 13
                        foreach($contentService->loadRelations($relatingContent->contentInfo) as $relatedContent) {
87 13
                            $contents[$relatedContent->contentInfo->id] = $relatedContent;
0 ignored issues
show
Bug introduced by
The property contentInfo does not seem to exist. Did you mean destinationContentInfo?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
88 13
                        }
89 13
                    }
90
                    break;
91 13
92 12
                default:
93 12
94 10
                    // BC support
95
                    if ($key == 'content_type') {
96
                        if (is_int($values[0]) || ctype_digit($values[0])) {
97 11
                            $key = self::MATCH_CONTENT_TYPE_ID;
98
                        } else {
99
                            $key = self::MATCH_CONTENT_TYPE_IDENTIFIER;
100
                        }
101 13
                    }
102
103 13
                    $query = new Query();
104 13
                    $query->limit = $limit != 0 ? $limit : self::INT_MAX_16BIT;
105
                    $query->offset = $offset;
106 13
                    if (isset($query->performCount)) $query->performCount = false;
107
                    $query->filter = $this->getQueryCriterion($key, $values);
108
                    if (!empty($sort)) {
109
                        $query->sortClauses = $this->getSortClauses($sort);
110 13
                    } else {
111
                        switch ($key) {
112
                            case 'content_type_id':
113
                            case self::MATCH_CONTENT_TYPE_ID:
114
                            case 'content_type_identifier':
115
                            case self::MATCH_CONTENT_TYPE_IDENTIFIER:
116
                                // sort objects by depth, lower to higher, so that deleting them has less chances of failure
117
                                // NB: we only do this in eZP versions that allow depth sorting on content queries
118
                                if (class_exists('eZ\Publish\API\Repository\Values\Content\Query\SortClause\LocationDepth')) {
119
                                    $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...
120 2
                                }
121
                        }
122 2
                    }
123 2
124
                    $results = $this->repository->getSearchService()->findContent($query);
125
126
                    $contents = [];
127
                    foreach ($results->searchHits as $result) {
128
                        // make sure we return every object only once
129
                        $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
130
                    }
131
            }
132
133
            return new ContentCollection($contents);
134
135
        }
136
    }
137
138
    /**
139
     * When matching by key, we accept content Id and remote Id only
140
     * @param int|string $key
141
     * @return array
142
     */
143
    protected function getConditionsFromKey($key)
144
    {
145
        if (is_int($key) || ctype_digit($key)) {
146
            return array(self::MATCH_CONTENT_ID => $key);
147
        }
148
        return array(self::MATCH_CONTENT_REMOTE_ID => $key);
149
    }
150
151
    /**
152
     * @param int[] $contentIds
153
     * @return Content[]
154
     * @deprecated
155
     */
156 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...
157
    {
158
        $contents = [];
159
160
        foreach ($contentIds as $contentId) {
161
            // return unique contents
162
            $content = $this->repository->getContentService()->loadContent($contentId);
163
            $contents[$content->contentInfo->id] = $content;
164
        }
165
166
        return $contents;
167
    }
168
169
    /**
170
     * @param string[] $remoteContentIds
171
     * @return Content[]
172
     * @deprecated
173
     */
174 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...
175
    {
176
        $contents = [];
177
178
        foreach ($remoteContentIds as $remoteContentId) {
179
            // return unique contents
180
            $content = $this->repository->getContentService()->loadContentByRemoteId($remoteContentId);
181
            $contents[$content->contentInfo->id] = $content;
182
        }
183
184
        return $contents;
185
    }
186
187
    /**
188
     * @param int[] $locationIds
189
     * @return Content[]
190
     * @deprecated
191
     */
192 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...
193
    {
194
        $contentIds = [];
195
196
        foreach ($locationIds as $locationId) {
197
            $location = $this->repository->getLocationService()->loadLocation($locationId);
198
            // return unique ids
199
            $contentIds[$location->contentId] = $location->contentId;
200
        }
201
202
        return $this->findContentsByContentIds($contentIds);
0 ignored issues
show
Deprecated Code introduced by
The method Kaliop\eZMigrationBundle...dContentsByContentIds() has been deprecated.

This method has been deprecated.

Loading history...
203
    }
204
205
    /**
206
     * @param string[] $remoteLocationIds
207
     * @return Content[]
208
     * @deprecated
209
     */
210 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...
211
    {
212
        $contentIds = [];
213
214
        foreach ($remoteLocationIds as $remoteLocationId) {
215
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($remoteLocationId);
216
            // return unique ids
217
            $contentIds[$location->contentId] = $location->contentId;
218
        }
219
220
        return $this->findContentsByContentIds($contentIds);
0 ignored issues
show
Deprecated Code introduced by
The method Kaliop\eZMigrationBundle...dContentsByContentIds() has been deprecated.

This method has been deprecated.

Loading history...
221
    }
222
223
    /**
224
     * @param int[] $parentLocationIds
225
     * @return Content[]
226
     * @deprecated
227
     */
228 View Code Duplication
    protected function findContentsByParentLocationIds($parentLocationIds)
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...
229
    {
230
        $query = new Query();
231
        $query->limit = self::INT_MAX_16BIT;
232
        if (isset($query->performCount)) $query->performCount = false;
233
        $query->filter = new Query\Criterion\ParentLocationId($parentLocationIds);
234
        $results = $this->repository->getSearchService()->findContent($query);
235
236
        $contents = [];
237
        foreach ($results->searchHits as $result) {
238
            // make sure we return every object only once
239
            $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
240
        }
241
242
        return $contents;
243
    }
244
245
    /**
246
     * @param string[] $remoteParentLocationIds
247
     * @return Content[]
248
     * @deprecated
249
     */
250 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...
251
    {
252
        $locationIds = [];
253
254
        foreach ($remoteParentLocationIds as $remoteParentLocationId) {
255
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($remoteParentLocationId);
256
            // unique locations
257
            $locationIds[$location->id] = $location->id;
258
        }
259
260
        return $this->findContentsByParentLocationIds($locationIds);
0 ignored issues
show
Deprecated Code introduced by
The method Kaliop\eZMigrationBundle...tsByParentLocationIds() has been deprecated.

This method has been deprecated.

Loading history...
261
    }
262
263
    /**
264
     * @param string[] $contentTypeIdentifiers
265
     * @return Content[]
266
     * @deprecated
267
     */
268 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...
269
    {
270
        $query = new Query();
271
        $query->limit = self::INT_MAX_16BIT;
272
        if (isset($query->performCount)) $query->performCount = false;
273
        $query->filter = new Query\Criterion\ContentTypeIdentifier($contentTypeIdentifiers);
274
        // sort objects by depth, lower to higher, so that deleting them has less chances of failure
275
        // NB: we only do this in eZP versions that allow depth sorting on content queries
276
        if (class_exists('eZ\Publish\API\Repository\Values\Content\Query\SortClause\LocationDepth')) {
277
            $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...
278
        }
279
280
        $results = $this->repository->getSearchService()->findContent($query);
281
282
        $contents = [];
283
        foreach ($results->searchHits as $result) {
284
            // make sure we return every object only once
285
            $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
286
        }
287
288
        return $contents;
289
    }
290
291
    /**
292
     * @param int[] $contentTypeIds
293
     * @return Content[]
294
     * @deprecated
295
     */
296 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...
297
    {
298
        $query = new Query();
299
        $query->limit = self::INT_MAX_16BIT;
300
        if (isset($query->performCount)) $query->performCount = false;
301
        $query->filter = new Query\Criterion\ContentTypeId($contentTypeIds);
302
        // sort objects by depth, lower to higher, so that deleting them has less chances of failure
303
        // NB: we only do this in eZP versions that allow depth sorting on content queries
304
        if (class_exists('eZ\Publish\API\Repository\Values\Content\Query\SortClause\LocationDepth')) {
305
            $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...
306
        }
307
        $results = $this->repository->getSearchService()->findContent($query);
308
309
        $contents = [];
310
        foreach ($results->searchHits as $result) {
311
            // make sure we return every object only once
312
            $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
313
        }
314
315
        return $contents;
316
    }
317
318
}
319