<?php namespace Drupal\uw_ct_service\Form; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; use Drupal\Core\Entity\EntityTypeManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Path\CurrentPathStack; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\path_alias\AliasManager; use Drupal\Core\Messenger\MessengerInterface; /** * Class ServiceSearchForm. * * Form for searching services. */ class ServiceSearchForm extends FormBase { /** * Entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * The variable for current path. * * @var \Drupal\Core\Path\CurrentPathStack */ protected $currentPath; /** * The variable for route match. * * @var \Drupal\Core\Routing\RouteMatchInterface */ protected $routeMatch; /** * The variable for alias manager. * * @var \Drupal\path_alias\AliasManager */ protected $aliasManager; /** * The Messenger service. * * @var \Drupal\Core\Messenger\MessengerInterface */ protected $messenger; /** * Class constructor. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager * The entity type manager. * @param \Drupal\Core\Path\CurrentPathStack $currentPath * The currentPath. * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch * The routeMatch. * @param \Drupal\path_alias\AliasManager $aliasManager * The aliasManager. * @param Drupal\Core\Messenger\MessengerInterface $messenger * The Drupal messenger. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ public function __construct(EntityTypeManagerInterface $entityTypeManager, CurrentPathStack $currentPath, RouteMatchInterface $routeMatch, AliasManager $aliasManager, MessengerInterface $messenger) { $this->entityTypeManager = $entityTypeManager; $this->currentPath = $currentPath; $this->routeMatch = $routeMatch; $this->aliasManager = $aliasManager; $this->messenger = $messenger; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { // Instantiates this form class. return new static( $container->get('entity_type.manager'), $container->get('path.current'), $container->get('current_route_match'), $container->get('path_alias.manager'), $container->get('messenger') ); } /** * Returns a unique string identifying the form. * * The returned ID should be a unique string that can be a valid PHP function * name, since it's used in hook implementation names such as * hook_form_FORM_ID_alter(). * * @return string * The unique string identifying the form. */ public function getFormId(): string { return 'service_search_form'; } /** * Form constructor. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * @param int $tid * The term id. * @param string $description * The description for the input element. * @param bool $use_placeholder * A flag to use a placeholder. * @param string $placeholder * The placeholder string. * * @return array * The form structure. */ public function buildForm(array $form, FormStateInterface $form_state, int $tid = NULL, string $description = NULL, bool $use_placeholder = TRUE, string $placeholder = NULL): array { // Get the current route. $route = $this->routeMatch->getRouteName(); // If the route is the all services page, set placeholder to // search with all services. if ($route == 'view.uw_view_services.services_page') { // Set the placeholder for all services. $placeholder = 'Search within all services'; } // If this is a service term page, then set placeholder to // search within <service_name>. elseif ($route == 'entity.taxonomy_term.canonical') { // Load the term. $term = $this->routeMatch->getParameter('taxonomy_term'); // Ensure that we are going to use a placeholder then set it. if ($use_placeholder && !$placeholder) { // Set the placeholder for specific catalog. $placeholder = 'Search within ' . $term->label(); } } // If this is a node page, we need to set the tid in the form // state so that it can be used later to load name and path. elseif ($route == 'entity.node.canonical') { // If we are to use a placeholder, set it. if ($use_placeholder && !$placeholder) { // Load the term in from the tid. $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid); // Set the placeholder. $placeholder = 'Search within ' . $term->label(); } // Set the tid in the form state. $form_state->set('tid', $tid); } // If this is any other route mainly: // /services/<service_name>/<new,category,audience, etc...>, // Then we have to get the tid from the URL, but ensure that // we are not in layout builder or error will be thrown. else { // Ensure that we are not on a layout builder page. // We do not need the tid on a layout builder page, because // this form can never get submitted on a layout builder page. if (strpos($route, 'layout_builder') !== 0) { // Get the current path. $url = $this->currentPath->getPath(); // Break the path into parts. $url = explode('/', $url); // The tid will always be the 4th element. $tid = $url[3] ?? NULL; // One last check to ensure that we have a tid. // If we do not have a tid, throw a Drupal error. if (is_numeric($tid)) { // If we are to use a placeholder, set it. if ($use_placeholder && !$placeholder) { // Load the term in from the tid. $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid); // Set the placeholder. $placeholder = 'Search within ' . $term->label(); } // Set the tid into the form state, so it can be used // in the form submit. $form_state->set('tid', $url[3]); } } } // The search input. $form['search_input'] = [ '#type' => 'textfield', '#placeholder' => $use_placeholder ? $placeholder : NULL, '#description' => $description ?? NULL, '#required' => TRUE, ]; // Add a submit button that handles the submission of the form. $form['submit'] = [ '#type' => 'submit', '#value' => '', '#attributes' => ['aria-label' => 'search'], ]; return $form; } /** * Form submission handler. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. */ public function submitForm(array &$form, FormStateInterface $form_state) { // Get the values of the form state. $values = $form_state->getValues(); // Get the tid from form state, if there is not one // it will be NULL. $tid = $form_state->get('tid'); // This is an internal URL. $url = 'internal:'; // If the tid is NULL, we are on a /catalogs page, so we // can just build the url from the current route. // If tid is not NULL, we have to determine if this is a // search all catalogs or specific and set things accordingly. if ($tid === NULL) { // Get the current route as the view for catalog // search will handle all and specific, based on URL. $url .= Url::fromRoute('<current>')->toString(); } else { // If the tid is 0, this is a search all catalogs, // so set the URL to the /services. // If not set the search to /services/<service_path>. if ($tid == 0) { $url .= '/services'; } else { $url .= $this->aliasManager->getAliasByPath('/taxonomy/term/' . $tid); } } // Add the search string. $url .= '/search?search-input=' . $values['search_input']; // Get a URL object. $url = Url::fromUri($url); // Set the form redirection URL. $form_state->setRedirectUrl($url); } }