Completed
Push — EZP-29984 ( d62455...65bc09 )
by André
18:37
created

FieldIn::getCondition()   B

Complexity

Conditions 7
Paths 17

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 17
nop 1
dl 0
loc 45
rs 8.2666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the FieldIn Field criterion visitor class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\Search\Elasticsearch\Content\CriterionVisitor\Field;
10
11
use eZ\Publish\Core\Search\Elasticsearch\Content\CriterionVisitorDispatcher as Dispatcher;
12
use eZ\Publish\Core\Search\Elasticsearch\Content\CriterionVisitor\Field;
13
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
14
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator;
15
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
16
17
/**
18
 * Visits the Field criterion with IN or EQ operator.
19
 */
20
class FieldIn extends Field
21
{
22
    /**
23
     * Check if visitor is applicable to current criterion.
24
     *
25
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
26
     *
27
     * @return bool
28
     */
29
    public function canVisit(Criterion $criterion)
30
    {
31
        return
32
            $criterion instanceof Criterion\Field &&
33
            (
34
                ($criterion->operator ?: Operator::IN) === Operator::IN ||
35
                $criterion->operator === Operator::EQ ||
36
                $criterion->operator === Operator::CONTAINS ||
37
                $criterion->operator === Operator::LIKE
38
            );
39
    }
40
41
    /**
42
     * Returns nested condition common for filter and query contexts.
43
     *
44
     * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If no searchable fields are found for the given criterion target.
45
     *
46
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
47
     *
48
     * @return array
49
     */
50
    protected function getCondition(Criterion $criterion)
51
    {
52
        $fieldNames = $this->getFieldNames($criterion, $criterion->target);
53
54
        $values = (array)$criterion->value;
55
56
        if (empty($fieldNames)) {
57
            throw new InvalidArgumentException(
58
                '$criterion->target',
59
                "No searchable fields found for the given criterion target '{$criterion->target}'."
60
            );
61
        }
62
63
        $fields = array();
64
        foreach ($fieldNames as $name) {
65
            $fields[] = 'fields_doc.' . $name;
66
        }
67
68
        if ($criterion->target === Operator::LIKE) {
69
            $match = 'regexp';
70
        } else {
71
            $match = 'query';
72
        }
73
74
        $terms = array();
75
        foreach ($values as $value) {
76
            if ($criterion->target === Operator::LIKE) {
77
                $value = strpos($value, '*') === false ? ".*$value.*" : str_replace('*', '.*', $value);
78
            }
79
80
            $terms[] = array(
81
                'multi_match' => array(
82
                    $match => $value,
83
                    'fields' => $fields,
84
                ),
85
            );
86
        }
87
88
        return array(
89
            'bool' => array(
90
                'should' => $terms,
91
                'minimum_should_match' => 1,
92
            ),
93
        );
94
    }
95
96
    /**
97
     * Map field value to a proper Elasticsearch filter representation.
98
     *
99
     * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If no searchable fields are found for the given criterion target.
100
     *
101
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
102
     * @param \eZ\Publish\Core\Search\Elasticsearch\Content\CriterionVisitorDispatcher $dispatcher
103
     * @param array $languageFilter
104
     *
105
     * @return mixed
106
     */
107 View Code Duplication
    public function visitFilter(Criterion $criterion, Dispatcher $dispatcher, array $languageFilter)
108
    {
109
        $filter = array(
110
            'nested' => array(
111
                'path' => 'fields_doc',
112
                'filter' => array(
113
                    'query' => $this->getCondition($criterion),
114
                ),
115
            ),
116
        );
117
118
        $fieldFilter = $this->getFieldFilter($languageFilter);
119
120
        if ($languageFilter !== null) {
121
            $filter['nested']['filter'] = array(
122
                'bool' => array(
123
                    'must' => array(
124
                        $fieldFilter,
125
                        $filter['nested']['filter'],
126
                    ),
127
                ),
128
            );
129
        }
130
131
        return $filter;
132
    }
133
134
    /**
135
     * Map field value to a proper Elasticsearch query representation.
136
     *
137
     * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If no searchable fields are found for the given criterion target.
138
     *
139
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
140
     * @param \eZ\Publish\Core\Search\Elasticsearch\Content\CriterionVisitorDispatcher $dispatcher
141
     * @param array $languageFilter
142
     *
143
     * @return mixed
144
     */
145 View Code Duplication
    public function visitQuery(Criterion $criterion, Dispatcher $dispatcher, array $languageFilter)
146
    {
147
        $fieldFilter = $this->getFieldFilter($languageFilter);
148
149
        if ($fieldFilter === null) {
150
            $query = array(
151
                'nested' => array(
152
                    'path' => 'fields_doc',
153
                    'query' => $this->getCondition($criterion),
154
                ),
155
            );
156
        } else {
157
            $query = array(
158
                'nested' => array(
159
                    'path' => 'fields_doc',
160
                    'query' => array(
161
                        'filtered' => array(
162
                            'query' => $this->getCondition($criterion),
163
                            'filter' => $fieldFilter,
164
                        ),
165
                    ),
166
                ),
167
            );
168
        }
169
170
        return $query;
171
    }
172
}
173