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', ChillDateType::class, [ 'label' => 'Birthdate', 'required' => false, ]) ->add('birthdate-after', ChillDateType::class, [ 'label' => 'Birthdate after', 'required' => false, ]) ->add('birthdate-before', ChillDateType::class, [ 'label' => 'Birthdate before', 'required' => false, ]) ->add('phonenumber', ChillPhoneNumberType::class, [ 'required' => false, 'label' => 'Part of the phonenumber', ]) ->add('gender', GenderType::class, [ 'label' => 'Gender', 'required' => false, 'expanded' => false, 'placeholder' => 'All genders', ]) ->add('city', TextType::class, [ 'required' => false, 'label' => 'City or postal code', ]); } public function convertFormDataToQuery(array $data) { $string = '@person '; $string .= !isset($data['_default']) ? '' : $data['_default'].' '; foreach (['firstname', 'lastname', 'gender', 'city'] as $key) { $string .= !isset($data[$key]) ? '' : $key.':'. // add quote if contains spaces (str_contains((string) $data[$key], ' ') ? '"'.$data[$key].'"' : $data[$key]) .' '; } foreach (['birthdate', 'birthdate-before', 'birthdate-after'] as $key) { $string .= !isset($data[$key]) ? '' : $key.':'.$data[$key]->format('Y-m-d').' '; } $string .= !isset($data['phonenumber']) ? '' : 'phonenumber:'.$data['phonenumber']->getNationalNumber(); return $string; } public function convertTermsToFormData(array $terms) { $data = []; foreach (['firstname', 'lastname', 'gender', '_default', 'phonenumber', 'city'] 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; } if (\array_key_exists('phonenumber', $terms)) { try { $phonenumber = new PhoneNumber(); $phonenumber->setNationalNumber($terms['phonenumber']); } catch (\Exception $ex) { throw new ParsingException('The data for phonenumber is not parsable', 0, $ex); } $data['phonenumber'] = $phonenumber; } return $data; } public function getAdvancedSearchTitle(): string { return 'Search within persons'; } public static function getAlias(): string { return self::NAME; } /** * (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 renderResult(array $terms, $start = 0, $limit = 50, array $options = [], $format = 'html') { $terms = $this->findAdditionnalInDefault($terms); $total = $this->count($terms); $paginator = $this->paginatorFactory->create($total); if ('html' === $format) { return $this->templating->render( '@ChillPerson/Person/list_with_period.html.twig', [ 'persons' => $this->search($terms, $start, $limit, $options), 'pattern' => $this->recomposePattern( $terms, \array_filter(self::POSSIBLE_KEYS, static fn ($item) => '_default' !== $item), $terms['_domain'] ), 'total' => $total, 'start' => $start, 'search_name' => self::NAME, 'preview' => $options[SearchInterface::SEARCH_PREVIEW_OPTION], 'paginator' => $paginator, ] ); } // format is "json" return [ 'results' => $this->search($terms, $start, $limit, \array_merge($options, ['simplify' => true])), 'pagination' => [ 'more' => $paginator->hasNextPage(), ], ]; } public function supports($domain, $format) { return 'person' === $domain; } protected function count(array $terms): int { [ '_default' => $default, 'firstname' => $firstname, 'lastname' => $lastname, 'birthdate' => $birthdate, 'birthdate-before' => $birthdateBefore, 'birthdate-after' => $birthdateAfter, 'gender' => $gender, 'nationality' => $countryCode, 'phonenumber' => $phonenumber, 'city' => $city, ] = $terms + \array_fill_keys(self::POSSIBLE_KEYS, null); if (null !== $birthdate) { try { $birthdate = new \DateTime($birthdate); } catch (\Exception $e) { throw new ParsingException('The date is not parsable', 0, $e); } } if (null !== $birthdateBefore) { try { $birthdateBefore = new \DateTime($birthdateBefore); } catch (\Exception $e) { throw new ParsingException('The date is not parsable', 0, $e); } } if (null !== $birthdateAfter) { try { $birthdateAfter = new \DateTime($birthdateAfter); } 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, $phonenumber, $city ); } /** * @return Person[] */ protected function search(array $terms, int $start, int $limit, array $options = []) { [ '_default' => $default, 'firstname' => $firstname, 'lastname' => $lastname, 'birthdate' => $birthdate, 'birthdate-before' => $birthdateBefore, 'birthdate-after' => $birthdateAfter, 'gender' => $gender, 'nationality' => $countryCode, 'phonenumber' => $phonenumber, 'city' => $city, ] = $terms + \array_fill_keys(self::POSSIBLE_KEYS, null); if (null !== $birthdate) { try { $birthdate = new \DateTime($birthdate); } catch (\Exception $e) { throw new ParsingException('The date is not parsable', 0, $e); } } if (null !== $birthdateBefore) { try { $birthdateBefore = new \DateTime($birthdateBefore); } catch (\Exception $e) { throw new ParsingException('The date is not parsable', 0, $e); } } if (null !== $birthdateAfter) { try { $birthdateAfter = new \DateTime($birthdateAfter); } 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, $phonenumber, $city ); } private function findAdditionnalInDefault(array $terms): array { // chaining some extractor $datesResults = $this->extractDateFromPattern->extractDates($terms['_default']); $phoneResults = $this->extractPhonenumberFromPattern->extractPhonenumber($datesResults->getFilteredSubject()); $terms['_default'] = $phoneResults->getFilteredSubject(); if ( $datesResults->hasResult() && (!\array_key_exists('birthdate', $terms) || null !== $terms['birthdate']) ) { $terms['birthdate'] = $datesResults->getFound()[0]->format('Y-m-d'); } if ( $phoneResults->hasResult() && (!\array_key_exists('phonenumber', $terms) || null !== $terms['phonenumber']) ) { $terms['phonenumber'] = $phoneResults->getFound()[0]; } return $terms; } }