For a certain view, if it returns only one result, you wish to redirect the users to the single result URL?
This is possible by choosing the right hook "hook_views_post_render()", here you go (example implementation):
/**
* Implements hook_views_post_render().
*/
function MY_MODULE_views_post_render(\Drupal\views\ViewExecutable $view, &$output, \Drupal\views\Plugin\views\cache\CachePluginBase $cache) {
// Redirect to the views result, if there's only one.
// Only redirect on view id "products_faceted_search" and do NOT redirect if an exposed filter is set.:
if (in_array($view->id(), ['products_faceted_search']) && $view->total_rows == 1 && count($view->getExposedInput()) == 0) {
// We have to kill the page cache here otherwise this hook will not be called again on the second request.
\Drupal::service('page_cache_kill_switch')->trigger();
// We also have to clear the views cache to make this work at 2nd call:
$cache->cacheFlush();
if (!empty($view->result[0]->_entity)) {
$entity = $view->result[0]->_entity;
$language = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT);
$entity = $entity->getTranslation($language->getId());
$url = $entity->toUrl();
// Display a notice for administrators. Do not redirect.
if (count(array_intersect(['administrator','manager'], \Drupal::currentUser()->getRoles()))>0) {
\Drupal::messenger()
->addMessage(new TranslatableMarkup('This page is set to redirect to another URL (@url), but you have permission to see this page and will not be automatically redirected (via MY_MODULE_views_post_render).', ['@url' => $url->toString()]), 'status');
}
else {
// Do not redirect cron
// From https://git.drupalcode.org/project/field_redirection/commit/42b8891
// Don't execute if running via the CLI, e.g. Drush.
// Don't do anything if the current page is running the normal cron script;
// this also supports Elysia Cron.
$current_url = Url::fromRoute('<current>');
$current_path = $current_url->toString();
if (mb_strpos($current_path, '/cron') === 0) {
return;
} elseif ($current_path === '/admin/reports/status/run-cron') {
return;
} elseif (defined('MAINTENANCE_MODE')) {
return;
} else {
// Redirect regular users.
$response = new \Symfony\Component\HttpFoundation\RedirectResponse($url->toString());
$request = \Drupal::request();
// Save the session so things like messages get saved.
$request->getSession()->save();
$response->prepare($request);
// Make sure to trigger kernel events.
\Drupal::service('kernel')->terminate($request, $response);
$response->send();
}
}
} else {
throw new Exception('No result returned');
}
}
}
Note: This doesn't yet seem to work with views caching enabled, help appreciated :)
Even better would be to have this as module with a view setting or something like that, but that's a different story ... :)