Facet Views 404 в Drupal 9

Сьогодні ми розглянемо невеликий модуль для Drupal 9, який допоміг частково вирішити наступну проблему:

Є сторінка фасетного пошуку за адресою website.com/catalog, також на сайті є записи типу товару, які мають URL-адресу, таку як website.com/catalog/productname23. Як ми можемо побачити, у них є спільна частина, тому коли ми видаляємо товар і переходимо до нього, ми маємо сторінку фасетного пошуку зі статусом 200 замість сторінки 404.

Коли я шукав рішення цієї проблеми, я знайшов модуль Views404, але, на жаль, він підтримується лише для Drupal версії 7, тому я вирішив швидко щось створити, щоб це працювало.

Загальний принцип роботи нашого модуля буде таким: спочатку ми перевіряємо, чи ми знаходимось на сторінці з URL, який збігається з нашим. Далі ми перевіряємо, чи це сторінка вузла, і якщо ми видалили наш товар, то ця перевірка повинна працювати успішно. Після цього ми отримуємо список всіх фасетних полів продуктів, щоб отримати імена псевдонімів URL для фасет. Після цього, знаючи, які у нас є псевдоніми фасет, ми перевіряємо, чи вони є в нашому URL. Якщо немає - перенаправляємо на сторінку 404.

Спочатку створюємо файл .info.yml

name: Views404 v9
description: 'Fix 404 for Views in Drupal 9'
type: module
version: 1.0
core_version_requirement: ^9 || ^10
package: DARTHARTH
dependencies:
  - drupal:views

після цього файл  .module

<?php

use Drupal\Core\Routing\RouteMatchInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Database\Database;

function getFacetAliases() {
  $connection = Database::getConnection();
  $like = $connection->escapeLike('search_api_db_facet_field_') . '%';
  $query = $connection->query("SHOW TABLE STATUS LIKE :like", [':like' => $like]);
  $tables = $query->fetchAllKeyed(0, 0);

  $facet_aliases = [];
  foreach ($tables as $table_name => $data) {
      if ($table_name !== 'search_api_db_facet_field_type') {
          $alias = str_replace('search_api_db_facet_field_', '', $table_name);
          $facet_aliases[] = $alias;
      }
  }

  return $facet_aliases;
}

/**
 * Implements hook_preprocess_page().
 */
function darth_views404_preprocess_page(&$variables) {
    $current_path = \Drupal::service('path.current')->getPath();
    $route_match = \Drupal::routeMatch();

    if (strpos($current_path, '/catalog/') !== FALSE) {
        if (isNodePage($route_match)) {
            return;
        }

        $facet_aliases = getFacetAliases();

        $path_parts = explode('/', trim($current_path, '/'));

        $facet_in_url = false;
        foreach ($facet_aliases as $alias) {
            if (in_array($alias, $path_parts)) {
                $facet_in_url = true;
                break;
            }
        }

        if (!$facet_in_url) {
          redirectTo404();
        }
    }
}

/**
 * 
 *
 * @param RouteMatchInterface $route_match
 * @return bool
 */
function isNodePage(RouteMatchInterface $route_match) {
    if ($route_match->getRouteName() == 'entity.node.canonical') {
        return TRUE;
    }

    return FALSE;
}

/**
 * 
 */
function redirectTo404() {
    $response = new RedirectResponse('/404', 301);
    $response->send();
    exit;
}

Link to GitHub

Простий текст

  • Не дозволено жодних HTML теґів.
  • Рядки й абзаци переносяться автоматично.
  • Адреси вебсторінок та адреси електронної пошти автоматично перетворюються у посилання.
Код мови коментаря.