feat: search results

This commit is contained in:
2025-04-20 23:47:12 -05:00
parent a4ad43cfe0
commit f5552e3ad7
20 changed files with 796 additions and 113 deletions

View File

@@ -2,7 +2,15 @@
namespace App\Search\Action\Command;
class SearchCommand
{
use OneToMany\RichBundle\Contract\CommandInterface;
}
class SearchCommand implements CommandInterface
{
/**
* @param string $term
* @implements CommandInterface<SearchCommand>
*/
public function __construct(
public string $term
) {}
}

View File

@@ -2,7 +2,24 @@
namespace App\Search\Action\Handler;
class SearchHandler
{
use App\Search\Action\Result\SearchResult;
use App\Tmdb\Tmdb;
use OneToMany\RichBundle\Contract\CommandInterface;
use OneToMany\RichBundle\Contract\HandlerInterface;
use OneToMany\RichBundle\Contract\ResultInterface;
}
class SearchHandler implements HandlerInterface
{
public function __construct(
private Tmdb $tmdb,
) {}
/*** @implements HandlerInterface<SearchResult> */
public function handle(CommandInterface $command): ResultInterface
{
return new SearchResult(
term: $command->term,
results: $this->tmdb->search($command->term)
);
}
}

View File

@@ -2,7 +2,25 @@
namespace App\Search\Action\Input;
class SearchInput
{
use App\Search\Action\Command\SearchCommand;
use OneToMany\RichBundle\Attribute\SourceQuery;
use OneToMany\RichBundle\Attribute\SourceRequest;
use OneToMany\RichBundle\Contract\CommandInterface;
use OneToMany\RichBundle\Contract\InputInterface;
}
/**
* @implements InputInterface<SearchCommand>
*/
class SearchInput implements InputInterface
{
public function __construct(
#[SourceQuery('term')]
#[SourceRequest('term')]
public string $term
){}
public function toCommand(): CommandInterface
{
return new SearchCommand($this->term);
}
}

View File

@@ -2,7 +2,12 @@
namespace App\Search\Action\Result;
class SearchResult
{
use OneToMany\RichBundle\Contract\ResultInterface;
}
class SearchResult implements ResultInterface
{
public function __construct(
public string $term = "",
public array $results = []
) {}
}

View File

@@ -2,17 +2,27 @@
namespace App\Search\Framework\Controller;
use App\Search\Action\Handler\SearchHandler;
use App\Search\Action\Input\SearchInput;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
final class SearchController extends AbstractController
{
public function __construct(
private SearchHandler $searchHandler,
) {}
#[Route('/search', name: 'app_search', methods: ['GET'])]
public function index(): Response
public function index(
SearchInput $searchInput,
): Response
{
$results = $this->searchHandler->handle($searchInput->toCommand());
return $this->render('search/results.html.twig', [
'controller_name' => 'SearchController',
'results' => $results,
]);
}
}