diff --git a/src/Controller/InfoProviderController.php b/src/Controller/InfoProviderController.php index 11935f0d..a755d093 100644 --- a/src/Controller/InfoProviderController.php +++ b/src/Controller/InfoProviderController.php @@ -23,8 +23,11 @@ declare(strict_types=1); namespace App\Controller; +use App\Form\InfoProviderSystem\PartSearchType; +use App\Services\InfoProviderSystem\PartInfoRetriever; use App\Services\InfoProviderSystem\ProviderRegistry; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; @@ -42,8 +45,23 @@ class InfoProviderController extends AbstractController } #[Route('/search', name: 'info_providers_search')] - public function search(): Response + public function search(Request $request, PartInfoRetriever $infoRetriever): Response { + $form = $this->createForm(PartSearchType::class); + $form->handleRequest($request); + $results = null; + + if ($form->isSubmitted() && $form->isValid()) { + $keyword = $form->get('keyword')->getData(); + $providers = $form->get('providers')->getData(); + + $results = $infoRetriever->searchByKeyword(keyword: $keyword, providers: $providers); + } + + return $this->render('info_providers/search/part_search.html.twig', [ + 'form' => $form, + 'results' => $results, + ]); } } \ No newline at end of file diff --git a/src/Form/InfoProviderSystem/PartSearchType.php b/src/Form/InfoProviderSystem/PartSearchType.php new file mode 100644 index 00000000..5bbbf156 --- /dev/null +++ b/src/Form/InfoProviderSystem/PartSearchType.php @@ -0,0 +1,39 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Form\InfoProviderSystem; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\SearchType; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\FormBuilderInterface; + +class PartSearchType extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->add('keyword', SearchType::class); + $builder->add('providers', ProviderSelectType::class); + $builder->add('submit', SubmitType::class); + } +} \ No newline at end of file diff --git a/src/Form/InfoProviderSystem/ProviderSelectType.php b/src/Form/InfoProviderSystem/ProviderSelectType.php new file mode 100644 index 00000000..6ebe663d --- /dev/null +++ b/src/Form/InfoProviderSystem/ProviderSelectType.php @@ -0,0 +1,57 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Form\InfoProviderSystem; + +use App\Services\InfoProviderSystem\ProviderRegistry; +use App\Services\InfoProviderSystem\Providers\InfoProviderInterface; +use Hoa\Compiler\Llk\Rule\Choice; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\ChoiceList\ChoiceList; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class ProviderSelectType extends AbstractType +{ + public function __construct(private readonly ProviderRegistry $providerRegistry) + { + + } + + public function getParent(): string + { + return ChoiceType::class; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'choices' => $this->providerRegistry->getActiveProviders(), + 'choice_label' => ChoiceList::label($this, fn (?InfoProviderInterface $choice) => $choice?->getProviderInfo()['name']), + 'choice_value' => ChoiceList::value($this, fn(?InfoProviderInterface $choice) => $choice?->getProviderKey()), + + 'multiple' => true, + ]); + } + +} \ No newline at end of file diff --git a/src/Services/InfoProviderSystem/PartInfoRetriever.php b/src/Services/InfoProviderSystem/PartInfoRetriever.php new file mode 100644 index 00000000..5e7ecc31 --- /dev/null +++ b/src/Services/InfoProviderSystem/PartInfoRetriever.php @@ -0,0 +1,60 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Services\InfoProviderSystem; + +use App\Services\InfoProviderSystem\DTOs\SearchResultDTO; +use App\Services\InfoProviderSystem\Providers\InfoProviderInterface; + +class PartInfoRetriever +{ + public function __construct(private readonly ProviderRegistry $provider_registry) + { + } + + /** + * Search for a keyword in the given providers + * @param string[]|InfoProviderInterface[] $providers A list of providers to search in, either as provider keys or as provider instances + * @param string $keyword The keyword to search for + * @return SearchResultDTO[] The search results + */ + public function searchByKeyword(string $keyword, array $providers): array + { + $results = []; + + foreach ($providers as $provider) { + if (is_string($provider)) { + $provider = $this->provider_registry->getProviderByKey($provider); + } + + if (!$provider instanceof InfoProviderInterface) { + throw new \InvalidArgumentException("The provider must be either a provider key or a provider instance!"); + } + + /** @noinspection SlowArrayOperationsInLoopInspection */ + $results = array_merge($results, $provider->searchByKeyword($keyword)); + } + + return $results; + } +} \ No newline at end of file diff --git a/src/Services/InfoProviderSystem/Providers/TestProvider.php b/src/Services/InfoProviderSystem/Providers/TestProvider.php index 4147b5b4..04018f32 100644 --- a/src/Services/InfoProviderSystem/Providers/TestProvider.php +++ b/src/Services/InfoProviderSystem/Providers/TestProvider.php @@ -43,7 +43,7 @@ class TestProvider implements InfoProviderInterface public function isActive(): bool { - return false; + return true; } public function searchByKeyword(string $keyword): array diff --git a/templates/info_providers/search/part_search.html.twig b/templates/info_providers/search/part_search.html.twig new file mode 100644 index 00000000..79d18c9a --- /dev/null +++ b/templates/info_providers/search/part_search.html.twig @@ -0,0 +1,46 @@ +{% extends "main_card.html.twig" %} + +{% import "info_providers/providers.macro.html.twig" as providers_macro %} +{% import "helper.twig" as helper %} + +{% block title %}{% trans %}info_providers.providers_list.title{% endtrans %}{% endblock %} + +{% block card_title %} + {% trans %}info_providers.providers_list.title{% endtrans %} +{% endblock %} + +{% block card_content %} + + {{ form(form) }} + + {% if results is not null %} + + + + + + + + + + + + + + {% for result in results %} + + + + + + + + + + {% endfor %} + + +
NameDescriptionManufactuerMPNStatusProvider
{{ result.name }}{{ result.description }}{{ result.manufacturer ?? '' }}{{ result.mpn ?? '' }}{{ helper.m_status_to_badge(result.manufacturing_status) }}{{ result.provider_key }}: {{ result.provider_id }}
+ {% endif %} + +{% endblock %}