Skip to content

Commit

Permalink
Replace endpoint callable with EndpointFactory
Browse files Browse the repository at this point in the history
Signed-off-by: Kim Pepper <kim@pepper.id.au>

Signed-off-by: Kim Pepper <kim@pepper.id.au>

Signed-off-by: Kim Pepper <kim@pepper.id.au>
  • Loading branch information
kimpepper committed Nov 5, 2024
1 parent add2d03 commit bbe2ad3
Show file tree
Hide file tree
Showing 45 changed files with 309 additions and 225 deletions.
46 changes: 8 additions & 38 deletions src/OpenSearch/ClientBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,7 @@ class ClientBuilder
*/
private $transport;

/**
* @var callable|null
*/
private $endpoint;
private ?EndpointFactoryInterface $endpointFactory = null;

/**
* @var NamespaceBuilderInterface[]
Expand Down Expand Up @@ -182,14 +179,6 @@ public function getTransport(): Transport
return $this->transport;
}

/**
* Can supply second param to Client::__construct() when invoking manually or with dependency injection
*/
public function getEndpoint(): callable
{
return $this->endpoint;
}

/**
* Can supply third param to Client::__construct() when invoking manually or with dependency injection
*
Expand Down Expand Up @@ -325,15 +314,9 @@ public function setConnectionPool($connectionPool, array $args = []): ClientBuil
return $this;
}

/**
* Set the endpoint
*
* @param callable $endpoint
*/
public function setEndpoint(callable $endpoint): ClientBuilder
public function setEndpointFactory(EndpointFactoryInterface $endpointFactory): ClientBuilder
{
$this->endpoint = $endpoint;

$this->endpointFactory = $endpointFactory;
return $this;
}

Expand Down Expand Up @@ -671,21 +654,8 @@ public function build(): Client

$this->buildTransport();

if (is_null($this->endpoint)) {
$serializer = $this->serializer;

$this->endpoint = function ($class) use ($serializer) {
$fullPath = '\\OpenSearch\\Endpoints\\' . $class;

$reflection = new ReflectionClass($fullPath);
$constructor = $reflection->getConstructor();

if ($constructor && $constructor->getParameters()) {
return new $fullPath($serializer);
} else {
return new $fullPath();
}
};
if (is_null($this->endpointFactory)) {
$this->endpointFactory = new EndpointFactory($this->serializer);
}

$registeredNamespaces = [];
Expand All @@ -696,12 +666,12 @@ public function build(): Client
$registeredNamespaces[$builder->getName()] = $builder->getObject($this->transport, $this->serializer);
}

return $this->instantiate($this->transport, $this->endpoint, $registeredNamespaces);
return $this->instantiate($this->transport, $this->endpointFactory, $registeredNamespaces);
}

protected function instantiate(Transport $transport, callable $endpoint, array $registeredNamespaces): Client
protected function instantiate(Transport $transport, EndpointFactoryInterface $endpointFactory, array $registeredNamespaces): Client
{
return new Client($transport, $endpoint, $registeredNamespaces);
return new Client($transport, $endpointFactory, $registeredNamespaces);
}

private function buildLoggers(): void
Expand Down
55 changes: 55 additions & 0 deletions src/OpenSearch/EndpointFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace OpenSearch;

use OpenSearch\Endpoints\AbstractEndpoint;
use OpenSearch\Serializers\SerializerInterface;
use ReflectionClass;

/**
* A factory for creating endpoints.
*/
class EndpointFactory implements EndpointFactoryInterface
{
/**
* @var array<string, AbstractEndpoint>
*/
private array $endpoints = [];

public function __construct(
protected SerializerInterface $serializer,
) {
}

/**
* {@inheritdoc}
*/
public function getEndpoint(string $class): AbstractEndpoint
{
if (!isset($this->endpoints[$class])) {
$this->endpoints[$class] = $this->createEndpoint($class);
}

return $this->endpoints[$class];
}

/**
* Creates an endpoint.
*
* @phpstan-template T of AbstractEndpoint
* @phpstan-param class-string<T> $class
* @phpstan-return T
* @throws \ReflectionException
*/
private function createEndpoint(string $class): AbstractEndpoint
{
$reflection = new ReflectionClass($class);
$constructor = $reflection->getConstructor();

if ($constructor && $constructor->getParameters()) {
return new $class($this->serializer);
}
return new $class();
}

}
21 changes: 21 additions & 0 deletions src/OpenSearch/EndpointFactoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace OpenSearch;

use OpenSearch\Endpoints\AbstractEndpoint;

/**
* A factory for creating endpoints.
*/
interface EndpointFactoryInterface
{
/**
* Gets an endpoint.
*
* @phpstan-template T of AbstractEndpoint
* @phpstan-param class-string<T> $class
* @phpstan-return T
*/
public function getEndpoint(string $class): AbstractEndpoint;

}
77 changes: 77 additions & 0 deletions src/OpenSearch/EndpointInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace OpenSearch;

/**
* Provides and interface for endpoints.
*/
interface EndpointInterface
{
/**
* Get the whitelist of allowed parameters.
*
* @return string[]
*/
public function getParamWhitelist(): array;

/**
* Get the URI.
*/
public function getURI(): string;

/**
* Get the HTTP method.
*/
public function getMethod(): string;

/**
* Set the query string parameters.
*/
public function setParams(array $params): static;

/**
* Get the query string parameters.
*/
public function getParams(): array;

/**
* Get the options.
*/
public function getOptions(): array;

/**
* Get the index.
*/
public function getIndex(): ?string;

/**
* Set the index.
*
* @param string|string[]|null $index
*
* @return $this
*/
public function setIndex(string|array|null $index): static;

/**
* Get the document ID.
*
* @param int|string|null $docID
*
* @return $this
*/
public function setId(int|string|null $docID): static;

/**
* Get the body of the request.
*
* @return array|string
*/
public function getBody(): array|string;

/**
* Set the body of the request.
*/
public function setBody(array $body): static;

}
4 changes: 2 additions & 2 deletions src/OpenSearch/Namespaces/AbstractNamespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

namespace OpenSearch\Namespaces;

use OpenSearch\EndpointFactoryInterface;
use OpenSearch\Endpoints\AbstractEndpoint;
use OpenSearch\Transport;

Expand All @@ -36,10 +37,9 @@ abstract class AbstractNamespace
*/
protected $endpoints;

public function __construct(Transport $transport, callable $endpoints)
public function __construct(Transport $transport, protected readonly EndpointFactoryInterface $endpointFactory)
{
$this->transport = $transport;
$this->endpoints = $endpoints;
}

/**
Expand Down
16 changes: 8 additions & 8 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,9 @@ public function testExtractArgumentIterable()
/** @test */
public function sendRawRequest(): void
{
$callable = function () {};
$transport = $this->createMock(OpenSearch\Transport::class);
$client = new OpenSearch\Client($transport, $callable, []);
$endpointFactory = $this->createMock(OpenSearch\EndpointFactoryInterface::class);
$client = new OpenSearch\Client($transport, $endpointFactory, []);

$transport->expects($this->once())->method('performRequest')->with('GET', '/', [], null, []);

Expand All @@ -425,9 +425,9 @@ public function sendRawRequest(): void
/** @test */
public function sendRawRequestWithBody(): void
{
$callable = function () {};
$transport = $this->createMock(OpenSearch\Transport::class);
$client = new OpenSearch\Client($transport, $callable, []);
$endpointFactory = $this->createMock(OpenSearch\EndpointFactoryInterface::class);
$client = new OpenSearch\Client($transport, $endpointFactory, []);
$body = ['query' => ['match' => ['text_entry' => 'long live king']]];

$transport->expects($this->once())->method('performRequest')->with('GET', '/shakespeare/_search', [], $body, []);
Expand All @@ -438,9 +438,9 @@ public function sendRawRequestWithBody(): void
/** @test */
public function sendRawRequestWithParams(): void
{
$callable = function () {};
$transport = $this->createMock(OpenSearch\Transport::class);
$client = new OpenSearch\Client($transport, $callable, []);
$endpointFactory = $this->createMock(OpenSearch\EndpointFactoryInterface::class);
$client = new OpenSearch\Client($transport, $endpointFactory, []);
$params = ['foo' => 'bar'];

$transport->expects($this->once())->method('performRequest')->with('GET', '/_search', $params, null, []);
Expand All @@ -451,9 +451,9 @@ public function sendRawRequestWithParams(): void
/** @test */
public function sendRawRequestWithOptions(): void
{
$callable = function () {};
$transport = $this->createMock(OpenSearch\Transport::class);
$client = new OpenSearch\Client($transport, $callable, []);
$endpointFactory = $this->createMock(OpenSearch\EndpointFactoryInterface::class);
$client = new OpenSearch\Client($transport, $endpointFactory, []);
$options = ['client' => ['future' => 'lazy']];

$transport->expects($this->once())->method('performRequest')->with('GET', '/', [], null, $options);
Expand Down
Loading

0 comments on commit bbe2ad3

Please sign in to comment.