From ffd2ee6f6974ebf4a283c705d58068846364ecf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 22 Aug 2017 22:32:58 +0200 Subject: [PATCH] add advanced search --- Controller/SearchController.php | 67 +++++++++++++++++++ Form/AdvancedSearchType.php | 59 ++++++++++++++++ Resources/config/routing.yml | 4 ++ Resources/translations/messages.fr.yml | 7 ++ .../views/Search/advanced_search.html.twig | 42 ++++++++++++ Search/HasAdvancedSearchFormInterface.php | 34 ++++++++++ Search/SearchProvider.php | 28 ++++++++ 7 files changed, 241 insertions(+) create mode 100644 Form/AdvancedSearchType.php create mode 100644 Resources/views/Search/advanced_search.html.twig create mode 100644 Search/HasAdvancedSearchFormInterface.php diff --git a/Controller/SearchController.php b/Controller/SearchController.php index 87a750175..49a648f43 100644 --- a/Controller/SearchController.php +++ b/Controller/SearchController.php @@ -28,6 +28,8 @@ use Chill\MainBundle\Search\UnknowSearchDomainException; use Chill\MainBundle\Search\UnknowSearchNameException; use Chill\MainBundle\Search\ParsingException; use Chill\MainBundle\Search\SearchInterface; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\Extension\Core\Type\FormType; /** * @@ -104,4 +106,69 @@ class SearchController extends Controller ); } + public function advancedSearchAction($name, Request $request) + { + try { + /* @var $variable Chill\MainBundle\Search\SearchProvider */ + $searchProvider = $this->get('chill.main.search_provider'); + /* @var $variable Chill\MainBundle\Search\HasAdvancedSearchFormInterface */ + $search = $this->get('chill.main.search_provider') + ->getHasAdvancedFormByName($name); + + } catch (\Chill\MainBundle\Search\UnknowSearchNameException $e) { + throw $this->createNotFoundException("no advanced search for " + . "$name"); + } + + if ($request->query->has('q')) { + $data = $search->convertTermsToFormData($searchProvider->parse( + $request->query->get('q'))); + } + + $form = $this->createAdvancedSearchForm($name, $data ?? []); + + if ($request->isMethod(Request::METHOD_POST)) { + $form->handleRequest($request); + + if ($form->isValid()) { + $pattern = $this->get('chill.main.search_provider') + ->getHasAdvancedFormByName($name) + ->convertFormDataToQuery($form->getData()); + + return $this->redirectToRoute('chill_main_search', [ + 'q' => $pattern, 'name' => $name + ]); + } + } + + return $this->render('ChillMainBundle:Search:advanced_search.html.twig', + [ + 'form' => $form->createView(), + 'name' => $name + ]); + } + + protected function createAdvancedSearchForm($name, array $data = []) + { + $builder = $this + ->get('form.factory') + ->createNamedBuilder( + null, + FormType::class, + $data, + [ 'method' => Request::METHOD_POST ] + ); + + $this->get('chill.main.search_provider') + ->getHasAdvancedFormByName($name) + ->buildForm($builder) + ; + + $builder->add('submit', SubmitType::class, [ + 'label' => 'Search' + ]); + + return $builder->getForm(); + } + } diff --git a/Form/AdvancedSearchType.php b/Form/AdvancedSearchType.php new file mode 100644 index 000000000..a70a34b31 --- /dev/null +++ b/Form/AdvancedSearchType.php @@ -0,0 +1,59 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +namespace Chill\MainBundle\Form; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Chill\MainBundle\Search\SearchProvider; + +/** + * + * + * @author Julien Fastré + */ +class AdvancedSearchType extends AbstractType +{ + /** + * + * @var SearchProvider + */ + protected $searchProvider; + + public function __construct(SearchProvider $searchProvider) + { + $this->searchProvider = $searchProvider; + } + + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $this->searchProvider + ->getHasAdvancedFormByName($options['search_service']) + ->createSearchForm($builder) + ; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver + ->setRequired('search_service') + ->setAllowedTypes('search_service', [ 'string' ]) + ; + } +} diff --git a/Resources/config/routing.yml b/Resources/config/routing.yml index 6656b70f9..3252e8f96 100644 --- a/Resources/config/routing.yml +++ b/Resources/config/routing.yml @@ -62,6 +62,10 @@ chill_main_admin_permissions: chill_main_search: path: /{_locale}/search defaults: { _controller: ChillMainBundle:Search:search } + +chill_main_advanced_search: + path: /{_locale}/search/advanced/{name} + defaults: { _controller: ChillMainBundle:Search:advancedSearch } login: path: /login diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index 9f754324c..06e63ce31 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -32,6 +32,8 @@ Confirm: Confirmer Cancel: Annuler Save: Enregistrer +'You are going to leave a page with unsubmitted data. Are you sure you want to leave ?': "Vous allez quitter la page alors que des données n'ont pas été enregistrées. Êtes vous sûr de vouloir partir ?" + Edit: Modifier Update: Mettre à jour Back to the list: Retour à la liste @@ -56,6 +58,7 @@ You should not have more than one domain. : Vous ne devriez pas avoir plus d'un Search %pattern%: Recherche de "%pattern%" Results %start%-%end% of %total%: Résultats %start%-%end% sur %total% See all results: Voir tous les résultats +Advanced search: Recherche avancée #admin Create: Créer @@ -69,6 +72,10 @@ Users and permissions: Utilisateurs et permissions Permissions Menu: Gestion des droits Permissions management of your chill installation: Gestion des permissions de votre instance +#admin section +'Administration interface': Interface d'administration + + #admin section for center's administration Create a new center: Créer un nouveau centre Center list: Liste des centres diff --git a/Resources/views/Search/advanced_search.html.twig b/Resources/views/Search/advanced_search.html.twig new file mode 100644 index 000000000..48c2bd230 --- /dev/null +++ b/Resources/views/Search/advanced_search.html.twig @@ -0,0 +1,42 @@ +{# + * Copyright (C) 2014, Champs Libres Cooperative SCRLFS, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +#} +{% extends "ChillMainBundle::layout.html.twig" %} + + +{% block title 'Advanced search for %name%'|trans({ '%name%' : name }) %} + +{% block content %} + + {{ form_start(form) }} + + {% for f in form %} + {% if f.vars.name != 'submit' %} + {{ form_row(f) }} + {% endif %} + {% endfor %} + + + +
    +
  • + {{ form_widget(form.submit, { 'attr' : { 'class': 'sc-button bt-create change-icon' } } ) }} +
  • +
+ + {{ form_end(form) }} + +{% endblock %} diff --git a/Search/HasAdvancedSearchFormInterface.php b/Search/HasAdvancedSearchFormInterface.php new file mode 100644 index 000000000..f258a51f8 --- /dev/null +++ b/Search/HasAdvancedSearchFormInterface.php @@ -0,0 +1,34 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +namespace Chill\MainBundle\Search; + +use Symfony\Component\Form\FormBuilderInterface; + +/** + * + * @author Julien Fastré + */ +interface HasAdvancedSearchFormInterface extends SearchInterface +{ + public function buildForm(FormBuilderInterface $builder); + + public function convertFormDataToQuery(array $data); + + public function convertTermsToFormData(array $terms) ; + +} diff --git a/Search/SearchProvider.php b/Search/SearchProvider.php index 57241f8d2..db8aec208 100644 --- a/Search/SearchProvider.php +++ b/Search/SearchProvider.php @@ -3,6 +3,7 @@ namespace Chill\MainBundle\Search; use Chill\MainBundle\Search\SearchInterface; +use Chill\MainBundle\Search\HasAdvancedSearchFormInterface; /** * a service which gather all search services defined into the bundles @@ -29,6 +30,12 @@ class SearchProvider */ private $searchServices = array(); + /** + * + * @var HasAdvancedSearchForm[] + */ + private $hasAdvancedFormSearchServices = array(); + /* * return search services in an array, ordered by * the order key (defined in service definition) @@ -211,10 +218,31 @@ class SearchProvider throw new UnknowSearchNameException($name); } } + + /** + * return searchservice with an advanced form, defined in service + * definition. + * + * @param string $name + * @return HasAdvancedSearchForm + * @throws UnknowSearchNameException + */ + public function getHasAdvancedFormByName($name) + { + if (\array_key_exists($name, $this->hasAdvancedFormSearchServices)) { + return $this->hasAdvancedFormSearchServices[$name]; + } else { + throw new UnknowSearchNameException($name); + } + } public function addSearchService(SearchInterface $service, $name) { $this->searchServices[$name] = $service; + + if ($service instanceof HasAdvancedSearchFormInterface) { + $this->hasAdvancedFormSearchServices[$name] = $service; + } } /**