Completed
Pull Request — master (#90)
by Andreas
10:43
created

ContentMatcher::matchContent()   C

Complexity

Conditions 15
Paths 67

Size

Total Lines 48
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 17.7662

Importance

Changes 0
Metric Value
dl 0
loc 48
ccs 20
cts 26
cp 0.7692
rs 5.0127
c 0
b 0
f 0
cc 15
eloc 29
nc 67
nop 1
crap 17.7662

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\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 extend to allow matching on multiple conditions (AND)
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_CONTENT_ID, self::MATCH_LOCATION_ID, self::MATCH_CONTENT_REMOTE_ID, self::MATCH_LOCATION_REMOTE_ID,
28
        self::MATCH_PARENT_LOCATION_ID, self::MATCH_PARENT_LOCATION_REMOTE_ID, self::MATCH_CONTENT_TYPE_IDENTIFIER,
29
        // aliases
30
        'content_type', 'content_type_id', 'content_type_identifier'
31
    );
32
    protected $returns = 'Content';
33 3
34
    /**
35 3
     * @param array $conditions key: condition, value: int / string / int[] / string[]
36
     * @return ContentCollection
37
     */
38
    public function match(array $conditions)
39
    {
40
        return $this->matchContent($conditions);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->matchContent($conditions); of type Kaliop\eZMigrationBundle...\ContentCollection|null adds the type Kaliop\eZMigrationBundle...ction\ContentCollection to the return on line 40 which is incompatible with the return type declared by the interface Kaliop\eZMigrationBundle...MatcherInterface::match of type array|Kaliop\eZMigrationBundle\API\ArrayObject.
Loading history...
41
    }
42 3
43
    /**
44 3
     * @param array $conditions key: condition, value: int / string / int[] / string[]
45
     * @return ContentCollection
46 3
     */
47
    public function matchContent(array $conditions)
48 3
    {
49 3
        $this->validateConditions($conditions);
50 3
51
        foreach ($conditions as $key => $values) {
52
53 3
            if (!is_array($values)) {
54 3
                $values = array($values);
55
            }
56 2
57 1
            // BC support
58
            if ($key == 'content_type') {
59 2
                if (ctype_digit($key)) {
60
                    $key = self::MATCH_CONTENT_TYPE_ID;
61
                } else {
62 2
                    $key = self::MATCH_CONTENT_TYPE_IDENTIFIER;
63
                }
64
            }
65 2
66
            switch ($key) {
67
                case self::MATCH_CONTENT_ID:
68 2
                   return new ContentCollection($this->findContentsByContentIds($values));
69
70
                case self::MATCH_LOCATION_ID:
71 2
                    return new ContentCollection($this->findContentsByLocationIds($values));
72 2
73
                case self::MATCH_CONTENT_REMOTE_ID:
74
                    return new ContentCollection($this->findContentsByContentRemoteIds($values));
75
76
                case self::MATCH_LOCATION_REMOTE_ID:
77
                    return new ContentCollection($this->findContentsByLocationRemoteIds($values));
78
79
                case self::MATCH_PARENT_LOCATION_ID:
80
                    return new ContentCollection($this->findContentsByParentLocationIds($values));
81 3
82
                case self::MATCH_PARENT_LOCATION_REMOTE_ID:
83 3
                    return new ContentCollection($this->findContentsByParentLocationRemoteIds($values));
84
85 3
                case 'content_type_id':
86
                case self::MATCH_CONTENT_TYPE_ID:
87 3
                    return new ContentCollection($this->findContentsByContentTypeIds($values));
88 3
89 3
                case 'content_type_identifier':
90
                case self::MATCH_CONTENT_TYPE_IDENTIFIER:
91 3
                    return new ContentCollection($this->findContentsByContentTypeIdentifiers($values));
92
            }
93
        }
94
    }
95
96
    /**
97
     * When matching by key, we accept content Id and remote Id only
98
     * @param int|string $key
99
     * @return array
100
     */
101
    protected function getConditionsFromKey($key)
102
    {
103
        if (is_int($key) || ctype_digit($key)) {
104
            return array(self::MATCH_CONTENT_ID => $key);
105
        }
106
        return array(self::MATCH_CONTENT_REMOTE_ID => $key);
107
    }
108
109
    /**
110
     * @param int[] $contentIds
111
     * @return Content[]
112
     */
113 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...
114
    {
115 1
        $contents = [];
116
117 1
        foreach ($contentIds as $contentId) {
118
            // return unique contents
119 1
            $content = $this->repository->getContentService()->loadContent($contentId);
120 1
            $contents[$content->contentInfo->id] = $content;
121
        }
122 1
123 1
        return $contents;
124
    }
125 1
126
    /**
127
     * @param string[] $remoteContentIds
128
     * @return Content[]
129
     */
130 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...
131
    {
132
        $contents = [];
133
134
        foreach ($remoteContentIds as $remoteContentId) {
135
            // return unique contents
136
            $content = $this->repository->getContentService()->loadContentByRemoteId($remoteContentId);
137
            $contents[$content->contentInfo->id] = $content;
138
        }
139
140
        return $contents;
141
    }
142
143
    /**
144
     * @param int[] $locationIds
145
     * @return Content[]
146
     */
147 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...
148
    {
149
        $contentIds = [];
150
151
        foreach ($locationIds as $locationId) {
152
            $location = $this->repository->getLocationService()->loadLocation($locationId);
153
            // return unique ids
154
            $contentIds[$location->contentId] = $location->contentId;
155
        }
156
157
        return $this->findContentsByContentIds($contentIds);
158
    }
159
160
    /**
161
     * @param string[] $remoteLocationIds
162
     * @return Content[]
163
     */
164 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...
165
    {
166
        $contentIds = [];
167
168
        foreach ($remoteLocationIds as $remoteLocationId) {
169
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($remoteLocationId);
170
            // return unique ids
171
            $contentIds[$location->contentId] = $location->contentId;
172
        }
173
174
        return $this->findContentsByContentIds($contentIds);
175
    }
176
177
    /**
178
     * @param int[] $parentLocationIds
179
     * @return Content[]
180
     */
181
    protected function findContentsByParentLocationIds($parentLocationIds)
182
    {
183
        $query = new Query();
184
        $query->limit = PHP_INT_MAX;
185
        $query->filter = new Query\Criterion\ParentLocationId($parentLocationIds);
186 2
        $results = $this->repository->getSearchService()->findContent($query);
187
188 2
        $contents = [];
189 2
        foreach ($results->searchHits as $result) {
190 2
            // make sure we return every object only once
191
            $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
192
        }
193 2
194 2
        return $contents;
195
    }
196 2
197 2
    /**
198
     * @param string[] $remoteParentLocationIds
199 2
     * @return Content[]
200 2
     */
201 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...
202 2
    {
203
        $locationIds = [];
204
205
        foreach ($remoteParentLocationIds as $remoteParentLocationId) {
206
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($remoteParentLocationId);
207
            // unique locations
208
            $locationIds[$location->id] = $location->id;
209
        }
210
211
        return $this->findContentsByParentLocationIds($locationIds);
212
    }
213
214
    /**
215
     * @param string[] $contentTypeIdentifiers
216
     * @return Content[]
217
     */
218 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...
219
    {
220
        $query = new Query();
221
        $query->limit = PHP_INT_MAX;
222
        $query->filter = new Query\Criterion\ContentTypeIdentifier($contentTypeIdentifiers);
223
        // sort objects by depth, lower to higher, so that deleting them has less chances of failure
224
        // NB: we only do this in eZP versions that allow depth sorting on content queries
225
        if (class_exists('eZ\Publish\API\Repository\Values\Content\Query\SortClause\LocationDepth')) {
226
            $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...
227
        }
228
229
        $results = $this->repository->getSearchService()->findContent($query);
230
231
        $contents = [];
232
        foreach ($results->searchHits as $result) {
233
            // make sure we return every object only once
234
            $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
235
        }
236
237
        return $contents;
238
    }
239
240
    /**
241
     * @param int[] $contentTypeIds
242
     * @return Content[]
243
     */
244 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...
245
    {
246
        $query = new Query();
247
        $query->limit = PHP_INT_MAX;
248
        $query->filter = new Query\Criterion\ContentTypeId($contentTypeIds);
249
        // sort objects by depth, lower to higher, so that deleting them has less chances of failure
250
        // NB: we only do this in eZP versions that allow depth sorting on content queries
251
        if (class_exists('eZ\Publish\API\Repository\Values\Content\Query\SortClause\LocationDepth')) {
252
            $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...
253
        }
254
        $results = $this->repository->getSearchService()->findContent($query);
255
256
        $contents = [];
257
        foreach ($results->searchHits as $result) {
258
            // make sure we return every object only once
259
            $contents[$result->valueObject->contentInfo->id] = $result->valueObject;
260
        }
261
262
        return $contents;
263
    }
264
}
265