diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 03a3cb0d6..f5223961a 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -6,4 +6,13 @@ services: chill.report.routing_loader: class: Chill\ReportBundle\Routing\RoutesLoader tags: - - { name: routing.loader } \ No newline at end of file + - { name: routing.loader } + + chill.report.search: + class: Chill\ReportBundle\Search\ReportSearch + arguments: + - '@doctrine.orm.entity_manager' + calls: + - [setContainer, ["@service_container"]] + tags: + - { name: chill.search, alias: 'report' } \ No newline at end of file diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index be994b2e3..270ac00e1 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -26,4 +26,10 @@ User: Utilisateur 'Unable to find this report.': Rapport introuvable. 'This is not the report of the person.': "La personne et le rapport sélectionnés ne sont pas associés" -'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 ?" \ No newline at end of file +'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 ?" + +#search +'You may not set a date argument and a date in default': Vous avez introduit deux dates, l'une avec l'argument date et l'autre en zone de recherche par défaut. Merci d'indiquer l'un ou l'autre +'You must provide either a date:YYYY-mm-dd argument or a YYYY-mm-dd default search': Merci d'indiquer soit un argument date:YYYY-mm-dd, soit une date dans la recherche par défaut. +'Reports search results': Recherche dans les rapports +'%total% reports matching the search "%pattern%"': '{0} Aucun rapport ne correspond à la recherche "%pattern%" | {1} Un rapport correspond à la recherche "%pattern%" | ]1,Inf]%total% rapports correspondent à la recherche "%pattern%"' \ No newline at end of file diff --git a/Resources/views/Search/results.html.twig b/Resources/views/Search/results.html.twig new file mode 100644 index 000000000..df3b0cb43 --- /dev/null +++ b/Resources/views/Search/results.html.twig @@ -0,0 +1,45 @@ +{# + * 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 . +#} +

{{ 'Reports search results'|trans }}

+ +

{{ '%total% reports matching the search "%pattern%"'|transchoice( total, {'%pattern%': pattern, '%total%' : total}) }}

+ +{% if reports|length > 0 %} + + + + + + + + + + + + {% for report in reports %} + + + + + + + + + {% endfor %} + +
{{ 'Person'|trans }}{{ 'Date'|trans }}{{ 'Report type'|trans }}  
{{ report.person }}{% if report.date %}{{ report.date|date('d-m-Y') }}{% endif %}{{ report.cFGroup.getName|localize_translatable_string }}{{ 'View the report' | trans }}{{ 'Update the report' | trans }}
+{% endif %} \ No newline at end of file diff --git a/Search/ReportSearch.php b/Search/ReportSearch.php new file mode 100644 index 000000000..ef5b53965 --- /dev/null +++ b/Search/ReportSearch.php @@ -0,0 +1,131 @@ + + * + * 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\ReportBundle\Search; + +use Chill\MainBundle\Search\AbstractSearch; +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Chill\MainBundle\Search\ParsingException; + +/** + * Search amongst reports + * + * @author Julien Fastré + */ +class ReportSearch extends AbstractSearch implements ContainerAwareInterface +{ + use \Symfony\Component\DependencyInjection\ContainerAwareTrait; + + /** + * @var EntityManagerInterface + */ + private $em; + + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + + public function getOrder() + { + return 10000; + } + + public function isActiveByDefault() + { + return false; + } + + public function renderResult(array $terms, $start = 0, $limit = 50, array $options = array()) + { + return $this->container->get('templating')->render('ChillReportBundle:Search:results.html.twig', array( + 'reports' => $this->getReports($terms, $start, $limit), + 'total' => $this->count($terms), + 'pattern' => $this->recomposePattern($terms, array( 'date'), 'report') + )); + } + + private function getReports(array $terms, $start, $limit) + { + $qb = $this->buildQuery($terms); + + $qb->select('r') + ->setMaxResults($limit) + ->setFirstResult($start) + ->orderBy('r.date', 'desc') + ; + + $reportQuery = $qb->getQuery(); + $reportQuery->setFetchMode("Chill\ReportBundle\Entity\Report", "person", \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER); + + return $reportQuery->getResult(); + } + + private function count(array $terms) + { + $qb = $this->buildQuery($terms); + + $qb->select('COUNT(r.id)'); + + return $qb->getQuery()->getSingleScalarResult(); + } + + + /** + * @param array $terms the terms + * @return \Doctrine\ORM\QueryBuilder + */ + private function buildQuery(array $terms) + { + + $query = $this->em->createQueryBuilder(); + + $query->from('ChillReportBundle:Report', 'r'); + + //throw a parsing exception if key 'date' and default is set + if (array_key_exists('date', $terms) && $terms['_default'] !== '') { + throw new ParsingException('You may not set a date argument and a date in default'); + } + //throw a parsing exception if no argument except report + if (!array_key_exists('date', $terms) && $terms['_default'] === '') { + throw new ParsingException('You must provide either a date:YYYY-mm-dd argument or a YYYY-mm-dd default search'); + } + + + if (array_key_exists('date', $terms)) { + $query->andWhere($query->expr()->eq('r.date', ':date')) + ->setParameter('date', $this->parseDate($terms['date'])) + ; + } elseif (array_key_exists('_default', $terms)) { + $query->andWhere($query->expr()->eq('r.date', ':date')) + ->setParameter('date', $this->parseDate($terms['_default'])) + ; + } + + return $query; + } + + public function supports($domain) + { + return $domain === 'report'; + } + +} diff --git a/Tests/Search/ReportSearchTest.php b/Tests/Search/ReportSearchTest.php new file mode 100644 index 000000000..60008e0cd --- /dev/null +++ b/Tests/Search/ReportSearchTest.php @@ -0,0 +1,107 @@ + + * + * 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\ReportBundle\Tests\Search; + +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; + +/** + * Test for report search + * + * @author Julien Fastré + */ +class ReportSearchTest extends WebTestCase +{ + + public function testSearchExpectedDefault() + { + $client = $this->getAuthenticatedClient(); + + $crawler = $client->request('GET', '/fr/search', array( + 'q' => '@report 2015-01-05' + )); + + $this->assertTrue($client->getResponse()->isSuccessful()); + $this->assertRegExp('/Charline/', $crawler->text()); + $this->assertRegExp('/Situation de logement/i', $crawler->text()); + } + + public function testNamedSearch() + { + $client = $this->getAuthenticatedClient(); + + $crawler = $client->request('GET', '/fr/search', array( + 'q' => '@report '.(new \DateTime('tomorrow'))->format('Y-m-d'), //there should be any result for future. And future is tomorrow + 'name' => 'report' + )); + + $this->assertTrue($client->getResponse()->isSuccessful()); + } + + public function testSearchByDate() + { + $client = $this->getAuthenticatedClient(); + + $crawler = $client->request('GET', '/fr/search', array( + 'q' => '@report date:2015-01-05' + )); + + $this->assertTrue($client->getResponse()->isSuccessful()); + $this->assertRegExp('/Charline/', $crawler->text()); + $this->assertRegExp('/Situation de logement/i', $crawler->text()); + } + + public function testSearchDoubleDate() + { + $client = $this->getAuthenticatedClient(); + + $crawler = $client->request('GET', '/fr/search', array( + 'q' => '@report date:2014-05-01 2014-05-06' + )); + + $this->assertGreaterThan(0, $crawler->filter('.error')->count()); + } + + public function testSearchEmtpy() + { + $client = $this->getAuthenticatedClient(); + + $crawler = $client->request('GET', '/fr/search', array( + 'q' => '@report ' + )); + + $this->assertGreaterThan(0, $crawler->filter('.error')->count()); + } + + + + + /** + * + * @return \Symfony\Component\BrowserKit\Client + */ + private function getAuthenticatedClient() + { + return static::createClient(array(), array( + 'PHP_AUTH_USER' => 'center a_social', + 'PHP_AUTH_PW' => 'password', + )); + } +}