class CustomSearchBlockForm in Custom Search 8
Builds the search form for the search block.
Hierarchy
- class \Drupal\Core\Form\FormBase implements ContainerInjectionInterface, FormInterface uses DependencySerializationTrait, LoggerChannelTrait, MessengerTrait, LinkGeneratorTrait, RedirectDestinationTrait, UrlGeneratorTrait, StringTranslationTrait
- class \Drupal\custom_search\Form\CustomSearchBlockForm
Expanded class hierarchy of CustomSearchBlockForm
File
- src/
Form/ CustomSearchBlockForm.php, line 21
Namespace
Drupal\custom_search\FormView source
class CustomSearchBlockForm extends FormBase {
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The search page repository.
*
* @var \Drupal\search\SearchPageRepositoryInterface
*/
protected $searchPageRepository;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The entity repository.
*
* @var \Drupal\Core\Entity\EntityRepositoryInterface
*/
protected $entityRepository;
/**
* Constructs a new SearchBlockForm.
*
* @param \Drupal\search\SearchPageRepositoryInterface $search_page_repository
* The search page repository.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The Module handler object.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* The entity repository.
*/
public function __construct(SearchPageRepositoryInterface $search_page_repository, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository) {
$this->searchPageRepository = $search_page_repository;
$this->moduleHandler = $module_handler;
$this->entityTypeManager = $entity_type_manager;
$this->entityRepository = $entity_repository;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container
->get('search.search_page_repository'), $container
->get('module_handler'), $container
->get('entity_type.manager'), $container
->get('entity.repository'));
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'custom_search_block_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = func_get_arg(2);
$form['#method'] = 'post';
// Popup.
$form['popup'] = [
'#type' => 'fieldset',
'#weight' => 1 + $config['search_box']['weight'],
'#attributes' => [
'class' => [
'custom_search-popup',
],
],
];
// Search box.
$form['keys'] = [
'#type' => 'search',
'#title' => Html::escape($config['search_box']['label']),
'#title_display' => $config['search_box']['label_visibility'] ? 'before' : 'invisible',
'#size' => $config['search_box']['size'],
'#maxlength' => $config['search_box']['max_length'],
'#default_value' => '',
'#placeholder' => [
'title' => Html::escape($config['search_box']['placeholder']),
],
'#attributes' => [
'title' => Html::escape($config['search_box']['title']),
'class' => [
'custom_search-keys',
],
],
'#weight' => $config['search_box']['weight'],
];
// Content.
$toptions = [];
$types = array_keys(array_filter($config['content']['types']));
if (count($types)) {
$names = node_type_get_names();
if (count($types) > 1 || $config['content']['any']['force']) {
$toptions['c-all'] = $config['content']['any']['text'];
}
foreach ($types as $type) {
$toptions['c-' . $type] = $names[$type];
}
}
$options = [];
// Other searches.
$others = !empty($config['content']['other']) ? array_keys(array_filter($config['content']['other'])) : [];
// If content types and other searches are combined, make an optgroup.
if (count($others) && count($toptions) && $config['content']['selector']['type'] == 'select') {
$search_page = $this->entityTypeManager
->getStorage('search_page')
->load($config['content']['page']);
$options[Html::escape($search_page
->label())] = $toptions;
}
else {
$options = $toptions;
}
if (count($others)) {
$other_pages = $this->entityTypeManager
->getStorage('search_page')
->loadMultiple($others);
foreach ($others as $other) {
$options['o-' . Html::escape($other_pages[$other]
->id())] = Html::escape($other_pages[$other]
->label());
}
}
if (count($options)) {
$selector_type = $config['content']['selector']['type'];
if ($selector_type == 'selectmultiple') {
$selector_type = 'select';
$multiple = TRUE;
}
else {
$multiple = FALSE;
}
$form['types'] = [
'#type' => $selector_type,
'#multiple' => $multiple,
'#title' => Html::escape($config['content']['selector']['label']),
'#title_display' => $config['content']['selector']['label_visibility'] ? 'before' : 'invisible',
'#options' => $options,
'#default_value' => $selector_type == 'checkboxes' ? [
'c-all',
] : 'c-all',
'#attributes' => [
'class' => [
'custom-search-selector',
'custom-search-types',
],
],
'#weight' => $config['content']['weight'],
'#validated' => TRUE,
];
// If there's only one type, hide the selector.
if (count($others) + count($types) == 1 && !$config['content']['any']['force']) {
$form['custom_search_types']['#type'] = 'hidden';
$form['custom_search_types']['#default_value'] = key(array_slice($options, count($options) - 1));
}
elseif ($config['content']['region'] == 'popup') {
$form['popup']['types'] = $form['types'];
unset($form['types']);
}
}
// Taxonomy.
$vocabularies = $this->entityTypeManager
->getStorage('taxonomy_vocabulary')
->loadMultiple();
if (count($config['taxonomy']) > 0) {
$taxonomy_term_storage = \Drupal::entityTypeManager()
->getStorage('taxonomy_term');
foreach ($vocabularies as $voc) {
$vid = $voc
->id();
if (empty($config['taxonomy'][$vid]['type']) || $config['taxonomy'][$vid]['type'] == 'disabled') {
continue;
}
$options = [];
$options['c-all'] = $config['taxonomy'][$vid]['all_text'];
$vocabulary_depth = !$config['taxonomy'][$vid]['depth'] ? NULL : $config['taxonomy'][$vid]['depth'];
$terms = $taxonomy_term_storage
->loadTree($vid, 0, $vocabulary_depth, TRUE);
foreach ($terms as $term) {
$termName = Html::escape($this->entityRepository
->getTranslationFromContext($term)
->label());
$options['c-' . $term
->id()] = mb_substr($config['taxonomy'][$vid]['type'], 0, 6) == 'select' ? str_repeat('-', $term->depth) . ' ' . $termName : $termName;
}
$selector_type = $config['taxonomy'][$vid]['type'];
if ($selector_type == 'selectmultiple') {
$selector_type = 'select';
$multiple = TRUE;
}
else {
$multiple = FALSE;
}
$form['vocabulary_' . $vid] = [
'#type' => $selector_type,
'#multiple' => $multiple,
'#title' => Html::escape($config['taxonomy'][$vid]['label']),
'#title_display' => $config['taxonomy'][$vid]['label_visibility'] ? 'before' : 'invisible',
'#options' => $options,
'#default_value' => $selector_type == 'checkboxes' ? [
'c-all',
] : 'c-all',
'#attributes' => [
'class' => [
'custom-search-selector',
'custom-search-vocabulary',
],
],
'#weight' => $config['taxonomy'][$vid]['weight'],
];
if ($config['taxonomy'][$vid]['region'] == 'popup') {
$form['popup']['vocabulary_' . $vid] = $form['vocabulary_' . $vid];
unset($form['vocabulary_' . $vid]);
}
}
}
// Languages.
$options = [];
$languages = array_keys(array_filter($config['languages']['languages']));
if (count($languages)) {
if (count($languages) > 1 || $config['languages']['any']['force']) {
$options['c-all'] = $config['languages']['any']['text'];
}
$current_language = \Drupal::languageManager()
->getCurrentLanguage();
$current_language_id = $current_language
->getId();
foreach ($languages as $language) {
switch ($language) {
case 'current':
$options['c-' . $language] = t('- Current language (@current) -', [
'@current' => $current_language
->getName(),
]);
break;
case Language::LANGCODE_NOT_SPECIFIED:
$options['c-' . $language] = t('- Not specified -');
break;
case Language::LANGCODE_NOT_APPLICABLE:
$options['c-' . $language] = t('- Not applicable -');
break;
default:
if ($language != $current_language_id || $language != $current_language_id && !array_key_exists('c-' . $language, $options)) {
$options['c-' . $language] = \Drupal::languageManager()
->getLanguageName($language);
}
}
}
}
if (count($options)) {
$selector_type = $config['languages']['selector']['type'];
if ($selector_type == 'selectmultiple') {
$selector_type = 'select';
$multiple = TRUE;
}
else {
$multiple = FALSE;
}
$form['languages'] = [
'#type' => $selector_type,
'#multiple' => $multiple,
'#title' => Html::escape($config['languages']['selector']['label']),
'#title_display' => $config['languages']['selector']['label_visibility'] ? 'before' : 'invisible',
'#options' => $options,
'#default_value' => $selector_type == 'checkboxes' ? [
'c-all',
] : 'c-all',
'#attributes' => [
'class' => [
'custom-search-selector',
'custom-search-language',
],
],
'#weight' => $config['languages']['weight'],
'#validated' => TRUE,
];
// If there's only one type, hide the selector.
if (count($languages) == 1 && !$config['languages']['any']['force']) {
$form['languages']['#type'] = 'hidden';
$form['languages']['#default_value'] = key(array_slice($options, count($options) - 1));
}
elseif ($config['languages']['region'] == 'popup') {
$form['popup']['languages'] = $form['languages'];
unset($form['languages']);
}
}
// Custom Paths.
$paths = $config['paths']['list'];
if ($paths != '') {
$options = [];
$lines = explode("\n", $paths);
foreach ($lines as $line) {
$temp = explode('|', $line);
$options[$temp[0]] = count($temp) >= 2 ? t($temp[1]) : '';
}
if (count($options) == 1) {
$form['paths'] = [
'#type' => 'hidden',
'#default_value' => key($options),
];
}
else {
$form['paths'] = [
'#type' => $config['paths']['selector']['type'],
'#title' => Html::escape($config['paths']['selector']['label']),
'#title_display' => $config['paths']['selector']['label_visibility'] ? 'before' : 'invisible',
'#options' => $options,
'#default_value' => key($options),
'#weight' => $config['paths']['weight'],
];
if ($config['paths']['region'] == 'popup') {
$form['popup']['paths'] = $form['paths'];
unset($form['paths']);
}
}
}
// Criteria.
$criteria = [
'or',
'phrase',
'negative',
];
foreach ($criteria as $c) {
if ($config['criteria'][$c]['display']) {
$form['criteria_' . $c] = [
'#type' => 'textfield',
'#title' => Html::escape($config['criteria'][$c]['label']),
'#size' => 15,
'#maxlength' => 255,
'#weight' => $config['criteria'][$c]['weight'],
];
if ($config['criteria'][$c]['region'] == 'popup') {
$form['popup']['criteria_' . $c] = $form['criteria_' . $c];
unset($form['criteria_' . $c]);
}
}
}
// Actions.
$form['actions'] = [
'#type' => 'actions',
];
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => Html::escape($config['submit']['text']),
// Prevent op from showing up in the query string.
'#name' => '',
'#weight' => $config['submit']['weight'],
];
if ($config['submit']['image_path'] != '') {
$form['actions']['submit']['#type'] = 'image_button';
$form['actions']['submit']['#src'] = $config['submit']['image_path'];
$form['actions']['submit']['#attributes'] = [
'alt' => Html::escape($config['submit']['text']),
'class' => [
'custom-search-button',
],
];
unset($form['actions']['submit']['#value']);
}
elseif ($form['actions']['submit']['#value'] == '') {
$form['actions']['submit']['#attributes'] = [
'style' => 'display:none;',
];
}
// If nothing has been added to the popup, don't output any markup.
if (!count(Element::children($form['popup']))) {
unset($form['popup']);
}
// Add attributes.
$form['#attributes']['role'] = 'search';
// Passes the config for later use.
$form_state
->set('config', $config);
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$config = $form_state
->get('config');
$filters = [];
// Keywords.
$keys = trim($form_state
->getValue('keys'));
// Filter Types.
$types = $form_state
->hasValue('types') ? $form_state
->getValue('types') : [];
if (!is_array($types)) {
$types = [
$types,
];
}
// Check if we're using another search (ie. Users).
$first_type = current($types);
if (substr($first_type, 0, 2) == 'o-') {
$search_page_id = substr($first_type, 2);
$search_pages = $this->entityTypeManager
->getStorage('search_page')
->loadMultiple([
$search_page_id,
]);
if (!empty($search_pages)) {
$route = 'search.view_' . $search_page_id;
}
}
else {
// Build route.
$route = 'search.view_' . $config['content']['page'];
// Types filters.
$types = array_map(function ($val) {
return $this
->filterKeys($val);
}, array_filter($types));
$excluded = array_map(function ($val) {
return $this
->filterKeys($val);
}, array_filter($config['content']['excluded']));
if (count($types)) {
if (in_array('all', $types)) {
// If - Any - is set to restrict the search, grab the content types.
if ($config['content']['any']['restricts']) {
$types = array_keys(array_filter($config['content']['types']));
}
// If exclusion has to be made, specify all the other types.
if (!empty($excluded)) {
$types = array_keys(node_type_get_names());
}
$types = array_diff($types, $excluded);
if (!in_array('all', $types)) {
foreach ($types as $type) {
$filters[] = 'type:' . $type;
}
}
}
else {
$types = array_diff($types, $excluded);
foreach ($types as $type) {
$filters[] = 'type:' . $type;
}
}
}
elseif (!empty($excluded)) {
$types = array_diff(array_keys(node_type_get_names()), $excluded);
foreach ($types as $type) {
$filters[] = 'type:' . $type;
}
}
// Taxonomy filters.
if ($this->moduleHandler
->moduleExists('taxonomy')) {
$terms = [];
$vocabularies = $this->entityTypeManager
->getStorage('taxonomy_vocabulary')
->loadMultiple();
foreach ($vocabularies as $voc) {
$vid = $voc
->id();
if ($form_state
->hasValue('vocabulary_' . $vid)) {
$vterms = $form_state
->getValue('vocabulary_' . $vid);
if (!is_array($vterms)) {
$vterms = [
$vterms,
];
}
$terms = array_merge($terms, $vterms);
}
}
// Uses array_values() to filter here to get numerical index, so we can
// splice the array later if needed (see line below the array_map()).
$terms = array_map(function ($val) {
return $this
->filterKeys($val);
}, array_values(array_filter($terms)));
// If one or more -Any- is selected, delete them.
while (($index = array_search('all', $terms)) !== FALSE) {
array_splice($terms, $index, 1);
}
if (count($terms)) {
foreach ($terms as $term) {
$filters[] = 'term:' . $term;
}
}
}
// Criteria filters.
if ($form_state
->hasValue('criteria_or') && trim($form_state
->getValue('criteria_or')) != '') {
$keys .= ' ' . str_replace(' ', ' OR ', trim($form_state
->getValue('criteria_or')));
}
if ($form_state
->hasValue('criteria_negative') && trim($form_state
->getValue('criteria_negative')) != '') {
$keys .= ' -' . str_replace(' ', ' -', trim($form_state
->getValue('criteria_negative')));
}
if ($form_state
->hasValue('criteria_phrase') && trim($form_state
->getValue('criteria_phrase')) != '') {
$keys .= ' "' . trim($form_state
->getValue('criteria_phrase')) . '"';
}
// Language filters.
$languages = $form_state
->hasValue('languages') ? $form_state
->getValue('languages') : [];
if (!is_array($languages)) {
$languages = [
$languages,
];
}
$languages = array_map(function ($val) {
return $this
->filterKeys($val);
}, array_filter($languages));
if (count($languages)) {
// If - Any - is selected and - Any - is set to restrict the search,
// grab the languages.
if (in_array('all', $languages) && $config['languages']['any']['restricts']) {
$languages = array_keys(array_filter($config['languages']['languages']));
}
// If it's not - Any -, search for that language.
if (!in_array('all', $languages)) {
foreach ($languages as $language) {
if ($language == 'current') {
$filters[] = 'language:' . \Drupal::languageManager()
->getCurrentLanguage()
->getId();
}
else {
$filters[] = 'language:' . $language;
}
}
}
}
}
// Build a custom path if needed.
if ($form_state
->hasValue('paths') && $form_state
->getValue('paths') != '') {
$route = $form_state
->getValue('paths');
$route = str_replace('[current_path]', \Drupal::service('path.current')
->getPath(), $route);
$route = str_replace('[key]', $keys, $route);
if (strpos($route, '[types]') !== FALSE) {
$route = str_replace('[types]', isset($types) && count($types) ? implode($config['paths']['separator'], $types) : '', $route);
}
if (strpos($route, '[terms]') !== FALSE) {
$route = str_replace('[terms]', isset($terms) && count($terms) ? implode($config['paths']['separator'], $terms) : '', $route);
}
// Check for a query string.
$query = [];
$route_query_position = strpos($route, '?');
if ($route_query_position !== FALSE) {
$query_tmp = substr($route, 1 + $route_query_position);
$query_tmp = str_replace('&', '&', $query_tmp);
$query_tmp = explode('&', $query_tmp);
foreach ($query_tmp as $param) {
$param_exploded = explode('=', $param);
$query[$param_exploded[0]] = $param_exploded[1];
}
$route = substr($route, 0, $route_query_position);
}
// If not an external URL, add the base url scheme.
if (substr($route, 0, 4) != 'http') {
$route = 'base://' . $route;
}
// Generate the final url.
$url = Url::fromUri($route, [
'query' => $query,
]);
// Redirect.
if ($url
->isExternal()) {
$form_state
->setResponse(new TrustedRedirectResponse($url
->toUriString(), 302));
}
else {
$form_state
->setRedirectUrl($url);
}
}
else {
$query['keys'] = $keys;
if (count($filters)) {
$query['f'] = $filters;
}
$form_state
->setRedirect($route, [], [
'query' => $query,
]);
}
}
/**
* Helper functions.
*/
private static function filterKeys($val) {
return strlen($val) > 2 && $val[1] == '-' ? mb_substr($val, 2) : $val;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
CustomSearchBlockForm:: |
protected | property | The entity repository. | |
CustomSearchBlockForm:: |
protected | property | The entity type manager. | |
CustomSearchBlockForm:: |
protected | property | The module handler. | |
CustomSearchBlockForm:: |
protected | property | The search page repository. | |
CustomSearchBlockForm:: |
public | function |
Form constructor. Overrides FormInterface:: |
|
CustomSearchBlockForm:: |
public static | function |
Instantiates a new instance of this class. Overrides FormBase:: |
|
CustomSearchBlockForm:: |
private static | function | Helper functions. | |
CustomSearchBlockForm:: |
public | function |
Returns a unique string identifying the form. Overrides FormInterface:: |
|
CustomSearchBlockForm:: |
public | function |
Form submission handler. Overrides FormInterface:: |
|
CustomSearchBlockForm:: |
public | function | Constructs a new SearchBlockForm. | |
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FormBase:: |
protected | property | The config factory. | 1 |
FormBase:: |
protected | property | The request stack. | 1 |
FormBase:: |
protected | property | The route match. | |
FormBase:: |
protected | function | Retrieves a configuration object. | |
FormBase:: |
protected | function | Gets the config factory for this form. | 1 |
FormBase:: |
private | function | Returns the service container. | |
FormBase:: |
protected | function | Gets the current user. | |
FormBase:: |
protected | function | Gets the request object. | |
FormBase:: |
protected | function | Gets the route match. | |
FormBase:: |
protected | function | Gets the logger for a specific channel. | |
FormBase:: |
protected | function |
Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait:: |
|
FormBase:: |
public | function | Resets the configuration factory. | |
FormBase:: |
public | function | Sets the config factory for this form. | |
FormBase:: |
public | function | Sets the request stack object to use. | |
FormBase:: |
public | function |
Form validation handler. Overrides FormInterface:: |
62 |
LinkGeneratorTrait:: |
protected | property | The link generator. | 1 |
LinkGeneratorTrait:: |
protected | function | Returns the link generator. | |
LinkGeneratorTrait:: |
protected | function | Renders a link to a route given a route name and its parameters. | |
LinkGeneratorTrait:: |
public | function | Sets the link generator service. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
UrlGeneratorTrait:: |
protected | property | The url generator. | |
UrlGeneratorTrait:: |
protected | function | Returns the URL generator service. | |
UrlGeneratorTrait:: |
public | function | Sets the URL generator service. | |
UrlGeneratorTrait:: |
protected | function | Generates a URL or path for a specific route based on the given parameters. |