* * 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\PersonBundle\Search; use Chill\MainBundle\Search\AbstractSearch; use Chill\PersonBundle\Repository\PersonACLAwareRepositoryInterface; use Chill\PersonBundle\Entity\Person; use Chill\MainBundle\Search\SearchInterface; use Chill\MainBundle\Search\ParsingException; use Chill\MainBundle\Pagination\PaginatorFactory; use Symfony\Component\Form\Extension\Core\Type\TextType; use Chill\MainBundle\Form\Type\ChillDateType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Chill\MainBundle\Search\HasAdvancedSearchFormInterface; use Symfony\Component\Templating\EngineInterface; class PersonSearch extends AbstractSearch implements HasAdvancedSearchFormInterface { protected EngineInterface $templating; protected PaginatorFactory $paginatorFactory; protected PersonACLAwareRepositoryInterface $personACLAwareRepository; const NAME = "person_regular"; private const POSSIBLE_KEYS = [ '_default', 'firstname', 'lastname', 'birthdate', 'birthdate-before', 'birthdate-after', 'gender', 'nationality' ]; public function __construct( EngineInterface $templating, PaginatorFactory $paginatorFactory, PersonACLAwareRepositoryInterface $personACLAwareRepository ) { $this->templating = $templating; $this->paginatorFactory = $paginatorFactory; $this->personACLAwareRepository = $personACLAwareRepository; } /* * (non-PHPdoc) * @see \Chill\MainBundle\Search\SearchInterface::getOrder() */ public function getOrder() { return 100; } /* * (non-PHPdoc) * @see \Chill\MainBundle\Search\SearchInterface::isActiveByDefault() */ public function isActiveByDefault() { return true; } public function supports($domain, $format) { return 'person' === $domain; } /* * (non-PHPdoc) * @see \Chill\MainBundle\Search\SearchInterface::renderResult() */ 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->templating->render('@ChillPerson/Person/list_with_period.html.twig', array( 'persons' => $this->search($terms, $start, $limit, $options), 'pattern' => $this->recomposePattern( $terms, \array_filter(self::POSSIBLE_KEYS, fn($item) => $item !== '_default'), $terms['_domain'] ), 'total' => $total, 'start' => $start, 'search_name' => self::NAME, 'preview' => $options[SearchInterface::SEARCH_PREVIEW_OPTION], 'paginator' => $paginator )); } 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()) { [ '_default' => $default, 'firstname' => $firstname, 'lastname' => $lastname, 'birthdate' => $birthdate, 'birthdate-before' => $birthdateBefore, 'birthdate-after' => $birthdateAfter, 'gender' => $gender, 'nationality' => $countryCode, ] = $terms + \array_fill_keys(self::POSSIBLE_KEYS, null); foreach (['birthdateBefore', 'birthdateAfter', 'birthdate'] as $v) { if (NULL !== ${$v}) { try { ${$v} = new \DateTime(${$v}); } catch (\Exception $e) { throw new ParsingException('The date is ' . 'not parsable', 0, $e); } } } return $this->personACLAwareRepository ->findBySearchCriteria( $start, $limit, $options['simplify'] ?? false, $default, $firstname, $lastname, $birthdate, $birthdateBefore, $birthdateAfter, $gender, $countryCode, ); } protected function count(array $terms): int { [ '_default' => $default, 'firstname' => $firstname, 'lastname' => $lastname, 'birthdate' => $birthdate, 'birthdate-before' => $birthdateBefore, 'birthdate-after' => $birthdateAfter, 'gender' => $gender, 'nationality' => $countryCode, ] = $terms + \array_fill_keys(self::POSSIBLE_KEYS, null); foreach (['birthdateBefore', 'birthdateAfter', 'birthdate'] as $v) { if (NULL !== ${$v}) { try { ${$v} = new \DateTime(${$v}); } catch (\Exception $e) { throw new ParsingException('The date is ' . 'not parsable', 0, $e); } } } return $this->personACLAwareRepository ->countBySearchCriteria( $default, $firstname, $lastname, $birthdate, $birthdateBefore, $birthdateAfter, $gender, $countryCode, ); } public function buildForm(FormBuilderInterface $builder) { $builder ->add('_default', TextType::class, [ 'label' => 'First name or Last name', 'required' => false ]) ->add('firstname', TextType::class, [ 'label' => 'First name', 'required' => false ]) ->add('lastname', TextType::class, [ 'label' => 'Last name', 'required' => false ]) ->add('birthdate-after', ChillDateType::class, [ 'label' => 'Birthdate after', 'required' => false ]) ->add('birthdate', ChillDateType::class, [ 'label' => 'Birthdate', 'required' => false ]) ->add('birthdate-before', ChillDateType::class, [ 'label' => 'Birthdate before', 'required' => false ]) ->add('gender', ChoiceType::class, [ 'choices' => [ 'Man' => Person::MALE_GENDER, 'Woman' => Person::FEMALE_GENDER ], 'label' => 'Gender', 'required' => false ]) ; } public function convertFormDataToQuery(array $data) { $string = '@person '; $string .= empty($data['_default']) ? '' : $data['_default'].' '; foreach(['firstname', 'lastname', 'gender'] as $key) { $string .= empty($data[$key]) ? '' : $key.':'. // add quote if contains spaces (strpos($data[$key], ' ') !== false ? '"'.$data[$key].'"': $data[$key]) .' '; } foreach (['birthdate', 'birthdate-before', 'birthdate-after'] as $key) { $string .= empty($data[$key]) ? '' : $key.':'.$data[$key]->format('Y-m-d').' ' ; } return $string; } public function convertTermsToFormData(array $terms) { foreach(['firstname', 'lastname', 'gender', '_default'] as $key) { $data[$key] = $terms[$key] ?? null; } // parse dates foreach (['birthdate', 'birthdate-before', 'birthdate-after'] as $key) { if (\array_key_exists($key, $terms)) { try { $date = new \DateTime($terms[$key]); } catch (\Exception $ex) { throw new ParsingException("The date for $key is " . 'not parsable', 0, $ex); } } $data[$key] = $date ?? null; } return $data; } public function getAdvancedSearchTitle() { return 'Search within persons'; } public static function getAlias(): string { return self::NAME; } }