Completed
Push — master ( 3a2d29...d0475e )
by Nicolas
02:57
created

lib/Elastica/Multi/Search.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Elastica\Multi;
3
4
use Elastica\Client;
5
use Elastica\JSON;
6
use Elastica\Request;
7
use Elastica\Search as BaseSearch;
8
9
/**
10
 * Elastica multi search.
11
 *
12
 * @author munkie
13
 *
14
 * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html
15
 */
16
class Search
17
{
18
    /**
19
     * @const string[] valid header options
20
     */
21
    private static $HEADER_OPTIONS = ['index', 'types', 'search_type',
22
                                      'routing', 'preference', ];
23
    /**
24
     * @var MultiBuilderInterface
25
     */
26
    private $_builder;
27
28
    /**
29
     * @var \Elastica\Client
30
     */
31
    protected $_client;
32
33
    /**
34
     * @var array
35
     */
36
    protected $_options = [];
37
38
    /**
39
     * @var array|\Elastica\Search[]
40
     */
41
    protected $_searches = [];
42
43
    /**
44
     * Constructs search object.
45
     *
46
     * @param \Elastica\Client      $client  Client object
47
     * @param MultiBuilderInterface $builder
48
     */
49
    public function __construct(Client $client, MultiBuilderInterface $builder = null)
50
    {
51
        $this->_builder = $builder ?: new MultiBuilder();
52
        $this->_client = $client;
53
    }
54
55
    /**
56
     * @return \Elastica\Client
57
     */
58
    public function getClient()
59
    {
60
        return $this->_client;
61
    }
62
63
    /**
64
     * @return $this
65
     */
66
    public function clearSearches()
67
    {
68
        $this->_searches = [];
69
70
        return $this;
71
    }
72
73
    /**
74
     * @param \Elastica\Search $search
75
     * @param string           $key    Optional key
76
     *
77
     * @return $this
78
     */
79
    public function addSearch(BaseSearch $search, $key = null)
80
    {
81
        if ($key) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $key of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
82
            $this->_searches[$key] = $search;
83
        } else {
84
            $this->_searches[] = $search;
85
        }
86
87
        return $this;
88
    }
89
90
    /**
91
     * @param array|\Elastica\Search[] $searches
92
     *
93
     * @return $this
94
     */
95
    public function addSearches(array $searches)
96
    {
97
        foreach ($searches as $key => $search) {
98
            $this->addSearch($search, $key);
99
        }
100
101
        return $this;
102
    }
103
104
    /**
105
     * @param array|\Elastica\Search[] $searches
106
     *
107
     * @return $this
108
     */
109
    public function setSearches(array $searches)
110
    {
111
        $this->clearSearches();
112
        $this->addSearches($searches);
113
114
        return $this;
115
    }
116
117
    /**
118
     * @return array|\Elastica\Search[]
119
     */
120
    public function getSearches()
121
    {
122
        return $this->_searches;
123
    }
124
125
    /**
126
     * @param string $searchType
127
     *
128
     * @return $this
129
     */
130
    public function setSearchType($searchType)
131
    {
132
        $this->_options[BaseSearch::OPTION_SEARCH_TYPE] = $searchType;
133
134
        return $this;
135
    }
136
137
    /**
138
     * @return \Elastica\Multi\ResultSet
139
     */
140
    public function search()
141
    {
142
        $data = $this->_getData();
143
144
        $response = $this->getClient()->request(
145
            '_msearch',
146
            Request::POST,
147
            $data,
148
            $this->_options
149
        );
150
151
        return $this->_builder->buildMultiResultSet($response, $this->getSearches());
152
    }
153
154
    /**
155
     * @return string
156
     */
157
    protected function _getData()
158
    {
159
        $data = '';
160
        foreach ($this->getSearches() as $search) {
161
            $data .= $this->_getSearchData($search);
162
        }
163
164
        return $data;
165
    }
166
167
    /**
168
     * @param \Elastica\Search $search
169
     *
170
     * @return string
171
     */
172
    protected function _getSearchData(BaseSearch $search)
173
    {
174
        $header = $this->_getSearchDataHeader($search);
175
176
        $header = (empty($header)) ? new \stdClass() : $header;
177
        $query = $search->getQuery();
178
179
        // Keep other query options as part of the search body
180
        $queryOptions = array_diff_key($search->getOptions(), array_flip(self::$HEADER_OPTIONS));
181
182
        $data = JSON::stringify($header)."\n";
183
        $data .= JSON::stringify($query->toArray() + $queryOptions)."\n";
184
185
        return $data;
186
    }
187
188
    /**
189
     * @param \Elastica\Search $search
190
     *
191
     * @return array
192
     */
193
    protected function _getSearchDataHeader(BaseSearch $search)
194
    {
195
        $header = $search->getOptions();
196
197
        if ($search->hasIndices()) {
198
            $header['index'] = $search->getIndices();
199
        }
200
201
        if ($search->hasTypes()) {
202
            $header['types'] = $search->getTypes();
203
        }
204
205
        // Filter options accepted in the "header"
206
        return array_intersect_key($header, array_flip(self::$HEADER_OPTIONS));
207
    }
208
}
209