1<?php 2 3declare(strict_types = 1); 4 5namespace Elasticsearch\Endpoints; 6 7use Elasticsearch\Common\Exceptions\UnexpectedValueException; 8use Elasticsearch\Serializers\SerializerInterface; 9use Elasticsearch\Transport; 10use Exception; 11use GuzzleHttp\Ring\Future\FutureArrayInterface; 12 13/** 14 * Class AbstractEndpoint 15 * 16 * @category Elasticsearch 17 * @package Elasticsearch\Endpoints 18 * @author Zachary Tong <zach@elastic.co> 19 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache2 20 * @link http://elastic.co 21 */ 22abstract class AbstractEndpoint 23{ 24 /** 25 * @var array 26 */ 27 protected $params =[]; 28 29 /** 30 * @var string 31 */ 32 protected $index = null; 33 34 /** 35 * @var string 36 */ 37 protected $type = null; 38 39 /** 40 * @var string|int 41 */ 42 protected $id = null; 43 44 /** 45 * @var string 46 */ 47 protected $method = null; 48 49 /** 50 * @var string|array 51 */ 52 protected $body = null; 53 54 /** 55 * @var array 56 */ 57 private $options = []; 58 59 /** 60 * @var SerializerInterface 61 */ 62 protected $serializer; 63 64 /** 65 * @return string[] 66 */ 67 abstract public function getParamWhitelist(): array; 68 69 /** 70 * @return string 71 */ 72 abstract public function getURI(): string; 73 74 /** 75 * @return string 76 */ 77 abstract public function getMethod(): string; 78 79 80 /** 81 * Set the parameters for this endpoint 82 * 83 * @param string[] $params Array of parameters 84 * @return $this 85 */ 86 public function setParams(array $params) 87 { 88 $this->extractOptions($params); 89 $this->checkUserParams($params); 90 $params = $this->convertCustom($params); 91 $this->params = $this->convertArraysToStrings($params); 92 93 return $this; 94 } 95 96 public function getParams(): array 97 { 98 return $this->params; 99 } 100 101 public function getOptions(): array 102 { 103 return $this->options; 104 } 105 106 public function getIndex(): ?string 107 { 108 return $this->index; 109 } 110 111 /** 112 * @return $this 113 */ 114 public function setIndex($index) 115 { 116 if ($index === null) { 117 return $this; 118 } 119 120 if (is_array($index) === true) { 121 $index = array_map('trim', $index); 122 $index = implode(",", $index); 123 } 124 125 $this->index = urlencode($index); 126 127 return $this; 128 } 129 130 /** 131 * @deprecated 132 */ 133 public function getType(): ?string 134 { 135 return $this->type; 136 } 137 138 /** 139 * @deprecated 140 * @return $this 141 */ 142 public function setType(?string $type) 143 { 144 if ($type === null) { 145 return $this; 146 } 147 148 if (is_array($type) === true) { 149 $type = array_map('trim', $type); 150 $type = implode(",", $type); 151 } 152 153 $this->type = urlencode($type); 154 155 return $this; 156 } 157 158 /** 159 * @param int|string $docID 160 * 161 * @return $this 162 */ 163 public function setID($docID) 164 { 165 if ($docID === null) { 166 return $this; 167 } 168 169 if (is_int($docID)) { 170 $docID = (string) $docID; 171 } 172 173 $this->id = urlencode($docID); 174 175 return $this; 176 } 177 178 /** 179 * @return array|string 180 */ 181 public function getBody() 182 { 183 return $this->body; 184 } 185 186 protected function getOptionalURI(string $endpoint): string 187 { 188 $uri = []; 189 $uri[] = $this->getOptionalIndex(); 190 $uri[] = $this->getOptionalType(); 191 $uri[] = $endpoint; 192 $uri = array_filter($uri); 193 194 return '/' . implode('/', $uri); 195 } 196 197 private function getOptionalIndex(): string 198 { 199 if (isset($this->index) === true) { 200 return $this->index; 201 } else { 202 return '_all'; 203 } 204 } 205 206 private function getOptionalType(): string 207 { 208 if (isset($this->type) === true) { 209 return $this->type; 210 } else { 211 return ''; 212 } 213 } 214 215 /** 216 * @param array $params 217 * 218 * @throws UnexpectedValueException 219 */ 220 private function checkUserParams(array $params) 221 { 222 if (isset($params) !== true) { 223 return; //no params, just return. 224 } 225 226 $whitelist = array_merge( 227 $this->getParamWhitelist(), 228 [ 'pretty', 'human', 'error_trace', 'source', 'filter_path' ] 229 ); 230 231 $invalid = array_diff(array_keys($params), $whitelist); 232 if (count($invalid) > 0) { 233 sort($invalid); 234 sort($whitelist); 235 throw new UnexpectedValueException( 236 sprintf( 237 (count($invalid) > 1 ? '"%s" are not valid parameters.' : '"%s" is not a valid parameter.').' Allowed parameters are "%s"', 238 implode('", "', $invalid), 239 implode('", "', $whitelist) 240 ) 241 ); 242 } 243 } 244 245 /** 246 * @param array $params Note: this is passed by-reference! 247 */ 248 private function extractOptions(&$params) 249 { 250 // Extract out client options, then start transforming 251 if (isset($params['client']) === true) { 252 $this->options['client'] = $params['client']; 253 unset($params['client']); 254 } 255 $ignore = isset($this->options['client']['ignore']) ? $this->options['client']['ignore'] : null; 256 if (isset($ignore) === true) { 257 if (is_string($ignore)) { 258 $this->options['client']['ignore'] = explode(",", $ignore); 259 } elseif (is_array($ignore)) { 260 $this->options['client']['ignore'] = $ignore; 261 } else { 262 $this->options['client']['ignore'] = [$ignore]; 263 } 264 } 265 } 266 267 private function convertCustom(array $params): array 268 { 269 if (isset($params['custom']) === true) { 270 foreach ($params['custom'] as $k => $v) { 271 $params[$k] = $v; 272 } 273 unset($params['custom']); 274 } 275 276 return $params; 277 } 278 279 private function convertArraysToStrings(array $params): array 280 { 281 foreach ($params as $key => &$value) { 282 if (!($key === 'client' || $key == 'custom') && is_array($value) === true) { 283 if ($this->isNestedArray($value) !== true) { 284 $value = implode(",", $value); 285 } 286 } 287 } 288 289 return $params; 290 } 291 292 private function isNestedArray(array $a): bool 293 { 294 foreach ($a as $v) { 295 if (is_array($v)) { 296 return true; 297 } 298 } 299 300 return false; 301 } 302} 303