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

LocationMatcher::getQueryCriterion()   B

Complexity

Conditions 9
Paths 18

Size

Total Lines 36

Duplication

Lines 14
Ratio 38.89 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
dl 14
loc 36
ccs 0
cts 31
cp 0
rs 8.0555
c 0
b 0
f 0
cc 9
nc 18
nop 2
crap 90
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Matcher;
4
5
use eZ\Publish\API\Repository\Values\Content\Query;
6
use Kaliop\eZMigrationBundle\API\Collection\LocationCollection;
7
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
8
use eZ\Publish\API\Repository\Values\Content\Location;
9
10
class LocationMatcher extends QueryBasedMatcher
11
{
12
    use FlexibleKeyMatcherTrait;
13
14
    const MATCH_DEPTH = 'depth';
15
    const MATCH_IS_MAIN_LOCATION = 'is_main_location';
16
    const MATCH_PRIORITY = 'priority';
17
18
    protected $allowedConditions = array(
19
        self::MATCH_AND, self::MATCH_OR, self::MATCH_NOT,
20
        self::MATCH_CONTENT_ID, self::MATCH_LOCATION_ID, self::MATCH_CONTENT_REMOTE_ID, self::MATCH_LOCATION_REMOTE_ID,
21
        self::MATCH_ATTRIBUTE, self::MATCH_CONTENT_TYPE_ID, self::MATCH_CONTENT_TYPE_IDENTIFIER, self::MATCH_GROUP,
22
        self::MATCH_CREATION_DATE, self::MATCH_MODIFICATION_DATE, self::MATCH_OBJECT_STATE, self::MATCH_OWNER,
23
        self::MATCH_PARENT_LOCATION_ID, self::MATCH_PARENT_LOCATION_REMOTE_ID, self::MATCH_SECTION, self::MATCH_SUBTREE,
24
        self::MATCH_VISIBILITY,
25
        // aliases
26
        'content_type', 'content_type_id', 'content_type_identifier',
27
        // location-only
28
        self::MATCH_DEPTH, self::MATCH_IS_MAIN_LOCATION, self::MATCH_PRIORITY,
29
    );
30
    protected $returns = 'Location';
31
32
    /**
33
     * @param array $conditions key: condition, value: int / string / int[] / string[]
34
     * @return LocationCollection
35
     */
36
    public function match(array $conditions)
37
    {
38
        return $this->matchLocation($conditions);
39
    }
40
41
    /**
42
     * @param array $conditions key: condition, value: value: int / string / int[] / string[]
43
     * @return LocationCollection
44
     */
45 View Code Duplication
    public function matchLocation(array $conditions)
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...
46
    {
47
        $this->validateConditions($conditions);
48
49
        foreach ($conditions as $key => $values) {
50
51
            $query = new LocationQuery();
52
            $query->limit = self::INT_MAX_16BIT;
53
            if (isset($query->performCount)) $query->performCount = false;
54
            $query->filter = $this->getQueryCriterion($key, $values);
55
            $results = $this->repository->getSearchService()->findLocations($query);
56
57
            $locations = [];
58
            foreach ($results->searchHits as $result) {
59
                $locations[$result->valueObject->id] = $result->valueObject;
60
            }
61
62
            return new LocationCollection($locations);
63
        }
64
    }
65
66
    /**
67
     * When matching by key, we accept location Id and remote Id only
68
     * @param int|string $key
69
     * @return array
70
     */
71
    protected function getConditionsFromKey($key)
72
    {
73
        if (is_int($key) || ctype_digit($key)) {
74
            return array(self::MATCH_LOCATION_ID => $key);
75
        }
76
        return array(self::MATCH_LOCATION_REMOTE_ID => $key);
77
    }
78
79
    protected function getQueryCriterion($key, $values)
80
    {
81
        if (!is_array($values)) {
82
            $values = array($values);
83
        }
84
85
        switch ($key) {
86 View Code Duplication
            case self::MATCH_DEPTH:
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...
87
                $match = reset($values);
88
                $operator = key($values);
89
                if (!isset(self::$operatorsMap[$operator])) {
90
                    throw new \Exception("Can not use '$operator' as comparison operator for depth");
91
                }
92
                return new Query\Criterion\Location\Depth(self::$operatorsMap[$operator], $match);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \eZ\Publish\A...ap[$operator], $match); (eZ\Publish\API\Repositor...riterion\Location\Depth) is incompatible with the return type of the parent method Kaliop\eZMigrationBundle...cher::getQueryCriterion of type eZ\Publish\API\Repositor...ry\Criterion\LogicalNot.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
93
94
            case self::MATCH_IS_MAIN_LOCATION:
95
            case 'is_main':
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...
96
                /// @todo error/warning if there is more than 1 value...
97
                $value = reset($values);
98
                if ($value) {
99
                    return new Query\Criterion\Location\IsMainLocation(Query\Criterion\Location\IsMainLocation::MAIN);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \eZ\Publish\A...\IsMainLocation::MAIN); (eZ\Publish\API\Repositor...Location\IsMainLocation) is incompatible with the return type of the parent method Kaliop\eZMigrationBundle...cher::getQueryCriterion of type eZ\Publish\API\Repositor...ry\Criterion\LogicalNot.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
100
                } else {
101
                    return new Query\Criterion\Location\IsMainLocation(Query\Criterion\Location\IsMainLocation::NOT_MAIN);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \eZ\Publish\A...ainLocation::NOT_MAIN); (eZ\Publish\API\Repositor...Location\IsMainLocation) is incompatible with the return type of the parent method Kaliop\eZMigrationBundle...cher::getQueryCriterion of type eZ\Publish\API\Repositor...ry\Criterion\LogicalNot.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
102
                }
103
104 View Code Duplication
            case self::MATCH_PRIORITY:
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...
105
                $match = reset($values);
106
                $operator = key($values);
107
                if (!isset(self::$operatorsMap[$operator])) {
108
                    throw new \Exception("Can not use '$operator' as comparison operator for depth");
109
                }
110
                return new Query\Criterion\Location\Priority(self::$operatorsMap[$operator], $match);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \eZ\Publish\A...ap[$operator], $match); (eZ\Publish\API\Repositor...erion\Location\Priority) is incompatible with the return type of the parent method Kaliop\eZMigrationBundle...cher::getQueryCriterion of type eZ\Publish\API\Repositor...ry\Criterion\LogicalNot.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
111
        }
112
113
        return parent::getQueryCriterion($key, $values);
114
    }
115
116
    /**
117
     * Returns all locations of a set of objects
118
     *
119
     * @param int[] $contentIds
120
     * @return Location[]
121
     * @deprecated
122
     */
123 View Code Duplication
    protected function findLocationsByContentIds(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...
124
    {
125
        $locations = [];
126
127
        foreach ($contentIds as $contentId) {
128
            $content = $this->repository->getContentService()->loadContent($contentId);
129
            foreach($this->repository->getLocationService()->loadLocations($content->contentInfo) as $location) {
130
                $locations[$location->id] = $location;
131
            }
132
        }
133
134
        return $locations;
135
    }
136
137
    /**
138
     * Returns all locations of a set of objects
139
     *
140
     * @param int[] $remoteContentIds
141
     * @return Location[]
142
     * @deprecated
143
     */
144 View Code Duplication
    protected function findLocationsByContentRemoteIds(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...
145
    {
146
        $locations = [];
147
148
        foreach ($remoteContentIds as $remoteContentId) {
149
            $content = $this->repository->getContentService()->loadContentByRemoteId($remoteContentId);
150
            foreach($this->repository->getLocationService()->loadLocations($content->contentInfo) as $location) {
151
                $locations[$location->id] = $location;
152
            }
153
        }
154
155
        return $locations;
156
    }
157
158
    /**
159
     * @param int[] $locationIds
160
     * @return Location[]
161
     * @deprecated
162
     */
163
    protected function findLocationsByLocationIds(array $locationIds)
164
    {
165
        $locations = [];
166
167
        foreach ($locationIds as $locationId) {
168
            $locations[$locationId] = $this->repository->getLocationService()->loadLocation($locationId);
169
        }
170
171
        return $locations;
172
    }
173
174
    /**
175
     * @param int[] $locationRemoteIds
176
     * @return Location[]
177
     * @deprecated
178
     */
179
    protected function findLocationsByLocationRemoteIds($locationRemoteIds)
180
    {
181
        $locations = [];
182
183
        foreach ($locationRemoteIds as $locationRemoteId) {
184
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($locationRemoteId);
185
            $locations[$location->id] = $location;
186
        }
187
188
        return $locations;
189
    }
190
191
    /**
192
     * @param int[] $parentLocationIds
193
     * @return Location[]
194
     * @deprecated
195
     */
196 View Code Duplication
    protected function findLocationsByParentLocationIds($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...
197
    {
198
        $query = new LocationQuery();
199
        $query->limit = self::INT_MAX_16BIT;
200
        if (isset($query->performCount)) $query->performCount = false;
201
        $query->filter = new Query\Criterion\ParentLocationId($parentLocationIds);
202
203
        $results = $this->repository->getSearchService()->findLocations($query);
204
205
        $locations = [];
206
207
        foreach ($results->searchHits as $result) {
208
            $locations[$result->valueObject->id] = $result->valueObject;
209
        }
210
211
        return $locations;
212
    }
213
214
    /**
215
     * @param int[] $parentLocationRemoteIds
216
     * @return Location[]
217
     * @deprecated
218
     */
219 View Code Duplication
    protected function findLocationsByParentLocationRemoteIds($parentLocationRemoteIds)
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...
220
    {
221
        $locationIds = [];
222
223
        foreach ($parentLocationRemoteIds as $parentLocationRemoteId) {
224
            $location = $this->repository->getLocationService()->loadLocationByRemoteId($parentLocationRemoteId);
225
            $locationIds[$location->id] = $location->id;
226
        }
227
228
        return $this->findLocationsByParentLocationIds($locationIds);
0 ignored issues
show
Deprecated Code introduced by
The method Kaliop\eZMigrationBundle...nsByParentLocationIds() has been deprecated.

This method has been deprecated.

Loading history...
229
    }
230
}
231