em = $em; $this->user = $tokenStorage->getToken()->getUser(); $this->helper = $helper; $this->paginatorFactory = $paginatorFactory; // throw an error if user is not a valid user if (!$this->user instanceof \Chill\MainBundle\Entity\User) { throw new \LogicException('The user provided must be an instance' . ' of Chill\MainBundle\Entity\User'); } } /* * (non-PHPdoc) * @see \Chill\MainBundle\Search\SearchInterface::getOrder() */ public function getOrder() { return 200; } /* * (non-PHPdoc) * @see \Chill\MainBundle\Search\SearchInterface::isActiveByDefault() */ public function isActiveByDefault() { return true; } public function supports($domain, $format) { return 'person' === $domain; } /** * @param array $terms * @param int $start * @param int $limit * @param array $options * @param string $format * @return array */ public function renderResult(array $terms, $start = 0, $limit = 50, array $options = array(), $format = 'html') { $total = $this->count($terms); $paginator = $this->paginatorFactory->create($total); if ($format === 'html') { return $this->container->get('templating')->render('ChillPersonBundle:Person:list.html.twig', array( 'persons' => $this->search($terms, $start, $limit, $options), 'pattern' => $this->recomposePattern($terms, array('nationality', 'firstname', 'lastname', 'birthdate', 'gender', 'birthdate-before','birthdate-after'), $terms['_domain']), 'total' => $total, 'start' => $start, 'search_name' => self::NAME, 'preview' => $options[SearchInterface::SEARCH_PREVIEW_OPTION], 'paginator' => $paginator, 'title' => "Similar persons" )); } elseif ($format === 'json') { return [ 'results' => $this->search($terms, $start, $limit, \array_merge($options, [ 'simplify' => true ])), 'pagination' => [ 'more' => $paginator->hasNextPage() ] ]; } } /** * * @param string $pattern * @param int $start * @param int $limit * @param array $options * @return Person[] */ protected function search(array $terms, $start, $limit, array $options = array()) { $qb = $this->createQuery($terms, 'search'); if ($options['simplify'] ?? false) { $qb->select( 'p.id', $qb->expr()->concat( 'p.firstName', $qb->expr()->literal(' '), 'p.lastName' ).'AS text' ); } else { $qb->select('p'); } $qb ->setMaxResults($limit) ->setFirstResult($start); //order by firstname, lastname $qb ->orderBy('p.firstName') ->addOrderBy('p.lastName'); if ($options['simplify'] ?? false) { return $qb->getQuery()->getResult(Query::HYDRATE_ARRAY); } else { 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 clone $this->_cacheQuery[$cacheKey]; } $qb = $this->em->createQueryBuilder(); $qb->from('ChillPersonBundle:Person', 'p'); if ($terms['_default'] !== '') { $grams = explode(' ', $terms['_default']); foreach($grams as $key => $gram) { $qb->andWhere( 'SIMILARITY(p.fullnameCanonical, UNACCENT(LOWER(:default_'.$key.'))) >= 0.15') ->setParameter('default_'.$key, '%'.$gram.'%'); } } //restraint center for security $reachableCenters = $this->helper->getReachableCenters($this->user, new Role('CHILL_PERSON_SEE')); $qb->andWhere($qb->expr() ->in('p.center', ':centers')) ->setParameter('centers', $reachableCenters) ; $this->_cacheQuery[$cacheKey] = $qb; return clone $qb; } }