Completed
Push — EZP-29984 ( 65bc09...6aa958 )
by André
25:18
created

FieldIn::getCondition()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 5
nop 1
dl 0
loc 35
rs 9.36
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
            );
38
    }
39
40
    /**
41
     * Returns nested condition common for filter and query contexts.
42
     *
43
     * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If no searchable fields are found for the given criterion target.
44
     *
45
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
46
     *
47
     * @return array
48
     */
49
    protected function getCondition(Criterion $criterion)
50
    {
51
        $fieldNames = $this->getFieldNames($criterion, $criterion->target);
52
53
        $values = (array)$criterion->value;
54
55
        if (empty($fieldNames)) {
56
            throw new InvalidArgumentException(
57
                '$criterion->target',
58
                "No searchable fields found for the given criterion target '{$criterion->target}'."
59
            );
60
        }
61
62
        $fields = array();
63
        foreach ($fieldNames as $name) {
64
            $fields[] = 'fields_doc.' . $name;
65
        }
66
67
        $terms = array();
68
        foreach ($values as $value) {
69
            $terms[] = array(
70
                'multi_match' => array(
71
                    'query' => $value,
72
                    'fields' => $fields,
73
                ),
74
            );
75
        }
76
77
        return array(
78
            'bool' => array(
79
                'should' => $terms,
80
                'minimum_should_match' => 1,
81
            ),
82
        );
83
    }
84
85
    /**
86
     * Map field value to a proper Elasticsearch filter representation.
87
     *
88
     * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If no searchable fields are found for the given criterion target.
89
     *
90
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
91
     * @param \eZ\Publish\Core\Search\Elasticsearch\Content\CriterionVisitorDispatcher $dispatcher
92
     * @param array $languageFilter
93
     *
94
     * @return mixed
95
     */
96 View Code Duplication
    public function visitFilter(Criterion $criterion, Dispatcher $dispatcher, array $languageFilter)
97
    {
98
        $filter = array(
99
            'nested' => array(
100
                'path' => 'fields_doc',
101
                'filter' => array(
102
                    'query' => $this->getCondition($criterion),
103
                ),
104
            ),
105
        );
106
107
        $fieldFilter = $this->getFieldFilter($languageFilter);
108
109
        if ($languageFilter !== null) {
110
            $filter['nested']['filter'] = array(
111
                'bool' => array(
112
                    'must' => array(
113
                        $fieldFilter,
114
                        $filter['nested']['filter'],
115
                    ),
116
                ),
117
            );
118
        }
119
120
        return $filter;
121
    }
122
123
    /**
124
     * Map field value to a proper Elasticsearch query representation.
125
     *
126
     * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If no searchable fields are found for the given criterion target.
127
     *
128
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
129
     * @param \eZ\Publish\Core\Search\Elasticsearch\Content\CriterionVisitorDispatcher $dispatcher
130
     * @param array $languageFilter
131
     *
132
     * @return mixed
133
     */
134 View Code Duplication
    public function visitQuery(Criterion $criterion, Dispatcher $dispatcher, array $languageFilter)
135
    {
136
        $fieldFilter = $this->getFieldFilter($languageFilter);
137
138
        if ($fieldFilter === null) {
139
            $query = array(
140
                'nested' => array(
141
                    'path' => 'fields_doc',
142
                    'query' => $this->getCondition($criterion),
143
                ),
144
            );
145
        } else {
146
            $query = array(
147
                'nested' => array(
148
                    'path' => 'fields_doc',
149
                    'query' => array(
150
                        'filtered' => array(
151
                            'query' => $this->getCondition($criterion),
152
                            'filter' => $fieldFilter,
153
                        ),
154
                    ),
155
                ),
156
            );
157
        }
158
159
        return $query;
160
    }
161
}
162