Completed
Push — master ( 5a501b...3982a6 )
by Gaetano
08:04
created

QueryBasedMatcher::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 10
cp 0
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 5
crap 2
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\Repository;
7
use Kaliop\eZMigrationBundle\API\KeyMatcherInterface;
8
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator;
9
10
/**
11
 * @todo extend to allow matching by modifier, language code, content_type_group_id
12
 */
13
abstract class QueryBasedMatcher extends RepositoryMatcher
14
{
15
    const MATCH_CONTENT_ID = 'content_id';
16
    const MATCH_LOCATION_ID = 'location_id';
17
    const MATCH_CONTENT_REMOTE_ID = 'content_remote_id';
18
    const MATCH_LOCATION_REMOTE_ID = 'location_remote_id';
19
    const MATCH_ATTRIBUTE = 'attribute';
20
    const MATCH_CONTENT_TYPE_ID = 'contenttype_id';
21
    const MATCH_CONTENT_TYPE_IDENTIFIER = 'contenttype_identifier';
22
    const MATCH_CREATION_DATE = 'creation_date';
23
    const MATCH_GROUP = 'group';
24
    const MATCH_MODIFICATION_DATE = 'modification_date';
25
    const MATCH_OBJECT_STATE = 'object_state';
26
    const MATCH_OWNER = 'owner';
27
    const MATCH_PARENT_LOCATION_ID = 'parent_location_id';
28
    const MATCH_PARENT_LOCATION_REMOTE_ID = 'parent_location_remote_id';
29
    const MATCH_SECTION = 'section';
30
    const MATCH_SUBTREE = 'subtree';
31
    const MATCH_VISIBILITY = 'visibility';
32
33
    // useful f.e. when talking to Solr, which defaults to java integers for max nr of items for queries
34
    const INT_MAX_16BIT = 2147483647;
35
36
    static protected $operatorsMap = array(
37
        'eq' => Operator::EQ,
38
        'gt' => Operator::GT,
39
        'gte' => Operator::GTE,
40
        'lt' => Operator::LT,
41
        'lte' => Operator::LTE,
42
        'in' => Operator::IN,
43
        'between' => Operator::BETWEEN,
44
        'like' => Operator::LIKE,
45
        'contains' => Operator::CONTAINS,
46
        Operator::EQ => Operator::EQ,
47
        Operator::GT => Operator::GT,
48
        Operator::GTE => Operator::GTE,
49
        Operator::LT => Operator::LT,
50
        Operator::LTE => Operator::LTE,
51
    );
52
53
    /** @var  KeyMatcherInterface $groupMatcher */
54
    protected $groupMatcher;
55
    /** @var  KeyMatcherInterface $sectionMatcher */
56
    protected $sectionMatcher;
57
    /** @var  KeyMatcherInterface $stateMatcher */
58
    protected $stateMatcher;
59
    /** @var  KeyMatcherInterface $userMatcher */
60
    protected $userMatcher;
61
62
    /**
63
     * @param Repository $repository
64
     * @param KeyMatcherInterface $groupMatcher
65
     * @param KeyMatcherInterface $sectionMatcher
66
     * @param KeyMatcherInterface $stateMatcher
67
     * @param KeyMatcherInterface $userMatcher
68
     * @todo inject the services needed, not the whole repository
69
     */
70
    public function __construct(Repository $repository, KeyMatcherInterface $groupMatcher = null,
0 ignored issues
show
Unused Code introduced by
The parameter $groupMatcher is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
71
        KeyMatcherInterface $sectionMatcher = null, KeyMatcherInterface $stateMatcher = null,
72
        KeyMatcherInterface $userMatcher = null)
73
    {
74
        parent::__construct($repository);
75
        $this->userMatcher = $userMatcher;
76
        $this->sectionMatcher = $sectionMatcher;
77
        $this->stateMatcher = $stateMatcher;
78
        $this->userMatcher = $userMatcher;
79
    }
80
81
    /**
82
     * @param $key
83
     * @param $values
84
     * @return mixed should it be \eZ\Publish\API\Repository\Values\Content\Query\CriterionInterface ?
85
     * @throws \Exception for unsupported keys
86
     */
87
    protected function getQueryCriterion($key, $values)
88
    {
89
        if (!is_array($values)) {
90
            $values = array($values);
91
        }
92
93
        switch ($key) {
94
            case self::MATCH_CONTENT_ID:
95
                return new Query\Criterion\ContentId($values);
96
97
            case self::MATCH_LOCATION_ID:
98
                // NB: seems to cause problems with EZP 2014.3
99
                return new Query\Criterion\LocationId(reset($values));
100
101
            case self::MATCH_CONTENT_REMOTE_ID:
102
                return new Query\Criterion\RemoteId($values);
103
104
            case self::MATCH_LOCATION_REMOTE_ID:
105
                return new Query\Criterion\LocationRemoteId($values);
106
107
            case self::MATCH_ATTRIBUTE:
108
                $spec = reset($values);
109
                $attribute = key($values);
110
                $match = reset($spec);
111
                $operator = key($spec);
112
                if (!isset(self::$operatorsMap[$operator])) {
113
                    throw new \Exception("Can not use '$operator' as comparison operator for attributes");
114
                }
115
                return new Query\Criterion\Field($attribute, self::$operatorsMap[$operator], $match);
116
117
            case 'content_type_id':
118
            case self::MATCH_CONTENT_TYPE_ID:
119
                return new Query\Criterion\ContentTypeId($values);
120
121
            case 'content_type_identifier':
122
            case self::MATCH_CONTENT_TYPE_IDENTIFIER:
123
                return new Query\Criterion\ContentTypeIdentifier($values);
124
125 View Code Duplication
            case self::MATCH_CREATION_DATE:
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...
126
                $match = reset($values);
127
                $operator = key($values);
128
                if (!isset(self::$operatorsMap[$operator])) {
129
                    throw new \Exception("Can not use '$operator' as comparison operator for dates");
130
                }
131
                return new Query\Criterion\DateMetadata(Query\Criterion\DateMetadata::CREATED, self::$operatorsMap[$operator], $match);
132
133 View Code Duplication
            case self::MATCH_GROUP:
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...
134
                foreach($values as &$value) {
135
                    if (!ctype_digit($value)) {
136
                        $value = $this->groupMatcher->matchOneByKey($value)->id;
137
                    }
138
                }
139
                return new Query\Criterion\UserMetadata(Query\Criterion\UserMetadata::GROUP, Operator::IN, $values);
140
141 View Code Duplication
            case self::MATCH_MODIFICATION_DATE:
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...
142
                $match = reset($values);
143
                $operator = key($values);
144
                if (!isset(self::$operatorsMap[$operator])) {
145
                    throw new \Exception("Can not use '$operator' as comparison operator for dates");
146
                }
147
                return new Query\Criterion\DateMetadata(Query\Criterion\DateMetadata::MODIFIED, self::$operatorsMap[$operator], $match);
148
149 View Code Duplication
            case self::MATCH_OBJECT_STATE:
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...
150
                foreach($values as &$value) {
151
                    if (!ctype_digit($value)) {
152
                        $value = $this->stateMatcher->matchOneByKey($value)->id;
153
                    }
154
                }
155
                return new Query\Criterion\ObjectStateId($values);
156
157 View Code Duplication
            case self::MATCH_OWNER:
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...
158
                foreach($values as &$value) {
159
                    if (!ctype_digit($value)) {
160
                        $value = $this->userMatcher->matchOneByKey($value)->id;
161
                    }
162
                }
163
                return new Query\Criterion\UserMetadata(Query\Criterion\UserMetadata::OWNER, Operator::IN, $values);
164
165
            case self::MATCH_PARENT_LOCATION_ID:
166
                return new Query\Criterion\ParentLocationId($values);
167
168
            case self::MATCH_PARENT_LOCATION_REMOTE_ID:
169
                $locationIds = [];
170
                foreach ($values as $remoteParentLocationId) {
171
                    $location = $this->repository->getLocationService()->loadLocationByRemoteId($remoteParentLocationId);
172
                    // unique locations
173
                    $locationIds[$location->id] = $location->id;
174
                }
175
                return new Query\Criterion\ParentLocationId($locationIds);
176
177 View Code Duplication
            case self::MATCH_SECTION:
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...
178
                foreach($values as &$value) {
179
                    if (!ctype_digit($value)) {
180
                        $value = $this->sectionMatcher->matchOneByKey($value)->id;
181
                    }
182
                }
183
                return new Query\Criterion\SectionId($values);
184
185
            case self::MATCH_SUBTREE:
186
                return new Query\Criterion\Subtree($values);
187
188
            case self::MATCH_VISIBILITY:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
189
                /// @todo error/warning if there is more than 1 value...
190
                $value = reset($values);
191
                if ($value) {
192
                    return new Query\Criterion\Visibility(Query\Criterion\Visibility::VISIBLE);
193
                } else {
194
                    return new Query\Criterion\Visibility(Query\Criterion\Visibility::HIDDEN);
195
                }
196
197 View Code Duplication
            case self::MATCH_AND:
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...
198
                $subCriteria = array();
199
                foreach($values as $subCriterion) {
200
                    $value = reset($subCriterion);
201
                    $subCriteria[] = $this->getQueryCriterion(key($subCriterion), $value);
202
                }
203
                return new Query\Criterion\LogicalAnd($subCriteria);
204
205 View Code Duplication
            case self::MATCH_OR:
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...
206
                $subCriteria = array();
207
                foreach($values as $subCriterion) {
208
                    $value = reset($subCriterion);
209
                    $subCriteria[] = $this->getQueryCriterion(key($subCriterion), $value);
210
                }
211
                return new Query\Criterion\LogicalOr($subCriteria);
212
213
            case self::MATCH_NOT:
214
                /// @todo throw if more than one sub-criteria found
215
                $value = reset($values);
216
                $subCriterion = $this->getQueryCriterion(key($values), $value);
217
                return new Query\Criterion\LogicalNot($subCriterion);
218
219
            default:
220
                throw new \Exception($this->returns . " can not be matched because matching condition '$key' is not supported. Supported conditions are: " .
221
                    implode(', ', $this->allowedConditions));
222
        }
223
    }
224
}
225