From 383fe786c7569f76b7b14a37b96a80ed90624f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 31 Dec 2014 02:34:33 +0100 Subject: [PATCH] Implementing new research behaviour refs #377 --- Search/PersonSearch.php | 137 +++++++++++++++++++++++++++++++++------- 1 file changed, 115 insertions(+), 22 deletions(-) diff --git a/Search/PersonSearch.php b/Search/PersonSearch.php index b970e0462..f15f9e322 100644 --- a/Search/PersonSearch.php +++ b/Search/PersonSearch.php @@ -20,11 +20,12 @@ namespace Chill\PersonBundle\Search; use Chill\MainBundle\Search\AbstractSearch; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use Chill\PersonBundle\Entity\Person; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\DependencyInjection\ContainerAwareTrait; +use Chill\MainBundle\Search\ParsingException; class PersonSearch extends AbstractSearch { @@ -32,14 +33,14 @@ class PersonSearch extends AbstractSearch /** * - * @var ObjectManager + * @var EntityManagerInterface */ - private $om; + private $em; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->om = $om; + $this->em = $em; } /* @@ -68,21 +69,24 @@ class PersonSearch extends AbstractSearch { return true; } + + public function supports($domain) + { + return 'person' === $domain; + } /* * (non-PHPdoc) * @see \Chill\MainBundle\Search\SearchInterface::renderResult() */ - public function renderResult($pattern, $start = 0, $limit = 50, array $options = array()) + public function renderResult(array $terms, $start = 0, $limit = 50, array $options = array()) { - $persons = $this->search($pattern, $start, $limit, $options); - return $this->container->get('templating')->render('ChillPersonBundle:Person:list.html.twig', array( - 'persons' => $persons, - 'pattern' => trim($pattern), - 'total' => count($persons) + 'persons' => $this->search($terms, $start, $limit, $options), + 'pattern' => 'trim($pattern)', + 'total' => $this->count($terms) )); } @@ -94,19 +98,108 @@ class PersonSearch extends AbstractSearch * @param array $options * @return Person[] */ - protected function search($pattern, $start, $limit, array $options = array()) + protected function search(array $terms, $start, $limit, array $options = array()) { - $dql = 'SELECT p FROM ChillPersonBundle:Person p' - . ' WHERE' - . ' LOWER(p.firstName) like LOWER(:q)' - . ' OR LOWER(p.lastName) like LOWER(:q)' - . 'ORDER BY p.lastName, p.firstName'; + $qb = $this->createQuery($terms, 'search'); - $query = $this->om->createQuery($dql) - ->setParameter('q', '%'.trim($pattern).'%') - ->setFirstResult($start) - ->setMaxResults($limit); + $qb->select('p') + ->setMaxResults($limit) + ->setFirstResult($start); - return $query->getResult() ; + return $qb->getQuery()->getResult(); } + + protected function count(array $terms) + { + $qb = $this->createQuery($terms); + + $qb->select('COUNT(p.id)'); + + return $qb->getQuery()->getSingleScalarResult(); + } + + + private $_cacheQuery = array(); + + /** + * + * @param array $terms + * @return \Doctrine\ORM\QueryBuilder + */ + protected function createQuery(array $terms) + { + //get from cache + $cacheKey = md5(serialize($terms)); + if (array_key_exists($cacheKey, $this->_cacheQuery)) { + return $this->_cacheQuery[$cacheKey]; + } + + $qb = $this->em->createQueryBuilder(); + + $qb->from('ChillPersonBundle:Person', 'p'); + + if (array_key_exists('firstname', $terms)) { + $qb->andWhere($qb->expr()->like('LOWER(p.firstName)', ':firstname')) + ->setParameter('firstname', '%'.$terms['firstname'].'%'); + } + + if (array_key_exists('lastname', $terms)) { + $qb->andWhere($qb->expr()->like('LOWER(p.lastName)', ':lastname')) + ->setParameter('lastname', '%'.$terms['lastname'].'%'); + } + + if (array_key_exists('birthdate', $terms)) { + try { + $date = new \DateTime($terms['birthdate']); + } catch (\Exception $ex) { + throw new ParsingException('The date is ' + . 'not parsable', 0, $ex); + } + + $qb->andWhere($qb->expr()->eq('p.dateOfBirth', ':birthdate')) + ->setParameter('birthdate', $date); + } + + if (array_key_exists('gender', $terms)) { + if (!in_array($terms['gender'], array(Person::GENRE_MAN, Person::GENRE_WOMAN))) { + throw new ParsingException('The gender ' + .$terms['gender'].' is not accepted. Should be "'.Person::GENRE_MAN + .'" or "'.Person::GENRE_WOMAN.'"'); + } + + $qb->andWhere($qb->expr()->eq('p.genre', ':gender')) + ->setParameter('gender', $terms['gender']); + } + + if (array_key_exists('nationality', $terms)) { + try { + $country = $this->em->createQuery('SELECT c FROM ' + . 'ChillMainBundle:Country c WHERE ' + . 'LOWER(c.countryCode) LIKE :code') + ->setParameter('code', $terms['nationality']) + ->getSingleResult(); + } catch (\Doctrine\ORM\NoResultException $ex) { + throw new ParsingException('The country code "'.$terms['nationality'].'" ' + . ', used in nationality, is unknow', 0, $ex); + } + + $qb->andWhere($qb->expr()->eq('p.nationality', ':nationality')) + ->setParameter('nationality', $country); + } + + if ($terms['_default'] !== '') { + $grams = explode(' ', $terms['_default']); + + foreach($grams as $key => $gram) { + $qb->andWhere($qb->expr() + ->like('LOWER(CONCAT(p.firstName, \' \', p.lastName))', ':default')) + ->setParameter('default', '%'.$gram.'%'); + } + } + + $this->_cacheQuery[$cacheKey] = $qb; + + return $qb; + } + } \ No newline at end of file