From 7a1ad24f0ef5dc38b390254756ee89709772180a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Fri, 7 May 2021 19:11:10 +0200 Subject: [PATCH] add endoint /api/1.0/search.json?q=xxx with fake data See https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/136 --- docs/source/installation/index.rst | 2 +- .../Controller/SearchController.php | 39 +++++---- .../ChillMainBundle/Search/Model/Result.php | 36 ++++++++ .../ChillMainBundle/Search/SearchApi.php | 85 +++++++++++++++++++ .../Normalizer/AddressNormalizer.php | 29 +++++++ src/Bundle/ChillMainBundle/config/routes.yaml | 7 ++ .../config/services/controller.yaml | 1 + .../config/services/search.yaml | 9 +- .../config/services/serializer.yaml | 4 + .../Normalizer/PersonNormalizer.php | 28 +++++- .../config/services/serializer.yaml | 1 + .../ChillThirdPartyExtension.php | 1 + .../Normalizer/ThirdPartyNormalizer.php | 31 +++++++ .../config/services.yaml | 3 - .../config/services/fixtures.yaml | 5 ++ .../config/services/serializer.yaml | 5 ++ 16 files changed, 261 insertions(+), 25 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Search/Model/Result.php create mode 100644 src/Bundle/ChillMainBundle/Search/SearchApi.php create mode 100644 src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php create mode 100644 src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php create mode 100644 src/Bundle/ChillThirdPartyBundle/config/services/serializer.yaml diff --git a/docs/source/installation/index.rst b/docs/source/installation/index.rst index 6aee5c526..1312480e3 100644 --- a/docs/source/installation/index.rst +++ b/docs/source/installation/index.rst @@ -82,7 +82,7 @@ Chill will be available at ``http://localhost:8001.`` Currently, there isn't any .. code-block:: bash - docker-compose exec --user $(id -u) php bin/console doctrine:fixtures:load + docker-compose exec --user $(id -u) php bin/console doctrine:fixtures:load --purge-with-truncate There are several users available: diff --git a/src/Bundle/ChillMainBundle/Controller/SearchController.php b/src/Bundle/ChillMainBundle/Controller/SearchController.php index a44af8e7b..45390ceca 100644 --- a/src/Bundle/ChillMainBundle/Controller/SearchController.php +++ b/src/Bundle/ChillMainBundle/Controller/SearchController.php @@ -22,6 +22,7 @@ namespace Chill\MainBundle\Controller; +use Chill\MainBundle\Serializer\Model\Collection; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Chill\MainBundle\Search\UnknowSearchDomainException; @@ -34,6 +35,7 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Chill\MainBundle\Search\SearchProvider; use Symfony\Contracts\Translation\TranslatorInterface; use Chill\MainBundle\Pagination\PaginatorFactory; +use Chill\MainBundle\Search\SearchApi; /** * Class SearchController @@ -42,32 +44,24 @@ use Chill\MainBundle\Pagination\PaginatorFactory; */ class SearchController extends AbstractController { - /** - * - * @var SearchProvider - */ - protected $searchProvider; + protected SearchProvider $searchProvider; - /** - * - * @var TranslatorInterface - */ - protected $translator; + protected TranslatorInterface $translator; - /** - * - * @var PaginatorFactory - */ - protected $paginatorFactory; + protected PaginatorFactory $paginatorFactory; + + protected SearchApi $searchApi; function __construct( SearchProvider $searchProvider, TranslatorInterface $translator, - PaginatorFactory $paginatorFactory + PaginatorFactory $paginatorFactory, + SearchApi $searchApi ) { $this->searchProvider = $searchProvider; $this->translator = $translator; $this->paginatorFactory = $paginatorFactory; + $this->searchApi = $searchApi; } @@ -152,6 +146,19 @@ class SearchController extends AbstractController array('results' => $results, 'pattern' => $pattern) ); } + + public function searchApi(Request $request, $_format): JsonResponse + { + //TODO this is an incomplete implementation + $query = $request->query->get('q', ''); + + $results = $this->searchApi->getResults($query, 0, 150); + $paginator = $this->paginatorFactory->create(count($results)); + + $collection = new Collection($results, $paginator); + + return $this->json($collection); + } public function advancedSearchListAction(Request $request) { diff --git a/src/Bundle/ChillMainBundle/Search/Model/Result.php b/src/Bundle/ChillMainBundle/Search/Model/Result.php new file mode 100644 index 000000000..a88c2f55f --- /dev/null +++ b/src/Bundle/ChillMainBundle/Search/Model/Result.php @@ -0,0 +1,36 @@ +relevance = $relevance; + $this->result = $result; + } + + public function getRelevance(): float + { + return $this->relevance; + } + + public function getResult() + { + return $this->result; + } + + + +} diff --git a/src/Bundle/ChillMainBundle/Search/SearchApi.php b/src/Bundle/ChillMainBundle/Search/SearchApi.php new file mode 100644 index 000000000..0c7c7b561 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Search/SearchApi.php @@ -0,0 +1,85 @@ +em = $em; + $this->search = $search; + } + + /** + * @return Model/Result[] + */ + public function getResults(string $query, int $offset, int $maxResult): array + { + // **warning again**: this is an incomplete implementation + $results = []; + + foreach ($this->getPersons($query) as $p) { + $results[] = new Model\Result((float)\rand(0, 100) / 100, $p); + } + foreach ($this->getThirdParties($query) as $t) { + $results[] = new Model\Result((float)\rand(0, 100) / 100, $t); + } + + \usort($results, function(Model\Result $a, Model\Result $b) { + return ($a->getRelevance() <=> $b->getRelevance()) * -1; + }); + + return $results; + } + + public function countResults(string $query): int + { + return 0; + } + + private function getThirdParties(string $query) + { + $thirdPartiesIds = $this->em->createQuery('SELECT t.id FROM '.ThirdParty::class.' t') + ->getScalarResult(); + + $nbResults = rand(0, 15); + if ($nbResults === 1) { + $nbResults++; + } + $ids = \array_rand($thirdPartiesIds, $nbResults); + + return $this->em->getRepository(ThirdParty::class) + ->findById($ids); + } + + private function getPersons(string $query) + { + $params = [ + SearchInterface::SEARCH_PREVIEW_OPTION => false + ]; + $search = $this->search->getResultByName($query, 'person_regular', 0, 50, $params, 'json'); + $ids = \array_map(function($r) { return $r['id']; }, $search['results']); + + + if (count($ids) === 0) { + return []; + } + + return $this->em->getRepository(Person::class) + ->findById($ids) + ; + } + +} diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php new file mode 100644 index 000000000..29d760b71 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/AddressNormalizer.php @@ -0,0 +1,29 @@ +getId(); + $data['text'] = $address->getStreet().', '.$address->getBuildingName(); + $data['postcode']['name'] = $address->getPostCode()->getName(); + + return $data; + } + + public function supportsNormalization($data, string $format = null) + { + return $data instanceof Address; + } + + +} diff --git a/src/Bundle/ChillMainBundle/config/routes.yaml b/src/Bundle/ChillMainBundle/config/routes.yaml index 3fd7eafab..bc3187add 100644 --- a/src/Bundle/ChillMainBundle/config/routes.yaml +++ b/src/Bundle/ChillMainBundle/config/routes.yaml @@ -69,6 +69,13 @@ chill_main_search: requirements: _format: html|json +chill_main_search_global: + path: '/api/1.0/search.{_format}' + controller: Chill\MainBundle\Controller\SearchController::searchApi + format: 'json' + requirements: + _format: 'json' + chill_main_advanced_search: path: /{_locale}/search/advanced/{name} controller: Chill\MainBundle\Controller\SearchController::advancedSearchAction diff --git a/src/Bundle/ChillMainBundle/config/services/controller.yaml b/src/Bundle/ChillMainBundle/config/services/controller.yaml index 5fb542786..6021e3d72 100644 --- a/src/Bundle/ChillMainBundle/config/services/controller.yaml +++ b/src/Bundle/ChillMainBundle/config/services/controller.yaml @@ -16,6 +16,7 @@ services: $searchProvider: '@chill_main.search_provider' $translator: '@Symfony\Contracts\Translation\TranslatorInterface' $paginatorFactory: '@Chill\MainBundle\Pagination\PaginatorFactory' + $searchApi: '@Chill\MainBundle\Search\SearchApi' tags: ['controller.service_arguments'] Chill\MainBundle\Controller\PermissionsGroupController: diff --git a/src/Bundle/ChillMainBundle/config/services/search.yaml b/src/Bundle/ChillMainBundle/config/services/search.yaml index e8a457415..b7a1656b3 100644 --- a/src/Bundle/ChillMainBundle/config/services/search.yaml +++ b/src/Bundle/ChillMainBundle/config/services/search.yaml @@ -1,3 +1,10 @@ services: chill_main.search_provider: - class: Chill\MainBundle\Search\SearchProvider \ No newline at end of file + class: Chill\MainBundle\Search\SearchProvider + + Chill\MainBundle\Search\SearchProvider: '@chill_main.search_provider' + + Chill\MainBundle\Search\SearchApi: + arguments: + $em: '@Doctrine\ORM\EntityManagerInterface' + $search: '@Chill\MainBundle\Search\SearchProvider' diff --git a/src/Bundle/ChillMainBundle/config/services/serializer.yaml b/src/Bundle/ChillMainBundle/config/services/serializer.yaml index fb5f57b7e..fa30b876d 100644 --- a/src/Bundle/ChillMainBundle/config/services/serializer.yaml +++ b/src/Bundle/ChillMainBundle/config/services/serializer.yaml @@ -4,6 +4,10 @@ services: tags: - { name: 'serializer.normalizer', priority: 64 } + Chill\MainBundle\Serializer\Normalizer\AddressNormalizer: + tags: + - { name: 'serializer.normalizer', priority: 64 } + Chill\MainBundle\Serializer\Normalizer\DateNormalizer: tags: - { name: 'serializer.normalizer', priority: 64 } diff --git a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonNormalizer.php b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonNormalizer.php index d88d27ddc..a315fb326 100644 --- a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonNormalizer.php +++ b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonNormalizer.php @@ -25,7 +25,7 @@ use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Chill\PersonBundle\Repository\PersonRepository; use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; - +use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension; /** * Serialize a Person entity @@ -41,25 +41,45 @@ class PersonNormalizer implements protected PersonRepository $repository; + private ChillEntityRenderExtension $render; + public const GET_PERSON = 'get_person'; - public function __construct(PersonRepository $repository) + public function __construct(PersonRepository $repository, ChillEntityRenderExtension $render) { $this->repository = $repository; + $this->render = $render; } public function normalize($person, string $format = null, array $context = array()) { /** @var Person $person */ return [ - 'id' => $person->getId(), + 'type' => 'person', + 'person_id' => $person->getId(), + 'text' => $this->render->renderString($person), 'firstName' => $person->getFirstName(), 'lastName' => $person->getLastName(), 'birthdate' => $this->normalizer->normalize($person->getBirthdate()), - 'center' => $this->normalizer->normalize($person->getCenter()) + 'center' => $this->normalizer->normalize($person->getCenter()), + 'phonenumber' => $person->getPhonenumber(), + 'mobilenumber' => $person->getMobilenumber(), + 'altNames' => $this->normalizeAltNames($person->getAltNames()) ]; } + protected function normalizeAltNames($altNames): array + { + $r = []; + + foreach ($altNames as $n) { + $r[] = [ 'key' => $n->getKey(), 'label' => $n->getLabel() ]; + } + + return $r; + } + + public function denormalize($data, string $type, string $format = null, array $context = []): Person { if ($context[self::GET_PERSON] ?? true) { diff --git a/src/Bundle/ChillPersonBundle/config/services/serializer.yaml b/src/Bundle/ChillPersonBundle/config/services/serializer.yaml index 092dc2320..843c984f8 100644 --- a/src/Bundle/ChillPersonBundle/config/services/serializer.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/serializer.yaml @@ -3,6 +3,7 @@ services: Chill\PersonBundle\Serializer\Normalizer\PersonNormalizer: arguments: $repository: '@Chill\PersonBundle\Repository\PersonRepository' + $render: '@Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension' tags: - { name: 'serializer.normalizer', priority: 64 } diff --git a/src/Bundle/ChillThirdPartyBundle/DependencyInjection/ChillThirdPartyExtension.php b/src/Bundle/ChillThirdPartyBundle/DependencyInjection/ChillThirdPartyExtension.php index aaf64a9e0..7ada8db8e 100644 --- a/src/Bundle/ChillThirdPartyBundle/DependencyInjection/ChillThirdPartyExtension.php +++ b/src/Bundle/ChillThirdPartyBundle/DependencyInjection/ChillThirdPartyExtension.php @@ -34,6 +34,7 @@ class ChillThirdPartyExtension extends Extension implements PrependExtensionInte $loader->load('services/templating.yaml'); $loader->load('services/menu.yaml'); $loader->load('services/fixtures.yaml'); + $loader->load('services/serializer.yaml'); } public function prepend(ContainerBuilder $container) diff --git a/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php b/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php new file mode 100644 index 000000000..b10ed4d7e --- /dev/null +++ b/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php @@ -0,0 +1,31 @@ +getName(); + $data['thirdparty_id'] = $thirdParty->getId(); + $data['address'] = $this->normalizer->normalize($thirdParty->getAddress(), $format, + [ 'address_rendering' => 'short' ]); + + return $data; + } + + public function supportsNormalization($data, string $format = null) + { + return $data instanceof ThirdParty; + } +} diff --git a/src/Bundle/ChillThirdPartyBundle/config/services.yaml b/src/Bundle/ChillThirdPartyBundle/config/services.yaml index d57dadd4a..4f179f43e 100644 --- a/src/Bundle/ChillThirdPartyBundle/config/services.yaml +++ b/src/Bundle/ChillThirdPartyBundle/config/services.yaml @@ -1,5 +1,2 @@ --- services: - Chill\ThirdPartyBundle\DataFixtures\ORM\LoadThirdParty: - tags: - - { 'name': doctrine.fixture.orm } diff --git a/src/Bundle/ChillThirdPartyBundle/config/services/fixtures.yaml b/src/Bundle/ChillThirdPartyBundle/config/services/fixtures.yaml index e69de29bb..d57dadd4a 100644 --- a/src/Bundle/ChillThirdPartyBundle/config/services/fixtures.yaml +++ b/src/Bundle/ChillThirdPartyBundle/config/services/fixtures.yaml @@ -0,0 +1,5 @@ +--- +services: + Chill\ThirdPartyBundle\DataFixtures\ORM\LoadThirdParty: + tags: + - { 'name': doctrine.fixture.orm } diff --git a/src/Bundle/ChillThirdPartyBundle/config/services/serializer.yaml b/src/Bundle/ChillThirdPartyBundle/config/services/serializer.yaml new file mode 100644 index 000000000..286bb74ec --- /dev/null +++ b/src/Bundle/ChillThirdPartyBundle/config/services/serializer.yaml @@ -0,0 +1,5 @@ +services: + Chill\ThirdPartyBundle\Serializer\Normalizer\: + resource: '../../Serializer/Normalizer/' + tags: + - { name: 'serializer.normalizer', priority: 64 }