Динамическое формирование pagetitle в плагине [EVO]

Всех приветствую!

Продолжаю разбираться с плагинами и modResource, интересует задача — динамически создать плагином pagetitle вида «Это страница $id», где $id — id документа.

Для упрощения предположил, что документ уже создан и сохранен, мы его редактируем. Гуглил — нахожу какие-то куски, целая картина не складывается.

Никак не могу добиться, чтобы работало.

— Нужно ли использовать modResource для этого?
— Или надо просто Яваскриптом вставить в поле pagetitle нужное значение?
— Какое событие использовать?

Если можно, дайте ссылку на какой-либо более-менее близкий пример плагина.

UPD: задачи стоит именно для админки, не для фронта.

25 комментариев

avatar
$e = $modx->Event;
switch ($e->name) {
    case 'OnLoadWebDocument' : case 'OnLoadWebPageCache' :
        $modx->documentObject['pagetitle'] = 'Это страница ' . $modx->documentIdentifier;
        break;
    default:
        break; 
}
avatar
Это если снаружи :)
avatar
Забыл написать, что это в админке нужно, при открытии документа менеджером на редактирование.

Вроде бы допетрил вот до чего. Событие для установки значений TV и полей ресурса подходит вроде бы OnDocFormPrerender.

В момент этих событий ID существующего документа уже известно и передано в плагин, его можно использовать как переменную $id.

Я устанавливаю ТВ, pagetitle и alias.

include_once(MODX_BASE_PATH.'assets/lib/MODxAPI/modResource.php');
$doc = new modResource($modx);

$e = & $modx->Event;
if ($e->name == "OnDocFormPrerender") {
	$pagetitle = 'Входная дверь-'.$id;
	$alias = 'vhodnaya-dver-'.$id;	
	$exterior_material_type = ... // тут вычисляется значение ТВ
	
	$doc->edit($id)->set('pagetitle',$pagetitle);
	$doc->edit($id)->set('exterior_material_type',$exterior_material_type); //Это ТВ	
	$doc->edit($id)->set('alias',$alias);
	
	$doc->save(true,true);
}
return;


Всё работает, ТВ так вообще меняется сразу после нажатия «Сохранить», а вот pagetitle — только после повторного открытия документа на редактирование.
avatar
Каждый ваш $doc->edit($id) берет документ по-новой и затирает все предыдущие значения. Вам нужно просто set-ить, взяв один раз
$doc->edit($id);
$doc->set('pagetitle', $pagetitle);
$doc->set('exterior_material_type', $exterior_material_type); //Это ТВ        
$doc->set('alias', $alias);
Комментарий отредактирован 2016-04-15 08:00:13 пользователем webber
avatar
Да, это я уже понял, спасибо. Вообще это все нужно только для нового создаваемого документа, вот что я понял )

P.S. Хотя на самом деле не затирает. Но конечно логичнее как вы сказали.
Комментарий отредактирован 2016-04-15 08:48:04 пользователем Aharito
avatar
А насчет OnDocFormPrerender — выбор сомнительный. Обычно все нужные измеенния вносятся на событии OnDocFormSave — которое наступает сразу после сохранения документа, чтобы и в дереве и при следующем открытии уже было все как намечалось :)
avatar
$e = $modx->Event;
switch ($e->name) {
    case 'OnDocFormSave' :
        $q = $modx->db->query("UPDATE `modx_site_content` SET `pagetitle` = CONCAT(`pagetitle`, ' - " . $id . "') WHERE id={$id} LIMT 0,1");
        break;
    default:
        break;
}


Это в админке :)
avatar
А я выше через modResource сделал. Есть ли в этом смысл? или как вы, напрямую в базе можно менять через DBAPI?

Насколько я понимаю, напрямую можно менять в базе, если не происходит никаких дополнительных действий, привязанных к изменению значений pagetitle и alias и ТВ. Я верно мыслю?
avatar
Думаю, сначала нужно отделить мух от котлет. Вы этот текст смотрели?
avatar
Нет, упустил его из вида. Прочитаю.
avatar
Я что-то не совсем понимаю задачу. Я бы этот pagetitle наоборот только один раз устанавливал на 'OnDocFormSave', введя у себя доп.проверку, что это вновь создаваемый документ

if ($mode == 'new') {
    $q = $modx->db->query("UPDATE `modx_site_content` SET `pagetitle` = CONCAT(`pagetitle`, ' - " . $id . "') WHERE id={$id} LIMT 0,1");
}


А уж потом, при редактировании надо чтобы была возможность это отредактировать на любой другой
avatar
Да, я нечетко сформулировал хотелку. Поэтому вышла каша. Вот почётче.

Есть документы-товары.
Они уж обладают рядом признаков (TV).
По этим ТВ нужно вычислить значения других ТВ.
У них уже есть заголовки pagetitle, которые нужно заменить.

Мне бы хотелось (для админки):
1) Чтобы некоторые ТВ вычислялись по значениям других ТВ сразу в процессе редактирования. Или хотя бы в момент сохранения документа.
1.1) И чтобы вычисленные значения ТВ появлялись в форме редактирования мгновенно после установки значений исходных ТВ (как в зависимых списках, выбрал в селекте город — для него появился список улиц этого города, или выбрал производителя машин — появился список его марок). Это в идеале.
1.2) Если не в идеале — то чтобы ТВ вычислялось в момент сохранения документа. Например, выбрал из списка марку машины, нажал «сохранить» — и в ТВ «производитель» записалось нужное значение и стало видно в форме редактирования (это я уже сделал).

2) Похожая история и с pagetitle. Его нужно формировать, используя признаки-ТВ (в топике для упрощения я употреблял ID документа). Причем не просто формировать, а желательно сразу и отображать в форме редактирования.

У меня он формируется, но отображается только если сохранить документ, потом ткнуть по другому до-ту, а потом снова ткнуть в этот.

Зачем мне все это надо? Вопрос интересный. По большей части для расширения познаний MODx — экспериментирую.

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

Но: 1) из интереса делал, 2) то же самое нужно и для вновь создаваемых документов-товаров.

Вот это теееекст вышел… если кто-то всю простыню прочитает — я сильно удивлюсь ))
avatar
Чтобы менять «на лету» — тут без js не обойтись. Подсунуть его можно на событии OnDocFormRender т.е. что-то типа такого
$output = '';
if($modx->event->name == 'OnDocFormRender') {
    global $content; //тут сразу получим доступ ко всем существующим полям вроде $content['parent'] и т.п.
    $output .= '<script type="text/javascript">jQuery(document).ready(function($){';
    $output .= '
        $("#tv10").on("change", function(){
            $("#tv11").val($("#tv10").val());
        })
    ';
    $output .= '})</script>';
    $modx->event->output($output);
}


Простейший пример, когда при изменении значения тв с id=10 будет меняться и значение тв с id=11 (теоретически, в зависимости от того, какие скрипты еще подключены — возможно надо будет сделать noConflict();)
avatar
О! спасибо! я как раз думал, какое событие использовать — OnDocFormRender или OnDocFormPrerender.
avatar
Конкретно для моего типа примеров (исполнение jquery при полной готовности документа) особой разницы нет OnDocFormPrerender (вызывается до начала формирования формы редактирования документа) или OnDocFormRender (вызывается сразу после формирования формы). Просто в OnDocFormPrerender у вас есть шанс подменить какие-то поля до того, как они рассчитались и вывелись (даже без js, через тот же global $content;), а вот уже после формирования формы значения полей можно подменить только на js, но зато они все уже известны, т.к. форма готова полностью :)

п.с. процесс формирования формы идет по адресу manager/actions/mutate_content.dynamic.php :)
Комментарий отредактирован 2016-04-15 12:59:03 пользователем webber
avatar
Ещё бы кто-нибудь заранее сказал мне, что есть такое $mode == 'new' :)
Тем и хороша MODx — сюрпризами.
avatar
Говорить тут особо нечего. Если вы хотите сохранить контент, то логично зайти в файл manager/processors/save_content.processor.php и найти там вызов событий при сохранении документа и увидеть, что ему в любом случае передается id и mode, равное new или upd (новый документ или существующий )))
avatar
Спасибо за «наводку», обязательно покопаюсь в коде. В том-то и проблема, что на разбор исходников ядра далеко не всегда есть время.

Хорошо, что есть такие люди как вы, Pathologic, Dmi3yy, w-navt, abadello и другие, которым не лень подсказать и направить куда надо.
avatar
Вы слишком хорошо обо мне думаете, просто мы с вами идём где-то параллельно и я имею корыстный интерес. Разбираясь с вашими вопросами — решаю свои.
avatar
Договорились. Буду думать плохо ))
avatar
Я конечно всё понимаю, но может вам просто задать новый плейсхолдер?
Делаете сниппет в head:

[[pl]]
<head>
<title>[+pagetitle2+]</title>
</head>

код сниппета:
$modx->setPlaceholder('pagetitle2','Это страница '.$modx->documentIdentifier);

Стоит обратить внимание что плейсхолдеры устанавливаются как внутри сниппетов через плюсы а не звёздочки.
avatar
avatar
Плейсхолдер — это можно сделать для вывода на фронт. Меня же интересует админка.

Бывают ситуации, когда название ресурса просто нет смысла выдумывать. Например, это квартира, которая характеризуется кол-вом комнат, площадью там и этажом. Таких квартир штук 200 разных.

Выдумывать для каждой квартиры название не хочется, писать его вручную в админке — тоже. Его можно сформировать автоматом из признаков — 3-х комнатная квартира с гардеробной площадью и т.д…

Этот pagetitle пойдет и для админки, и для фронте как тайтл.
avatar
Топикстартер писал:
Забыл написать, что это в админке нужно, при открытии документа менеджером на редактирование.
Ваш же вариант подменяет [*pagetitle*] во фронтэнде.
avatar
По поводу сырости плагина Вы правы, он еще очень слишком сырой!
1 — если увас структрура имеет минимум три вложенности как получить всех потомков с шаблоном «товар»???
2 Совместимость с PHP > 7 (не слышал =)) ) -у Вас в полном хаосе получения значения из массива где-то в ковычках, где-то без (видимо было лень).
Работу же самого плагина оценить так и не удалось, так как хотел увидить товары=(
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.