Сначала я сделал плагинчик для того, чтобы можно было ресурсы переносить из раздела в раздел безболезненно и добавлять дочерние ресурсы (у контейнеров префикс URL меняется).
Теперь решил поднатужится и сделать максимально автоматизированную систему, которая позволит не только переносить ресурсы, но и менять им псевдонимы, не беспокоясь о редиректах.
Схема и проблемы (теория)
Изначально идеей было сохранять все варианты uri ресурса в отдельную таблицу. Однако пришлось бы на каждом новом сайте создавать таблицу, прописывать схему и пр. Я же хотел, чтобы на каждый новый сайт этот функционал добавлялся как можно проще.
Думаю, как будет время, соберу пакет, который будет сам создавать таблицу и пр.
Пока решил сделать по-другому: при изменении псевдонима создается ресурс, которому устанавливается старый uri.
Тут появляется проблема — если мы захотим поменять псевдоним обратно, вылезет ошибка, так как такой uri уже используется. Я пытался отловить этот момент, чтобы перезаписывать uri второстепенного ресурса. Но здесь видно, что в момент выполнения функции checkFriendlyAlias не вызывается никаких событий (и до этой функции тоже).
Поэтому было решено отключить «проверку на дублирование uri во всех контекстах» (в настройках системы) и создать для второстепенных ресурсов свой контекст.
Сам код и комментарии
И так, сначала по событию OnBeforeDocFormSave мы записываем в сессию текущий uri:
<?php
switch ($modx->event->name) {
case "OnBeforeDocFormSave":
if ($mode == 'upd') {
$uri = $resource->uri;
$_SESSION[$id."-uri"] = $uri;
}
break;
}После сохранения (событие OnDocFormSave) мы смотрим, изменился ли uri ресурса и если да, то создаем второстепенный ресурс в отдельном контексте:<?php
switch ($modx->event->name) {
case "OnDocFormSave":
if ($mode == 'upd') {
if ($old_uri == $uri) {break;}
else {
$context = "redirector"; // наш контекст
$uri = $resource->uri; // текущий uri
$old_uri = $_SESSION[$id."-uri"]; // uri, записанный в сессию
// Чтобы дерево ресурсов не разрасталось и админка не тормозила
// ставим show_in_tree => 0
$redirectorParams = array(
"show_in_tree" => 0
, "published" => 1
, "uri_override" => 1
, "context_key" => $context
);
$redirectorParams["uri"] = $old_uri; // Записываем старый uri
$redirectorParams["longtitle"] = $id; // Указываем, куда редиректить
$response = $modx->runProcessor('resource/create', $redirectorParams);
$redirectorId = $response->response['object']['id'];
$redirector = $modx->getObject("modResource", $redirectorId);
$redirector->set("pagetitle", $redirectorId);
$redirector->set("alias", $redirectorId);
$redirector->save();
break;
}
}
}Если мы сначала поменяли псевдоним, а потом решили вернуть его обратно, просто меняем uri ресурсов местами:<?php
if ($redirector = $modx->getObject("modResource",
$redirectorParams)) {
$redirector->set("uri",$old_uri);
$redirector->save();
break;
}Ну и правила для редиректов (события OnPageNotFound):<?php
case "OnPageNotFound":
$url = $_SERVER['REQUEST_URI'];
$uri = str_replace($modx->getOption("site_url"),"",$url);
if (substr($uri, 0, 1) == "/") $uri = substr($uri, 1);
$redirector = $modx->getObject('modResource', array("uri" => $uri));
if ($redirector) {
$modx->sendRedirect($modx->makeUrl($redirector->get('longtitle')),
array('responseCode' => 'HTTP/1.1 301 Moved Permanently'));
}
// Если ресурс не редактировался (например, его просто перетащили в дереве)
// (это тот самый маленький плагин из прошлой статьи)
if (substr($url, -5) == ".html") $url = substr($url, 0, -5);
if (substr($url, -1) == "/") $url = substr($url, 0, -1);
$url = str_replace($modx->getOption("site_url"),"",$url);
$url_array = explode('/', $url);
$alias = array_pop($url_array);
$res = $modx->getObject('modResource', array("alias" => $alias));
if ($res) $modx->sendRedirect($modx->makeUrl($res->get('id')),
array('responseCode' => 'HTTP/1.1 301 Moved Permanently'));
break;
}Инструкция, как запустить на своем сайте
- Выключаем в настройках системы global_duplicate_uri_check («Проверять на дублирование URI во всех контекстах»)
- Создаем контекст redirector
- Создаем плагин и включаем в нем события OnBeforeDocFormSave, OnDocFormSave и OnPageNotFound
- Вставляем в плагин код по ссылке.
G+ Оригинал статьи community.modx-cms.ru/blog/tips_and_tricks/9559.html
Объектная
0 комментариев