1<?php
2
3namespace Elastica\Type;
4
5use Elastica\Exception\InvalidException;
6use Elastica\Response;
7use Elastica\Type;
8use Elasticsearch\Endpoints\Indices\Mapping\Put;
9
10/**
11 * Elastica Mapping object.
12 *
13 * @author Nicolas Ruflin <spam@ruflin.com>
14 *
15 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
16 */
17class Mapping
18{
19    /**
20     * Mapping.
21     *
22     * @var array Mapping
23     */
24    protected $_mapping = [];
25
26    /**
27     * Type.
28     *
29     * @var \Elastica\Type Type object
30     */
31    protected $_type;
32
33    /**
34     * Construct Mapping.
35     *
36     * @param Type  $type       OPTIONAL Type object
37     * @param array $properties OPTIONAL Properties
38     */
39    public function __construct(Type $type = null, array $properties = [])
40    {
41        if ($type) {
42            $this->setType($type);
43        }
44
45        if (!empty($properties)) {
46            $this->setProperties($properties);
47        }
48    }
49
50    /**
51     * Sets the mapping type
52     * Enter description here ...
53     *
54     * @param Type $type Type object
55     *
56     * @return $this
57     */
58    public function setType(Type $type): Mapping
59    {
60        $this->_type = $type;
61
62        return $this;
63    }
64
65    /**
66     * Sets the mapping properties.
67     *
68     * @param array $properties Properties
69     *
70     * @return $this
71     */
72    public function setProperties(array $properties): Mapping
73    {
74        return $this->setParam('properties', $properties);
75    }
76
77    /**
78     * Gets the mapping properties.
79     *
80     * @return array $properties Properties
81     */
82    public function getProperties(): array
83    {
84        return $this->getParam('properties');
85    }
86
87    /**
88     * Sets the mapping _meta.
89     *
90     * @param array $meta metadata
91     *
92     * @return $this
93     *
94     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-meta.html
95     */
96    public function setMeta(array $meta): Mapping
97    {
98        return $this->setParam('_meta', $meta);
99    }
100
101    /**
102     * Returns mapping type.
103     *
104     * @return Type Type
105     */
106    public function getType(): Type
107    {
108        return $this->_type;
109    }
110
111    /**
112     * Sets source values.
113     *
114     * To disable source, argument is
115     * array('enabled' => false)
116     *
117     * @param array $source Source array
118     *
119     * @return $this
120     *
121     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html
122     */
123    public function setSource(array $source): Mapping
124    {
125        return $this->setParam('_source', $source);
126    }
127
128    /**
129     * Disables the source in the index.
130     *
131     * Param can be set to true to enable again
132     *
133     * @param bool $enabled OPTIONAL (default = false)
134     *
135     * @return $this
136     */
137    public function disableSource(bool $enabled = false): Mapping
138    {
139        return $this->setSource(['enabled' => $enabled]);
140    }
141
142    /**
143     * Sets raw parameters.
144     *
145     * Possible options:
146     * _uid
147     * _id
148     * _type
149     * _source
150     * _analyzer
151     * _boost
152     * _routing
153     * _index
154     * _size
155     * properties
156     *
157     * @param string $key   Key name
158     * @param mixed  $value Key value
159     *
160     * @return $this
161     */
162    public function setParam(string $key, $value): Mapping
163    {
164        $this->_mapping[$key] = $value;
165
166        return $this;
167    }
168
169    /**
170     * Get raw parameters.
171     *
172     * @see setParam
173     *
174     * @param string $key Key name
175     *
176     * @return mixed $value Key value
177     */
178    public function getParam(string $key)
179    {
180        return $this->_mapping[$key] ?? null;
181    }
182
183    /**
184     * Converts the mapping to an array.
185     *
186     * @throws InvalidException
187     *
188     * @return array Mapping as array
189     */
190    public function toArray(): array
191    {
192        $type = $this->getType();
193
194        if (empty($type)) {
195            throw new InvalidException('Type has to be set');
196        }
197
198        return [$type->getName() => $this->_mapping];
199    }
200
201    /**
202     * Submits the mapping and sends it to the server.
203     *
204     * @param array $query Query string parameters to send with mapping
205     *
206     * @return Response Response object
207     */
208    public function send(array $query = []): Response
209    {
210        $endpoint = new Put();
211        $endpoint->setBody($this->toArray());
212        $endpoint->setParams($query);
213
214        return $this->getType()->requestEndpoint($endpoint);
215    }
216
217    /**
218     * Creates a mapping object.
219     *
220     * @param array|Mapping $mapping Mapping object or properties array
221     *
222     * @throws InvalidException If invalid type
223     *
224     * @return self
225     */
226    public static function create($mapping): Mapping
227    {
228        if (\is_array($mapping)) {
229            $mappingObject = new self();
230            $mappingObject->setProperties($mapping);
231
232            return $mappingObject;
233        }
234
235        if ($mapping instanceof self) {
236            return $mapping;
237        }
238
239        throw new InvalidException('Invalid object type');
240    }
241}
242