118 lines
3.1 KiB
PHP
118 lines
3.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Pcm\SearchBundle\Service;
|
|
|
|
use Pcm\SearchBundle\Entity\SearchIndex;
|
|
use Pcm\SearchBundle\Entity\Interface\SearchableInterface;
|
|
use Doctrine\Common\Util\ClassUtils;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Doctrine\ORM\Proxy\Proxy;
|
|
|
|
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)
|
|
{
|
|
$searchIndex = $this->createSearchResult($entity);
|
|
|
|
$this->em->persist($searchIndex);
|
|
$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 = get_class($entity);
|
|
|
|
$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
|
|
*/
|
|
public function createSearchResult(SearchableInterface $entity): SearchIndex
|
|
{
|
|
$values = [];
|
|
|
|
foreach ($entity->getSearchValues() as $value) {
|
|
$values[] = $value;
|
|
}
|
|
|
|
$data = implode(' ', $values);
|
|
|
|
$class = get_class($entity);
|
|
|
|
if ($entity instanceof Proxy) {
|
|
$class = ClassUtils::getRealClass($class);
|
|
}
|
|
|
|
$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;
|
|
}
|
|
|
|
/**
|
|
* Finds all searchable Doctrine entities the implement SearchableInterface
|
|
* @return array
|
|
*/
|
|
public function getSearchableClasses(): array
|
|
{
|
|
$metadata = $this->em->getMetadataFactory()->getAllMetadata();
|
|
$searchables = [];
|
|
|
|
foreach ($metadata as $meta) {
|
|
if ($meta->reflClass->implementsInterface(SearchableInterface::class)) {
|
|
$searchables[] = $meta->name;
|
|
}
|
|
}
|
|
|
|
return $searchables;
|
|
}
|
|
}
|