File "EndpointTrait.php"
Full Path: /var/www/drive/elasticsearch/elasticsearch/src/Traits/EndpointTrait.php
File size: 6.23 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* Elasticsearch PHP Client
*
* @link https://github.com/elastic/elasticsearch-php
* @copyright Copyright (c) Elasticsearch B.V (https://www.elastic.co)
* @license https://opensource.org/licenses/MIT MIT License
*
* Licensed to Elasticsearch B.V under one or more agreements.
* Elasticsearch B.V licenses this file to you under the MIT License.
* See the LICENSE file in the project root for more information.
*/
declare(strict_types = 1);
namespace Elastic\Elasticsearch\Traits;
use Elastic\Elasticsearch\Client;
use Elastic\Elasticsearch\Exception\ContentTypeException;
use Elastic\Elasticsearch\Exception\MissingParameterException;
use Elastic\Elasticsearch\Utility;
use Elastic\Transport\Serializer\JsonSerializer;
use Elastic\Transport\Serializer\NDJsonSerializer;
use Http\Discovery\Psr17FactoryDiscovery;
use Psr\Http\Message\RequestInterface;
use function http_build_query;
use function strpos;
use function sprintf;
trait EndpointTrait
{
/**
* Check if an array containts nested array
*/
private function isNestedArray(array $a): bool
{
foreach ($a as $v) {
if (is_array($v)) {
return true;
}
}
return false;
}
/**
* Check if an array is associative, i.e. has a string as key
*/
protected function isAssociativeArray(array $array): bool
{
foreach ($array as $k => $v) {
if (is_string($k)) {
return true;
}
}
return false;
}
/**
* Converts array to comma-separated list;
* Converts boolean value to true', 'false' string
*
* @param mixed $value
*/
private function convertValue($value): string
{
// Convert a boolean value in 'true' or 'false' string
if (is_bool($value)) {
return $value ? 'true' : 'false';
// Convert to comma-separated list if array
} elseif (is_array($value) && $this->isNestedArray($value) === false) {
return implode(',', $value);
}
return (string) $value;
}
/**
* Encode a value for a valid URL
*
* @param mixed $value
*/
protected function encode($value): string
{
return Utility::urlencode($this->convertValue($value));
}
/**
* Returns the URL with the query string from $params
* extracting the array keys specified in $keys
*/
protected function addQueryString(string $url, array $params, array $keys): string
{
$queryParams = [];
foreach ($keys as $k) {
if (isset($params[$k])) {
$queryParams[$k] = $this->convertValue($params[$k]);
}
}
if (empty($queryParams)) {
return $url;
}
return $url . '?' . http_build_query($queryParams);
}
/**
* Serialize the body using the Content-Type
*
* @param mixed $body
*/
protected function bodySerialize($body, string $contentType): string
{
if (strpos($contentType, 'application/x-ndjson') !== false ||
strpos($contentType, 'application/vnd.elasticsearch+x-ndjson') !== false) {
return NDJsonSerializer::serialize($body, ['remove_null' => false]);
}
if (strpos($contentType, 'application/json') !== false ||
strpos($contentType, 'application/vnd.elasticsearch+json') !== false) {
return JsonSerializer::serialize($body, ['remove_null' => false]);
}
throw new ContentTypeException(sprintf(
"The Content-Type %s is not managed by Elasticsearch serializer",
$contentType
));
}
/**
* Create a PSR-7 request
*
* @param array|string $body
*/
protected function createRequest(string $method, string $url, array $headers, $body = null): RequestInterface
{
$requestFactory = Psr17FactoryDiscovery::findRequestFactory();
$streamFactory = Psr17FactoryDiscovery::findStreamFactory();
$request = $requestFactory->createRequest($method, $url);
// Body request
if (!empty($body)) {
if (!isset($headers['Content-Type'])) {
throw new ContentTypeException(sprintf(
"The Content-Type is missing for %s %s",
$method,
$url
));
}
$content = is_string($body) ? $body : $this->bodySerialize($body, $headers['Content-Type']);
$request = $request->withBody($streamFactory->createStream($content));
}
$headers = $this->buildCompatibilityHeaders($headers);
// Headers
foreach ($headers as $name => $value) {
$request = $request->withHeader($name, $value);
}
return $request;
}
/**
* Build the API compatibility headers
* transfrom Content-Type and Accept adding vnd.elasticsearch+ and compatible-with
*
* @see https://github.com/elastic/elasticsearch-php/pull/1142
*/
protected function buildCompatibilityHeaders(array $headers): array
{
if (isset($headers['Content-Type'])) {
if (preg_match('/application\/([^,]+)$/', $headers['Content-Type'], $matches)) {
$headers['Content-Type'] = sprintf(Client::API_COMPATIBILITY_HEADER, 'application', $matches[1]);
}
}
if (isset($headers['Accept'])) {
$values = explode(',', $headers['Accept']);
foreach ($values as &$value) {
if (preg_match('/(application|text)\/([^,]+)/', $value, $matches)) {
$value = sprintf(Client::API_COMPATIBILITY_HEADER, $matches[1], $matches[2]);
}
}
$headers['Accept'] = implode(',', $values);
}
return $headers;
}
/**
* Check if the $required parameters are present in $params
* @throws MissingParameterException
*/
protected function checkRequiredParameters(array $required, array $params): void
{
foreach ($required as $req) {
if (!isset($params[$req])) {
throw new MissingParameterException(sprintf(
'The parameter %s is required',
$req
));
}
}
}
}