1<?php
2
3namespace Elastica;
4
5use Elastica\Exception\ConnectionException;
6use Elastica\Exception\InvalidException;
7use Elastica\Exception\ResponseException;
8
9/**
10 * Elastica Request object.
11 *
12 * @author Nicolas Ruflin <spam@ruflin.com>
13 */
14class Request extends Param
15{
16    public const HEAD = 'HEAD';
17    public const POST = 'POST';
18    public const PUT = 'PUT';
19    public const GET = 'GET';
20    public const DELETE = 'DELETE';
21    public const DEFAULT_CONTENT_TYPE = 'application/json';
22    public const NDJSON_CONTENT_TYPE = 'application/x-ndjson';
23
24    /**
25     * @var Connection|null
26     */
27    protected $_connection;
28
29    /**
30     * Construct.
31     *
32     * @param string       $path        Request path
33     * @param string       $method      OPTIONAL Request method (use const's) (default = self::GET)
34     * @param array|string $data        OPTIONAL Data array
35     * @param array        $query       OPTIONAL Query params
36     * @param string       $contentType Content-Type sent with this request
37     */
38    public function __construct(string $path, string $method = self::GET, $data = [], array $query = [], ?Connection $connection = null, string $contentType = self::DEFAULT_CONTENT_TYPE)
39    {
40        $this->setPath($path);
41        $this->setMethod($method);
42        $this->setData($data);
43        $this->setQuery($query);
44
45        if ($connection) {
46            $this->setConnection($connection);
47        }
48        $this->setContentType($contentType);
49    }
50
51    public function __toString(): string
52    {
53        return JSON::stringify($this->toArray());
54    }
55
56    /**
57     * Sets the request method. Use one of the for consts.
58     *
59     * @return $this
60     */
61    public function setMethod(string $method)
62    {
63        return $this->setParam('method', $method);
64    }
65
66    /**
67     * Get request method.
68     */
69    public function getMethod(): string
70    {
71        return $this->getParam('method');
72    }
73
74    /**
75     * Sets the request data.
76     *
77     * @param array|string $data Request data
78     *
79     * @return $this
80     */
81    public function setData($data)
82    {
83        return $this->setParam('data', $data);
84    }
85
86    /**
87     * Return request data.
88     *
89     * @return array|string Request data
90     */
91    public function getData()
92    {
93        return $this->getParam('data');
94    }
95
96    /**
97     * Sets the request path.
98     *
99     * @return $this
100     */
101    public function setPath(string $path)
102    {
103        return $this->setParam('path', $path);
104    }
105
106    /**
107     * Return request path.
108     */
109    public function getPath(): string
110    {
111        return $this->getParam('path');
112    }
113
114    /**
115     * Return query params.
116     *
117     * @return array Query params
118     */
119    public function getQuery(): array
120    {
121        return $this->getParam('query');
122    }
123
124    /**
125     * @return $this
126     */
127    public function setQuery(array $query = [])
128    {
129        return $this->setParam('query', $query);
130    }
131
132    /**
133     * @return $this
134     */
135    public function setConnection(Connection $connection)
136    {
137        $this->_connection = $connection;
138
139        return $this;
140    }
141
142    /**
143     * Return Connection Object.
144     *
145     * @throws Exception\InvalidException If no valid connection was set
146     */
147    public function getConnection(): Connection
148    {
149        if (null === $this->_connection) {
150            throw new InvalidException('No valid connection object set');
151        }
152
153        return $this->_connection;
154    }
155
156    /**
157     * Set the Content-Type of this request.
158     */
159    public function setContentType(string $contentType)
160    {
161        return $this->setParam('contentType', $contentType);
162    }
163
164    /**
165     * Get the Content-Type of this request.
166     */
167    public function getContentType(): string
168    {
169        return $this->getParam('contentType');
170    }
171
172    /**
173     * Sends request to server.
174     *
175     * @throws ResponseException
176     * @throws ConnectionException
177     */
178    public function send(): Response
179    {
180        $transport = $this->getConnection()->getTransportObject();
181
182        // Refactor: Not full toArray needed in exec?
183        return $transport->exec($this, $this->getConnection()->toArray());
184    }
185
186    /**
187     * @return array
188     */
189    public function toArray()
190    {
191        $data = $this->getParams();
192        if ($this->_connection) {
193            $data['connection'] = $this->_connection->getParams();
194        }
195
196        return $data;
197    }
198
199    /**
200     * Converts request to curl request format.
201     *
202     * @deprecated since version 7.1.3, use the "__toString()" method or cast to string instead.
203     *
204     * @return string
205     */
206    public function toString()
207    {
208        \trigger_deprecation('ruflin/elastica', '7.1.3', 'The "%s()" method is deprecated, use "__toString()" or cast to string instead. It will be removed in 8.0.', __METHOD__);
209
210        return (string) $this;
211    }
212}
213