Изменить адрес ноды при обращении к ней с определенной страницы

Главные вкладки

Аватар пользователя seoyuzer seoyuzer 2 сентября 2018 в 12:53

Здравствуйте!
На сайте есть страница "Архив (Views)" туда попадают ноды которые старше двух часов от текущего времени. Нужно чтобы при обращении к ноде через страницу Архив (Views) менялся ее url до вывода. Какой hook для этого подойдет? Спасибо!

Комментарии

Аватар пользователя seoyuzer seoyuzer 2 сентября 2018 в 13:06

Есть страница представления, на этой странице выводится список нод одного типа, при переходе в ноду именно с этой страницы, должен меняться url ноды, допустим url нод по умолчанию "/content/title.html" а при переходе со страницы представления менялся на "/arhiv/title.html"

Аватар пользователя Orion76 Orion76 2 сентября 2018 в 22:39
1

хм.. какой-то, мягко говоря, не стандартный подход к решению задачи..
может модуль VBO лучше подойдет? ( https://www.drupal.org/project/views_bulk_operations )
Он позволяет сделать вьюс, для выборки материалов..
И совершать с выбранными материалами "пакетные" операции.
Например изменить значение алиаса(url) материала..

Аватар пользователя seoyuzer seoyuzer 2 сентября 2018 в 23:19

Спасибо за подсказку! Но это не пойдет. У меня на сайте есть тип материала "Мероприятия" на главной странице через views выводятся ближайшие мероприятия которые только будут , если мероприятие уже прошло то эти мероприятия выводятся на странице архив, эта страница тоже сделанна через представление. Мне нужно чтобы к нодам которые уже относятся к архиву присвоился класс в body, чтобы через css убрать не нужные поля. Сейчас как бы в body есть классы, но так как эти ноды создаются через один тип материала и если я через эти классы скрою допустим кнопку заказать, то она скроется в ближайших мероприятиях тоже.

Нужно получается какое то условие, если мероприятие (нода) уже прошло и выводится на странице Архив, то этой ноде нужно присвоить класс допустим "arhiv", т.е именно когда переходишь в ноду со страницы архив.

Аватар пользователя seoyuzer seoyuzer 2 сентября 2018 в 23:32

Я просто помню на каком то проекте подобное, только это был d7, там то же была страница представления, на ней выводился список нод, при вызове ноды через эту страницу у ноды переписывался url и присваивался класс, а вот какой хук за это отвечал не помню.

Аватар пользователя adano adano 3 сентября 2018 в 6:08

Вьюха тут вообще не причем.
Истинным решением будет только следующее:
Проверка нод по крону -> по условию, изменение алиаса -> node_save (aka D7)

Думаю, через какой-нибудь scheduler и rules можно накликать.

seoyuzer wrote:

при вызове ноды через эту страницу у ноды переписывался url и присваивался класс

presave (node_save) скорее всего, через node_preview или препроцесс + global redirect.

P.S. Да и по SEO, ваше решение "нехорошее", т.к. редиректы придется прикручивать с /content/title.html на /arhiv/title.html.

Аватар пользователя OldWarrior OldWarrior 3 сентября 2018 в 8:17

seoyuzer wrote:

...url нод по умолчанию "/content/title.html" а при переходе со страницы представления менялся на "/arhiv/title.html"...

seoyuzer wrote:

...Какой hook для этого подойдет?...

Всё и проще и сложнее, чем кажется. Сложнее в том плане, что только каким-то одним определённым хуком API дело не ограничится.

1. Пишете роут, обрабатывающий внутренний путь /arhiv/{node_alias}. Таким образом, на вход роута будет поступать только часть синонима ноды, содержащая (насколько я понял из задачи) транслит заголовка материала.

2. В роуте пишете EntityQuery с условиями что-то вроде (только для примера):

  • type = 'ваш_тип_ноды'
  • status = 1 (т.е. published)
  • created = time() - 3600 * 2 (т.е. 2 часа с момента публикации)
  • path =LIKE '%/' . {node_alias} (искомый синоним)

3. Если EntityQuery вернул NID в результате (т.е. нашёл хоть что-то, соответствующее условиям), то $node = Node::load(NID)

4. return $node;

5. Всё. При переходе с представления на /arhiv/title.html будет грузиться и рендериться нода, содержащая в синониме подстроку title.html (если будет найдена таковая).

Вместо пп.2-3 можно и как-то так:

<?php
use \Drupal\node\Entity\Node;

$path = \Drupal::service('path.alias_manager')->getPathByAlias('content/' $node_alias);
if (
preg_match('/node\/(\d+)/'$path$matches)) {
  
$nid $matches[1];
  
$node Node::load($nid);
}
?>
Аватар пользователя adano adano 3 сентября 2018 в 9:00

ТС, скорее всего, preprocess_node ищет, раз речь идет о классе

seoyuzer wrote:

этой ноде нужно присвоить класс допустим "arhiv", т.е именно когда переходишь в ноду со страницы архив.

Аватар пользователя OldWarrior OldWarrior 3 сентября 2018 в 9:13

Тогда уж скорее hook_preprocess_html(), если в body

Да и речь же не только о классе, но и об урле (второе, как я понял, в приоритете).
Кстати, класс можно установить и из функции роута. Или даже программно вообще исключить поля из вывода ноды.

Аватар пользователя Orion76 Orion76 3 сентября 2018 в 17:57

что-то всего столько нагородили-)

Я правильно понял, что всего-навсего надо материалы старше 2 часов :
1.Не показывать в одной вьюхе.
2.Показывать в другой.
3.Странице просмотра материала установить нужный html-класс?

Аватар пользователя seoyuzer seoyuzer 3 сентября 2018 в 18:36

1.Не показывать в одной вьюхе.
2.Показывать в другой.

Это уже есть!

3.Странице просмотра материала установить нужный html-класс?

Да, нужно внутри самой ноды которая старше 2 часов от текущего времени, присвоить класс, например "arhiv" для того чтобы в этой ноде скрыть через css кнопку "Купить" так как мероприятие уже не актуально.

Сами ноды сортируются через поле "Дата"

Получается что нужна проверка через hook по полю дата.

Аватар пользователя Orion76 Orion76 3 сентября 2018 в 19:01

скрывать-показывать поля лучше при помощи разных режимов отображения материалов (view mode)

а режим отображения устанавливается как-то так:
https://drupal.stackexchange.com/questions/193319/how-to-change-display-...

(код не проверен, возможно придется отладить)

<?php
/**
 * Implements hook_entity_view_mode_alter().
 */
function MYMODULE_entity_view_mode_alter(&$view_modeDrupal\Core\Entity\EntityInterface $entity$context) {

$time_limit=time()- 260*60;

  if (

$entity->get('created')->value $time_limit && $view_mode == 'full') {
    
$view_mode 'teaser';
  }
}
?>
Аватар пользователя seoyuzer seoyuzer 3 сентября 2018 в 21:18

Спасибо! Походу то что нужно, код попробовал, ноне работает, буду разбираться) Видать условие не подхватывает.

Аватар пользователя Orion76 Orion76 4 сентября 2018 в 5:23

Создайте для материала нужные Режимы отображения (view mode) и поправьте в коде их "машинные" наименования (переменная $view_mode)

Аватар пользователя seoyuzer seoyuzer 4 сентября 2018 в 10:38

Сам hook срабатывает если я его вставляю так:

<?phpfunction custom_display_entity_view_mode_alter(&$view_mode, Drupal\Core\Entity\EntityInterface $entity, $context) {

  // For nodes, change the view mode when it is teaser.
  if ($entity
    ->getEntityTypeId() == 'node' && $view_mode == 'full') {
    $view_mode = 'ar';
  }
}
?>

Но если вставляю ваш код сайт ругается. Я как понимаю нужно чтобы модуль подключался к бд, потому что дата и время в мероприятиях указывается в ручную через поле "Дата"

Uncaught PHP Exception InvalidArgumentException: "Field created is unknown." at /localhost/core/lib/Drupal/Core/Entity/ContentEntityBase.php line 580, referer: http://localhost/meropriyatiya/tri-kota-poiski-sokrovisch
Аватар пользователя adano adano 4 сентября 2018 в 10:53

Уважаемый, не костыльте подобными способами, тем более, что код нелогичный. Лучше пересмотрите свою задачу прагматично, со стороны юзера.

Аватар пользователя gun_dose gun_dose 4 сентября 2018 в 10:57

Надо перебить роут ноды кастомным контроллером и там выводить, как надо. Но вот насчёт смены урла - хз. С точки зрения поисковой оптимизации это неудачное решение. Да и с логической тоже. Я бы урл оставил постоянным, а менял бы только хлебные крошки.