Skip to content

Commit

Permalink
419: Refactor code in ES services
Browse files Browse the repository at this point in the history
  • Loading branch information
cableman committed Jan 11, 2024
1 parent 424514c commit 1c97a8a
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 53 deletions.
5 changes: 0 additions & 5 deletions baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,8 @@
</file>
<file src="src/Service/ElasticSearchIndex.php">
<InvalidArgument>
<code>$params</code>
<code>$params</code>
<code><![CDATA[['name' => $indexName]]]></code>
</InvalidArgument>
<PossiblyInvalidArgument>
<code>$response</code>
<code>$response</code>
</PossiblyInvalidArgument>
</file>
</files>
49 changes: 30 additions & 19 deletions src/Api/State/AbstractProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace App\Api\State;

use ApiPlatform\Elasticsearch\Filter\FilterInterface;
use ApiPlatform\Elasticsearch\Filter\OrderFilter;
use ApiPlatform\Elasticsearch\Filter\SortFilterInterface;
use ApiPlatform\Metadata\Operation;
use App\Model\FilterTypes;
use App\Model\IndexNames;
use App\Service\IndexInterface;
use Psr\Container\ContainerInterface;
Expand Down Expand Up @@ -39,34 +40,27 @@ public function __construct(
protected function getFilters(Operation $operation, array $context = []): array
{
$resourceFilters = $operation->getFilters();
$orderFilters = [];
$outputFilters = [];
$outputFilters = [
FilterTypes::Filters => [],
FilterTypes::Sort => [],
];

if (!is_null($resourceFilters)) {
foreach ($resourceFilters as $filterId) {
$filter = $this->filterLocator->has($filterId) ? $this->filterLocator->get($filterId) : null;
$filter = $this->getFilterById($filterId);

if ($filter instanceof FilterInterface) {
// Apply the OrderFilter after every.
if ($filter instanceof OrderFilter) {
$orderFilters[$filterId] = $filter;
continue;
}

$data = $filter->apply([], IndexNames::Events->value, $operation, $context);

if (!empty($data)) {
$outputFilters[$filterId] = $data;
if ($filter instanceof SortFilterInterface) {
$outputFilters[FilterTypes::Sort][] = $data;
} else {
$outputFilters[FilterTypes::Filters][] = $data;
}
}
}
}

foreach ($orderFilters as $filterId => $orderFilter) {
$outputFilters['orderFilters'] ??= [];
$data = $orderFilter->apply([], IndexNames::Events->value, $operation, $context);
if (!empty($data)) {
$outputFilters['orderFilters'][$filterId] = $data;
}
}
}

return $outputFilters;
Expand All @@ -85,4 +79,21 @@ protected function calculatePageOffset(array $context): int
{
return (($context['filters']['page'] ?? 1) - 1) * self::PAGE_SIZE;
}

/**
* Retrieves a filter based on the provided filter ID.
*
* @param string $filterId
* The ID of the filter to retrieve
*
* @return FilterInterface|null
* The filter instance if found, otherwise null
*
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
protected function getFilterById(string $filterId): ?FilterInterface
{
return $this->filterLocator->has($filterId) ? $this->filterLocator->get($filterId) : null;
}
}
7 changes: 7 additions & 0 deletions src/Api/State/EventRepresentationProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Model\IndexNames;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

final class EventRepresentationProvider extends AbstractProvider implements ProviderInterface
{
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws \App\Exception\IndexException
*/
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
// @TODO: should we create enum with 5,10,15,20
Expand Down
10 changes: 7 additions & 3 deletions src/Api/State/OrganizationRepresentationProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Model\IndexNames;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

final class OrganizationRepresentationProvider extends AbstractProvider implements ProviderInterface
{
// @TODO: should we create enum with 5,10,15,20
public const PAGE_SIZE = 10;

/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws \App\Exception\IndexException
*/
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
if ($operation instanceof CollectionOperationInterface) {
Expand Down
12 changes: 12 additions & 0 deletions src/Model/FilterTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace App\Model;

/**
* Represents the types of filters that can be applied.
*/
enum FilterTypes: string
{
public const Filters = 'filters';
public const Sort = 'sort';
}
3 changes: 3 additions & 0 deletions src/Model/IndexNames.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace App\Model;

/**
* Represents an enumeration of index names.
*/
enum IndexNames: string
{
case Events = 'events';
Expand Down
92 changes: 66 additions & 26 deletions src/Service/ElasticSearchIndex.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Service;

use App\Exception\IndexException;
use App\Model\FilterTypes;
use Elastic\Elasticsearch\Client;
use Elastic\Elasticsearch\Exception\ClientResponseException;
use Elastic\Elasticsearch\Exception\MissingParameterException;
Expand All @@ -17,9 +18,6 @@ public function __construct(
) {
}

/**
* @throws IndexException
*/
public function indexExists($indexName): bool
{
try {
Expand All @@ -36,31 +34,61 @@ public function indexExists($indexName): bool
}
}

/**
* @throws ClientResponseException
* @throws ServerResponseException
* @throws MissingParameterException
* @throws \JsonException
*/
public function get(string $indexName, int $id): array
{
$params = [
'index' => $indexName,
'id' => $id,
];

// @TODO: check status codes.
$response = $this->client->get($params);
try {
/** @var Elasticsearch $response */
$response = $this->client->get($params);
if (Response::HTTP_OK !== $response->getStatusCode()) {
throw new IndexException('Failed to get document from Elasticsearch', $response->getStatusCode());
}
$result = $this->parseResponse($response);
} catch (ClientResponseException|ServerResponseException|MissingParameterException|\JsonException $e) {
throw new IndexException($e->getMessage(), $e->getCode(), $e);
}

return $result;
}

public function getAll(string $indexName, array $filters = [], int $from = 0, int $size = 10): array
{
$params = $this->buildParams($indexName, $filters, $from, $size);

try {
/** @var Elasticsearch $response */
$response = $this->client->search($params);
if (Response::HTTP_OK !== $response->getStatusCode()) {
throw new IndexException('Failed to get document from Elasticsearch', $response->getStatusCode());
}
$results = $this->parseResponse($response);
} catch (ClientResponseException|ServerResponseException|\JsonException $e) {
throw new IndexException($e->getMessage(), $e->getCode(), $e);
}

return $this->parseResponse($response);
return $this->extractSourceFromHits($results);
}

/**
* @throws ClientResponseException
* @throws ServerResponseException
* @throws \JsonException
* Builds the parameters for the Elasticsearch search request.
*
* @param string $indexName
* The name of the index to search in
* @param array $filters
* An array of filters to apply to the search query
* @param int $from
* The starting offset for the search results
* @param int $size
* The maximum number of search results to return
*
* @return array
* The built parameters for the Elasticsearch search request
*/
public function getAll(string $indexName, array $filters = [], int $from = 0, int $size = 10): array
private function buildParams(string $indexName, array $filters, int $from, int $size): array
{
$params = [
'index' => $indexName,
Expand All @@ -70,24 +98,36 @@ public function getAll(string $indexName, array $filters = [], int $from = 0, in
],
'size' => $size,
'from' => $from,
// @TODO: add order filters to sort results
'sort' => [],
],
];

$body = [];
foreach ($filters as $filter) {
// @TODO: add order filters to sort
$body += $filter;
}

$body = $this->buildBody($filters);
if (!empty($body)) {
$params['body']['query'] = $body;
}

$response = $this->client->search($params);
$results = $this->parseResponse($response);
return $params;
}

/**
* Builds the body for Elasticsearch request using the given filters.
*
* @param array $filters
* The filters to be included in the body
*
* @return array
* The built body for Elasticsearch request
*/
private function buildBody(array $filters): array
{
$body = [];
foreach ($filters[FilterTypes::Filters] as $filter) {
$body += $filter;
}

return $this->cleanUpHits($results);
return $body;
}

/**
Expand Down Expand Up @@ -116,7 +156,7 @@ private function parseResponse(Elasticsearch $response): array
* @return array
* The cleaned-up hits
*/
private function cleanUpHits(array $results): array
private function extractSourceFromHits(array $results): array
{
$hits = [];
foreach ($results['hits']['hits'] as $hit) {
Expand Down
34 changes: 34 additions & 0 deletions src/Service/IndexInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace App\Service;

use App\Exception\IndexException;

interface IndexInterface
{
/**
Expand All @@ -12,10 +14,42 @@ interface IndexInterface
*
* @return bool
* True if the index exists, false otherwise
*
* @throws IndexException
*/
public function indexExists(string $indexName): bool;

/**
* Retrieves information from the specified index based on the provided ID.
*
* @param string $indexName
* The name of the index to retrieve information from
* @param int $id
* The ID of the document to retrieve
*
* @return array
* The retrieved document as an array
*
* @throws IndexException
*/
public function get(string $indexName, int $id): array;

/**
* Retrieves documents from the specified index with optional filters and pagination.
*
* @param string $indexName
* The name of the index to retrieve data from
* @param array $filters
* An array of filters to apply to the retrieved documents keyed by FilterTypes. Default is an empty array.
* @param int $from
* The starting page. Default is 0.
* @param int $size
* The maximum number of records to retrieve. Default is 10.
*
* @return array
* An array containing the retrieved documents
*
* @throws IndexException
*/
public function getAll(string $indexName, array $filters = [], int $from = 0, int $size = 10): array;
}

0 comments on commit 1c97a8a

Please sign in to comment.