1<?php
2
3namespace Elastica\Transport;
4
5use Elastica\Connection;
6use Elastica\Exception\ConnectionException;
7use Elastica\Exception\InvalidException;
8use Elastica\Exception\ResponseException;
9use Elastica\Param;
10use Elastica\Request;
11use Elastica\Response;
12
13/**
14 * Elastica Abstract Transport object.
15 *
16 * @author Nicolas Ruflin <spam@ruflin.com>
17 */
18abstract class AbstractTransport extends Param
19{
20    /**
21     * @var Connection
22     */
23    protected $_connection;
24
25    /**
26     * Construct transport.
27     */
28    public function __construct(?Connection $connection = null)
29    {
30        if ($connection) {
31            $this->setConnection($connection);
32        }
33    }
34
35    public function getConnection(): Connection
36    {
37        return $this->_connection;
38    }
39
40    /**
41     * @return $this
42     */
43    public function setConnection(Connection $connection): AbstractTransport
44    {
45        $this->_connection = $connection;
46
47        return $this;
48    }
49
50    /**
51     * Executes the transport request.
52     *
53     * @param Request              $request Request object
54     * @param array<string, mixed> $params  Hostname, port, path, ...
55     *
56     * @throws ResponseException
57     * @throws ConnectionException
58     */
59    abstract public function exec(Request $request, array $params): Response;
60
61    /**
62     * BOOL values true|false should be sanityzed and passed to Elasticsearch
63     * as string.
64     *
65     * @param array<string, mixed> $query
66     *
67     * @return array<string, mixed>
68     */
69    public function sanityzeQueryStringBool(array $query)
70    {
71        foreach ($query as $key => $value) {
72            if (\is_bool($value)) {
73                $query[$key] = ($value) ? 'true' : 'false';
74            }
75        }
76
77        return $query;
78    }
79
80    /**
81     * Create a transport.
82     *
83     * The $transport parameter can be one of the following values:
84     *
85     * * string: The short name of a transport. For instance "Http"
86     * * object: An already instantiated instance of a transport
87     * * array: An array with a "type" key which must be set to one of the two options. All other
88     *          keys in the array will be set as parameters in the transport instance
89     *
90     * @param AbstractTransport|array<string, mixed>|string $transport  A transport definition
91     * @param Connection                                    $connection A connection instance
92     * @param array<string, mixed>                          $params     Parameters for the transport class
93     *
94     * @throws InvalidException
95     */
96    public static function create($transport, Connection $connection, array $params = []): AbstractTransport
97    {
98        if (\is_array($transport) && isset($transport['type'])) {
99            $transportParams = $transport;
100            unset($transportParams['type']);
101
102            $params = \array_replace($params, $transportParams);
103            $transport = $transport['type'];
104        }
105
106        if (\is_string($transport)) {
107            $specialTransports = [
108                'httpadapter' => 'HttpAdapter',
109                'nulltransport' => 'NullTransport',
110            ];
111
112            $transport = $specialTransports[\strtolower($transport)] ?? \ucfirst($transport);
113            $classNames = ["Elastica\\Transport\\{$transport}", $transport];
114            foreach ($classNames as $className) {
115                if (\class_exists($className)) {
116                    $transport = new $className();
117                    break;
118                }
119            }
120        }
121
122        if ($transport instanceof self) {
123            $transport->setConnection($connection);
124
125            foreach ($params as $key => $value) {
126                $transport->setParam($key, $value);
127            }
128        } else {
129            throw new InvalidException('Invalid transport');
130        }
131
132        return $transport;
133    }
134}
135