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

Делалось Лешей Либером (на основе url) и мной на основе id-шек на одном проекте. Можно сказать, что я просто немного пошаманила над кодом Леши, чтобы не было дубликатов и ошибок.

Теперь к делу. Вот итоговая штука, которая у нас вышла:

итог

Что делает штука? У нас есть тип ресурса Товар. У этого товара есть три поля с наименованием его модели, серии и маркировки. Вообще это может быть что угодно: поле с ценой, поле с артикулом, весом и пр.

Предположим менеджеру лениво было создавать товары и он, при заполнении не писал ничего в сео полях или longtitle и description, но исправно записывал видимую информацию о товаре. В итоге у него вышло так:

Красный диван из кожи
Синий диван без ножек
Розовый диван
и т.д.


Приходит сеошник и конечно возмущается. Ему нужно перелопатить 500 товаров и правильно их назвать. Благодаря данному скрипту он сделает это так: напишет в табличку быстрого редактирования номера страниц товаров, которые увидит на сайте в непотребном виде, и напишет так:

Купить диван {Наименование} {Маркировка} в Москве за {Цена} рублей

И все пять сотен диванов станут называться по другому. Удобно? Ну явно удобнее, чем открывать каждый ресурс отдельно или править БД :)

Меньше слов, больше дела. Создаем.


1. В настройках — панели создаем новый виджет и пишем в него произвольное имя. Тип — сниппет, размер — на всю ширину, пространство имен — core, словарь — core:dashboards. В содержимое виджета пишем SeoWidget_Id (это название будущего сниппета).
2. Назначаем виджет Панели.

3. Ну и создаем сам сниппет.

Код сниппета SeoWidget_Id (версия моя)
$err = '';
// ловим отправленные из формы списки поля, в котором пользователь вводит через запятую айдишки страниц
if (isset($_POST['urls'])) {     
    $urls = trim($_POST['urls']);    
    $urls = explode(",", $urls);
    foreach($urls as $url) {
           $id = trim($url);             
           $err[] = $id;
// Находим документы по этим айдишкам
if ($res = $modx->getObject('modResource', $id)) {
// и берем из них номера присвоенных TV.
            $good_name = $res->getTVValue(19);
            $good_mark = $res->getTVValue(20);
            $series_list = $res->getTVValue(27);
 // Немного магии           
            $healthy = array("{Наименование}", "{Маркировка}", "{Серия}");
            $yummy   = array($good_name, $good_mark, $series_list);

            $pagetitle = str_replace($healthy, $yummy, $modx->db->escape($_POST['pagetitle']));
            $longtitle = str_replace($healthy, $yummy, $modx->db->escape($_POST['longtitle']));
            $description = str_replace($healthy, $yummy, $modx->db->escape($_POST['description']));
            
            $seo_h1 = str_replace($healthy, $yummy, $modx->db->escape($_POST['seo_h1']));
            $seo_title = str_replace($healthy, $yummy, $modx->db->escape($_POST['seo_title']));
            $seo_description = str_replace($healthy, $yummy, $modx->db->escape($_POST['seo_description']));      
// сохраняем что вышло            
            $res->set('pagetitle', $pagetitle);
            $res->set('longtitle', $longtitle);
            $res->set('description', $description);
// помним, что до поля сохраняются через  setTVValue, а родные через  set    
            $res->setTVValue('seo-h1',$seo_h1); 
            $res->setTVValue('seo-title', $seo_title); 
            $res->setTVValue('seo-desc', $seo_description); 
            $res->save();
        }	
}
}
 // Часть Леши  - визуальная форма наша
if ($err) {
    $eraray = implode(",", $err);
    $eraray = 'Изменены следующие ID:
'.$eraray;
}
?>
<p>Доступные плейсхолдеры: {Наименование} {Маркировка} {Серия}</p>
<? echo $eraray;?>
<form method="post" action="">
<div class="x-form-item x-tab-item" tabindex="-1">
    <label for="seopro-keywords" style="width:auto;" class="x-form-item-label">Заголовок (PAGETITLE)</label>
    <div class="x-form-element" style="padding-left:0;">
        <input type="text" size="20" autocomplete="on"  class="x-form-text x-form-field" title="" style="width:calc(100% - 10px);" name="pagetitle" value="<? echo $_POST['pagetitle'];?>">
    </div>
    <div class="x-form-clear-left"></div>
</div>

<div class="x-form-item x-tab-item" tabindex="-1">
    <label for="seopro-keywords" style="width:auto;" class="x-form-item-label">Расширенный заголовок (LONGTITLE)</label>
    <div class="x-form-element" style="padding-left:0;">
        <input type="text" size="20" autocomplete="on"  class="x-form-text x-form-field" title="" style="width:calc(100% - 10px);" name="longtitle" value="<? echo $_POST['longtitle'];?>">
    </div>
    <div class="x-form-clear-left"></div>
</div>

<div class="x-form-item x-tab-item" tabindex="-1">
    <label for="seopro-keywords" style="width:auto;" class="x-form-item-label">Описание (Description)</label>
    <div class="x-form-element" style="padding-left:0;">
        <input type="text" size="20" autocomplete="on"  class="x-form-text x-form-field" title="" style="width:calc(100% - 10px);" name="description" value="<? echo $_POST['description'];?>">
    </div>
    <div class="x-form-clear-left"></div>
</div>

<div class="x-form-item x-tab-item" tabindex="-1">
    <label for="seopro-keywords" style="width:auto;" class="x-form-item-label">H1</label>
    <div class="x-form-element" style="padding-left:0;">
        <input type="text" size="20" autocomplete="on"  class="x-form-text x-form-field" title="" style="width:calc(100% - 10px);" name="seo_h1" value="<? echo $_POST['seo_h1'];?>">
    </div>
    <div class="x-form-clear-left"></div>
</div>

<div class="x-form-item x-tab-item" tabindex="-1">
    <label for="seopro-keywords" style="width:auto;" class="x-form-item-label">Title</label>
    <div class="x-form-element" style="padding-left:0;">
        <input type="text" size="20" autocomplete="on"  class="x-form-text x-form-field" title="" style="width:calc(100% - 10px);" name="seo_title" value="<? echo $_POST['seo_title'];?>">
    </div>
    <div class="x-form-clear-left"></div>
</div>

<div class="x-form-item x-tab-item" tabindex="-1">
    <label for="seopro-keywords" style="width:auto;" class="x-form-item-label">Description</label>
    <div class="x-form-element" style="padding-left:0;">
        <input type="text" size="20" autocomplete="on"  class="x-form-text x-form-field" title="" style="width:calc(100% - 10px);" name="seo_description" value="<? echo $_POST['seo_description'];?>">
    </div>
    <div class="x-form-clear-left"></div>
</div>

<div class="x-form-item x-tab-item" tabindex="-1">
    <label for="seopro-keywords" style="width:auto;" class="x-form-item-label">Номера страниц (строго через запятую)</label>
    <div class="x-form-element" style="padding-left:0;">
        <textarea autocomplete="on"  class="x-form-textarea x-form-field" title="" style="width:calc(100% - 10px);" rows="10" name="urls"><? echo $_POST['urls'];?></textarea>
    </div>
    <div class="x-form-clear-left"></div>
</div>
<div style="text-align:center; margin-top:15px;">
    <button type="submit" class="primary-button x-btn x-btn-text">Отправить</button>
</div>
</form>

На всякий случай уточню, что есть номера TV полей, а то мало ли, может кто еще чего напутает, я за 5 лет перестала удивляться многому :)

А, самое главное. Помните, что шаблоны эти {Цена} и {Маркировка} должны существовать в реальном мире. У Вас 100% не получится изменить у категории заголовок на

Купить диваный в Москве от {Цена} рублей

Если поле цены не назначено шаблоны категории. Просто напоминаю :)

Ну и все почти.


Правда менеджерам лениво искать айдишки в админке, по-этому еще и так делаем:
в шаблоне товара (ну или в карточке товара в категории) пишем его id только для менеджера. Удобно на fenom конечно, но данный сайт пришел сторонний и я не стала его переделывать, а использовала что есть.

Ставим компонент Personalize и пишем код в карточке после названия товара:

[ [!Personalize?
    &yesChunk=`@CODE:<br /><small>№ </small>`
    &context=`mgr`
] ]


В итоге на страницах только для менеджера сразу пишется какой номер у ресурса и не нужно ползать по админке. Если у владельца сайта принципиальных просьб нет, то эту айдишку можно замаскировать под что угодно: артикул, код модели и т.д. и не заморачиваться с ее сокрытием.



На этом моя часть закончилась. Идея Леши была вставлять не айдишки, а url страниц, которые массово требуется поменять. И мы все попросим его самого в комментарии добавить этот код, чтобы мы его заплюсовали ;)