1<?php
2
3namespace Elastica;
4
5/**
6 * Elastica result item.
7 *
8 * Stores all information from a result
9 *
10 * @author Nicolas Ruflin <spam@ruflin.com>
11 */
12class Result
13{
14    /**
15     * Hit array.
16     *
17     * @var array Hit array
18     */
19    protected $_hit = [];
20
21    /**
22     * Constructs a single results object.
23     *
24     * @param array $hit Hit data
25     */
26    public function __construct(array $hit)
27    {
28        $this->_hit = $hit;
29    }
30
31    /**
32     * Returns a param from the result hit array.
33     *
34     * This function can be used to retrieve all data for which a specific
35     * function doesn't exist.
36     * If the param does not exist, an empty array is returned
37     *
38     * @param string $name Param name
39     *
40     * @return mixed Result data
41     */
42    public function getParam($name)
43    {
44        if (isset($this->_hit[$name])) {
45            return $this->_hit[$name];
46        }
47
48        return [];
49    }
50
51    /**
52     * Test if a param from the result hit is set.
53     *
54     * @param string $name Param name to test
55     *
56     * @return bool True if the param is set, false otherwise
57     */
58    public function hasParam($name)
59    {
60        return isset($this->_hit[$name]);
61    }
62
63    /**
64     * Returns the hit id.
65     *
66     * @return string Hit id
67     */
68    public function getId()
69    {
70        return $this->getParam('_id');
71    }
72
73    /**
74     * Returns the type of the result.
75     *
76     * @return string Result type
77     */
78    public function getType()
79    {
80        return $this->getParam('_type');
81    }
82
83    /**
84     * Returns list of fields.
85     *
86     * @return array Fields list
87     */
88    public function getFields()
89    {
90        return $this->getParam('fields');
91    }
92
93    /**
94     * Returns whether result has fields.
95     *
96     * @return bool
97     */
98    public function hasFields()
99    {
100        return $this->hasParam('fields');
101    }
102
103    /**
104     * Returns the index name of the result.
105     *
106     * @return string Index name
107     */
108    public function getIndex()
109    {
110        return $this->getParam('_index');
111    }
112
113    /**
114     * Returns the score of the result.
115     *
116     * @return float Result score
117     */
118    public function getScore()
119    {
120        return $this->getParam('_score');
121    }
122
123    /**
124     * Returns the raw hit array.
125     *
126     * @return array Hit array
127     */
128    public function getHit()
129    {
130        return $this->_hit;
131    }
132
133    /**
134     * Returns the version information from the hit.
135     *
136     * @return string|int Document version
137     */
138    public function getVersion()
139    {
140        return $this->getParam('_version');
141    }
142
143    /**
144     * Returns inner hits.
145     *
146     * @return array Fields list
147     */
148    public function getInnerHits()
149    {
150        return $this->getParam('inner_hits');
151    }
152
153    /**
154     * Returns whether result has inner hits.
155     *
156     * @return bool
157     */
158    public function hasInnerHits()
159    {
160        return $this->hasParam('inner_hits');
161    }
162
163    /**
164     * Returns result data.
165     *
166     * Checks for partial result data with getFields, falls back to getSource or both
167     *
168     * @return array Result data array
169     */
170    public function getData()
171    {
172        if (isset($this->_hit['fields'])) {
173            return isset($this->_hit['_source'])
174                ? \array_merge($this->getFields(), $this->getSource())
175                : $this->getFields();
176        }
177
178        return $this->getSource();
179    }
180
181    /**
182     * Returns the result source.
183     *
184     * @return array Source data array
185     */
186    public function getSource()
187    {
188        return $this->getParam('_source');
189    }
190
191    /**
192     * Returns result data.
193     *
194     * @return array Result data array
195     */
196    public function getHighlights()
197    {
198        return $this->getParam('highlight');
199    }
200
201    /**
202     * Returns explanation on how its score was computed.
203     *
204     * @return array explanations
205     */
206    public function getExplanation()
207    {
208        return $this->getParam('_explanation');
209    }
210
211    /**
212     * Returns Document.
213     *
214     * @return Document
215     */
216    public function getDocument()
217    {
218        $doc = new Document();
219        $doc->setData($this->getSource());
220        $hit = $this->getHit();
221        unset($hit['_source']);
222        unset($hit['_explanation']);
223        unset($hit['highlight']);
224        unset($hit['_score']);
225        $doc->setParams($hit);
226
227        return $doc;
228    }
229
230    /**
231     * Sets a parameter on the hit.
232     *
233     * @param string $param
234     * @param mixed  $value
235     */
236    public function setParam($param, $value)
237    {
238        $this->_hit[$param] = $value;
239    }
240
241    /**
242     * Magic function to directly access keys inside the result.
243     *
244     * Returns null if key does not exist
245     *
246     * @param string $key Key name
247     *
248     * @return mixed Key value
249     */
250    public function __get($key)
251    {
252        $source = $this->getData();
253
254        return $source[$key] ?? null;
255    }
256
257    /**
258     * Magic function to support isset() calls.
259     *
260     * @param string $key Key name
261     *
262     * @return bool
263     */
264    public function __isset($key)
265    {
266        $source = $this->getData();
267
268        return \array_key_exists($key, $source) && null !== $source[$key];
269    }
270}
271