search_api_meilisearch-1.0.x-dev/src/Converter/Item/ItemConverter.php
src/Converter/Item/ItemConverter.php
<?php
namespace Drupal\search_api_meilisearch\Converter\Item;
use Drupal\search_api\Item\FieldInterface;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\SearchApiException;
use Drupal\search_api_meilisearch\Backend\SpecialFieldsInterface;
use Drupal\search_api_meilisearch\Converter\Field\FieldConverterInterface;
/**
* Provides converting search api item to a Meilisearch document array.
*/
final class ItemConverter implements ItemConverterInterface {
/**
* The list of applicable field converters.
*
* @var \Drupal\search_api_meilisearch\Converter\Field\FieldConverterInterface[]
*/
private array $fieldConverters = [];
/**
* The list of sorted field converters.
*
* @var \Drupal\search_api_meilisearch\Converter\Field\FieldConverterInterface[]
*/
private ?array $sortedFieldConverters = NULL;
/**
* {@inheritdoc}
*/
public function convertToDocuments(array $items): array {
if ($this->sortedFieldConverters === NULL) {
$this->sortedFieldConverters = $this->sortFieldConverters();
}
$convertedItems = [];
foreach ($items as $item) {
$convertedItems[] = $this->convertToDocument($item);
}
return $convertedItems;
}
/**
* Appends a field converter to the list.
*
* @param \Drupal\search_api_meilisearch\Converter\Field\FieldConverterInterface $parser
* The field converter to be appended to the list.
* @param int $priority
* The priority of the field converter being added.
*
* @return $this
*/
public function addFieldConverter(FieldConverterInterface $parser, int $priority = 0): self {
$this->fieldConverters[$priority][] = $parser;
$this->sortedFieldConverters = NULL;
return $this;
}
/**
* Sorts field converters by priority.
*
* @return \Drupal\search_api_meilisearch\Converter\Field\FieldConverterInterface[]
* A sorted array of field converter objects.
*/
private function sortFieldConverters(): array {
krsort($this->fieldConverters);
return array_merge([], ...$this->fieldConverters);
}
/**
* Converts a search api item to a meilisearch document.
*
* @return array
* The converted meilisearch document.
*/
private function convertToDocument(ItemInterface $item): array {
$convertedItem = [];
$fields = $this->getSpecialFields($item) + $item->getFields();
foreach ($fields as $field) {
if (empty($field->getValues())) {
continue;
}
$values = $this->getFieldValues($field);
if (count($values) <= 1) {
$values = reset($values);
}
$convertedItem[$field->getFieldIdentifier()] = $values;
}
return $convertedItem;
}
/**
* Extracts the value from a search api field.
*
* @param \Drupal\search_api\Item\FieldInterface $field
* The search api field.
*
* @return array
* The extracted values.
*/
private function getFieldValues(FieldInterface $field): array {
foreach ($this->sortedFieldConverters as $fieldConverter) {
if ($fieldConverter->supports($field)) {
return $fieldConverter->toValues($field);
}
}
return $field->getValues();
}
/**
* Retrieves backend special fields of an item.
*
* @param \Drupal\search_api\Item\ItemInterface $item
* The search api item.
*
* @return \Drupal\search_api\Item\FieldInterface[]
* A list of special fields.
*/
private function getSpecialFields(ItemInterface $item): array {
try {
$server = $item->getIndex()->getServerInstance();
if (!$server) {
return [];
}
$backend = $server->getBackend();
if (!$backend instanceof SpecialFieldsInterface) {
return [];
}
return $backend->getItemSpecialFields($item);
}
catch (SearchApiException $exception) {
return [];
}
}
}
