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