You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
4.0 KiB
127 lines
4.0 KiB
<?php |
|
|
|
namespace App\Twig\Components; |
|
|
|
use App\Repository\ArticleRepository; |
|
use Psr\Log\LoggerInterface; |
|
use Symfony\Component\HttpFoundation\RequestStack; |
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; |
|
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; |
|
use Symfony\UX\LiveComponent\Attribute\LiveAction; |
|
use Symfony\UX\LiveComponent\Attribute\LiveProp; |
|
use Symfony\UX\LiveComponent\DefaultActionTrait; |
|
use Symfony\Contracts\Cache\CacheInterface; |
|
|
|
#[AsLiveComponent] |
|
final class SearchComponent |
|
{ |
|
use DefaultActionTrait; |
|
|
|
#[LiveProp(writable: true, useSerializerForHydration: true)] |
|
public string $query = ''; |
|
public array $results = []; |
|
|
|
public bool $interactive = true; |
|
|
|
#[LiveProp] |
|
public int $vol = 0; |
|
|
|
#[LiveProp(writable: true)] |
|
public int $page = 1; |
|
|
|
#[LiveProp] |
|
public int $resultsPerPage = 12; |
|
|
|
private const string SESSION_KEY = 'last_search_results'; |
|
private const string SESSION_QUERY_KEY = 'last_search_query'; |
|
|
|
public function __construct( |
|
private readonly ArticleRepository $articleRepository, |
|
private readonly TokenStorageInterface $tokenStorage, |
|
private readonly LoggerInterface $logger, |
|
private readonly CacheInterface $cache, |
|
private readonly RequestStack $requestStack |
|
) |
|
{ |
|
} |
|
|
|
public function mount(): void |
|
{ |
|
// Restore search results from session if available and no query provided |
|
if (empty($this->query)) { |
|
$session = $this->requestStack->getSession(); |
|
if ($session->has(self::SESSION_QUERY_KEY)) { |
|
$this->query = $session->get(self::SESSION_QUERY_KEY); |
|
$this->results = $session->get(self::SESSION_KEY, []); |
|
$this->logger->info('Restored search results from session for query: ' . $this->query); |
|
} |
|
} |
|
} |
|
|
|
#[LiveAction] |
|
public function search(): void |
|
{ |
|
$this->logger->info("Query: {$this->query}"); |
|
|
|
if (empty($this->query)) { |
|
$this->results = []; |
|
$this->clearSearchCache(); |
|
return; |
|
} |
|
|
|
// Check if the same query exists in session |
|
$session = $this->requestStack->getSession(); |
|
if ($session->has(self::SESSION_QUERY_KEY) && |
|
$session->get(self::SESSION_QUERY_KEY) === $this->query) { |
|
$this->results = $session->get(self::SESSION_KEY, []); |
|
$this->logger->info('Using cached search results for query: ' . $this->query); |
|
return; |
|
} |
|
|
|
try { |
|
$this->results = []; |
|
|
|
// Use database-based search instead of Elasticsearch |
|
$offset = ($this->page - 1) * $this->resultsPerPage; |
|
$results = $this->articleRepository->searchArticles( |
|
$this->query, |
|
$this->resultsPerPage, |
|
$offset |
|
); |
|
|
|
$this->logger->info('Search results count: ' . count($results)); |
|
$this->logger->info('Search results: ', ['results' => $results]); |
|
|
|
$this->results = $results; |
|
|
|
// Cache the search results in session |
|
$this->saveSearchToSession($this->query, $this->results); |
|
|
|
} catch (\Exception $e) { |
|
$this->logger->error('Search error: ' . $e->getMessage()); |
|
$this->results = []; |
|
} |
|
} |
|
|
|
/** |
|
* Save search results to session |
|
*/ |
|
private function saveSearchToSession(string $query, array $results): void |
|
{ |
|
$session = $this->requestStack->getSession(); |
|
$session->set(self::SESSION_QUERY_KEY, $query); |
|
$session->set(self::SESSION_KEY, $results); |
|
$this->logger->info('Saved search results to session for query: ' . $query); |
|
} |
|
|
|
/** |
|
* Clear search cache from session |
|
*/ |
|
private function clearSearchCache(): void |
|
{ |
|
$session = $this->requestStack->getSession(); |
|
$session->remove(self::SESSION_QUERY_KEY); |
|
$session->remove(self::SESSION_KEY); |
|
$this->logger->info('Cleared search cache from session'); |
|
} |
|
}
|
|
|