Update search service
This commit is contained in:
@@ -5,107 +5,95 @@ declare(strict_types=1);
|
||||
namespace Pcm\SearchBundle\Service;
|
||||
|
||||
use Pcm\SearchBundle\Entity\SearchIndex;
|
||||
use Pcm\SearchBundle\Entity\Interface\SearchableInterface;
|
||||
use Pcm\SearchBundle\Interface\SearchableInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
class SearchService
|
||||
final class SearchService
|
||||
{
|
||||
public function __construct(private EntityManagerInterface $em) {}
|
||||
|
||||
/**
|
||||
* Given an $entity that implements SearchableInterface, this method
|
||||
* creates or updates a SearchIndex $entity
|
||||
*
|
||||
* @param SearchableInterface $entity
|
||||
* @return void
|
||||
*/
|
||||
public function index(SearchableInterface $entity)
|
||||
public function __construct(private EntityManagerInterface $em)
|
||||
{
|
||||
$searchIndex = $this->createSearchResult($entity);
|
||||
}
|
||||
|
||||
$this->em->persist($searchIndex);
|
||||
public function index(SearchableInterface $entity): void
|
||||
{
|
||||
$index = $this->createSearchResult($entity);
|
||||
|
||||
$this->em->persist($index);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
public function unIndex(SearchableInterface $entity): void
|
||||
{
|
||||
$entityId = $this->requireEntityId($entity);
|
||||
$index = $this->findIndex($this->resolveClass($entity), $entityId);
|
||||
|
||||
if ($index === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->em->remove($index);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an $entity that implements SearchableInterface, this method removes
|
||||
* the item from the search index
|
||||
*
|
||||
* @param SearchableInterface $entity
|
||||
* @return void
|
||||
*/
|
||||
public function unIndex(SearchableInterface $entity)
|
||||
{
|
||||
$class = $this->em->getClassMetadata($entity::class)->getName();
|
||||
|
||||
$search_result = $this
|
||||
->em
|
||||
->getRepository(SearchIndex::class)
|
||||
->findOneBy(['entityClass' => $class, 'entityId' => $entity->getId()]);
|
||||
|
||||
if ($search_result) {
|
||||
$this->em->remove($search_result);
|
||||
$this->em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an entity that implements SearchableInterface, this method first checks
|
||||
* if the relevant SearchIndex entity exists. If it doesn't, it's created. The
|
||||
* title and index data are set based on the methods in the $entity
|
||||
*
|
||||
* @param SearchableInterface $entity
|
||||
* @return SearchIndex
|
||||
* Finds or creates the SearchIndex row for the given entity and populates
|
||||
* its title and search text from the entity. The returned row is unflushed.
|
||||
*/
|
||||
public function createSearchResult(SearchableInterface $entity): SearchIndex
|
||||
{
|
||||
$values = [];
|
||||
$entityId = $this->requireEntityId($entity);
|
||||
$class = $this->resolveClass($entity);
|
||||
$index = $this->findIndex($class, $entityId) ?? new SearchIndex($class, $entityId);
|
||||
|
||||
foreach ($entity->getSearchValues() as $value) {
|
||||
$values[] = $value;
|
||||
}
|
||||
$index->setTitle($entity->getSearchTitle());
|
||||
$index->setSearchText(implode(' ', $entity->getSearchValues()));
|
||||
|
||||
$data = implode(' ', $values);
|
||||
|
||||
$class = $this->em->getClassMetadata($entity::class)->getName();
|
||||
|
||||
$searchResult = $this
|
||||
->em
|
||||
->getRepository(SearchIndex::class)
|
||||
->findOneBy(
|
||||
[
|
||||
'entityClass' => $class,
|
||||
'entityId' => $entity->getId()
|
||||
]
|
||||
);
|
||||
|
||||
if (!$searchResult) {
|
||||
$searchResult = new SearchIndex();
|
||||
$searchResult->setEntityClass($class);
|
||||
$searchResult->setEntityId($entity->getId());
|
||||
}
|
||||
|
||||
$searchResult->setTitle($entity->getSearchTitle());
|
||||
$searchResult->setData($data);
|
||||
|
||||
return $searchResult;
|
||||
return $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all searchable Doctrine entities the implement SearchableInterface
|
||||
* @return array
|
||||
* @return class-string[]
|
||||
*/
|
||||
public function getSearchableClasses(): array
|
||||
{
|
||||
$metadata = $this->em->getMetadataFactory()->getAllMetadata();
|
||||
$searchables = [];
|
||||
$classes = [];
|
||||
|
||||
foreach ($metadata as $meta) {
|
||||
foreach ($this->em->getMetadataFactory()->getAllMetadata() as $meta) {
|
||||
if ($meta->reflClass->implementsInterface(SearchableInterface::class)) {
|
||||
$searchables[] = $meta->name;
|
||||
$classes[] = $meta->name;
|
||||
}
|
||||
}
|
||||
|
||||
return $searchables;
|
||||
return $classes;
|
||||
}
|
||||
|
||||
private function findIndex(string $class, int $entityId): ?SearchIndex
|
||||
{
|
||||
return $this->em
|
||||
->getRepository(SearchIndex::class)
|
||||
->findOneBy(['entityClass' => $class, 'entityId' => $entityId]);
|
||||
}
|
||||
|
||||
private function requireEntityId(SearchableInterface $entity): int
|
||||
{
|
||||
$entityId = $entity->getId();
|
||||
|
||||
if ($entityId === null) {
|
||||
throw new \LogicException('Entity must be persisted before indexing.');
|
||||
}
|
||||
|
||||
return $entityId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T of object
|
||||
*
|
||||
* @param T $entity
|
||||
*
|
||||
* @return class-string<T>
|
||||
*/
|
||||
private function resolveClass(object $entity): string
|
||||
{
|
||||
return $this->em->getClassMetadata($entity::class)->getName();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user