MultyTags (структурированные теги)

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

Что это делает?

Внутри PmWiki есть механизм хранения "обратных ссылок". В момент сохранения любой страницы движок PmWiki собирает все внутренние ссылки, которые на ней есть и записывает их в отдельное поле "targets" текущей страницы в виде строки. По-умолчанию, это поле никак недоступно ни для редакторов, ни для администраторов сайта, но оно есть. Благодаря нему возможно быстро сделать выборку всех страниц, ссылающихся на страницу Х (без такого механизма пришлось бы прочесть и проанализировать содержимое всех страниц всего сайта, а это очень долго). Как следствие механизмом обеспечены разнообразные возможности структурирования контента, например Backlinks или невероятный PageListMultiTargets, позволяющий создавать любые "срезы" материалов по комбинации линков. Механизм глубоко интегрирован с ядром движка PmWiki и поддерживается другими подсистемами - кэшированием, pagelist'ингом и т.д.

Так вот: кратко суть настоящего рецепта в том, чтобы получить возможность вместо этого дефолтного фукнционала PmWiki, собирающего ссылки из контента страницы, выбирать их вручную из структуры сайта. А в остальном остаться полностью в рамках "ядра" PmWiki.

Демо

todo: добавить скриншотов

Использование

Для активации рецепта необходимо зайти в ConfigEditMode и активировать параметры MultyTagsConditions и MultyTagsGoals. Подсказки можно найти на этой же странице. Настройки позволяют определить критерии страниц, для которых будет активирован Рецепт, то есть, например, выбрать Группы, где он будет работать.

После активации этих настроек в режиме редактирования соответствующих страниц появится кнопка "связанные страницы".

С этого момента:

  • при первом редактировании страницы "связанные страницы" расставятся автоматически движком PmWiki
  • при последующих редактированиях расстановка ссылок будет сохраняться таковой, какую определит редактор сайта
  • механизм можно отключить на любой странице директивой (:multytags:off:) (которая должна быть обработана в MultyTagsConditions)

Внимание: невозможно выключить все ссылки. Хотя бы одна должна оставаться, иначе будет снова автоматически активирован дефолтный механизм PmWiki. Это архитектурное ограничение, выдержанное по техническим причинам ради обратной совместимости.

Почему так?

Либо теги выбраны руками (причем хотя бы один), либо работает движок PmWiki. Все, нет варианта, что поле вообще пустое, так как это сильно усложняет реализацию и, главное, может привести к сложнопредсказуемым последствиям по мере развития сайта.

В каком-то смысле это логично. Рецепт предоставляет возможность по кастомизации тегов, а "убирание тегов" - это не его задача.

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

Техническая информация

Требования

Режим редактирования Skin: editMode.tmpl

Как это работает архитектура решения

  • ThisSite.ConfigEditMode содержит описание условий вызова функционала и целевых страниц предоставляемых для расстановки ссылок. Результатом заполнения данных становится выполнение pagelist, формирующего группы выпадающих списков (select), которые встраиваются в ThisSite.EditForm
  • ThisSite.EditForm получает $TargetsBase из PV, созданной в phMultyTags.php, и, с помощью небольшого JS-скрипта оттуда же, расставляет options по select
    • полезно знать, что в Lebedizator есть PHP-код , генерирующий select с уже расставленными тегами. Это позволяет сохранять "расставленность" тегов без использования JS .
  • в момент сохранения страницы массив выбранных значений обрабатывается тем же phMultyTags.php, который отключает встроенный механизм PmWiki И записывает значение массива в поле в виде строки.
  • в момент исполнения любой страницы с помощью функции phMultyTargetsOutput из phMultyTags.php могут быть сформированы необходимые PageVariables, необходимые в данной локальной вики

phMultyTags.php общее описание серверной части решения

  • ОБРАБОТЧИК ДЛЯ РЕЖИМА РЕДАКТИРОВАНИЯ: расставляет уже выбранные теги по мультиселектам (требует jQuery, используется только в режиме редактирования).
  • ОБРАБОТЧИК ДЛЯ РЕЖИМА СОХРАНЕНИЯ СТРАНИЦЫ: записывает значение в поле страницы. Активируется, если получает на входе нужный массив.
  • ОПРЕДЕЛИТЕЛЬ поля $Targets - $FmtPV['$Targets']. Реализован здесь потому, что необходим для Обработчика Режима Редактирования
  • ФУНКЦИЯ phMultyTargetsOutput: форматирует ссылки из поля targets в необходимый вид. Используется в контексте формирования PageVariables функцией $FmtPV.

function phMultyTargetsOutput

Функция форматирует ссылки из поля targets в необходимый вид. Используется для создания PageVariables актуальных в контексте локальной копии wiki. Позволяет:

  • изменять сортировку страниц
  • ограничивать вывод ссылок только одной конкретной Группой
  • исключать конкретную Группу из вывода ссылок
  • выводить ссылки в виде wiki-кода (по-умолчанию), текста, или html-кода

Обязательный параметр только $page, остальные опциональны:
phMultyTargetsOutput ($page, $sortFUNC = NULL, $selectedGroup = NULL, $ignoreGroup = NULL, $output = NULL)

Функция предназначена для использования только во время определения PageVariables в массиве $FmtPV в локальной конфигурации Wiki.

Клоны функции для особых задач

  • function phMultyTargetsOutput_groupPattern - функция создает PV из всех страниц поля Targets, группа которых удовлетворяет паттерну $groupPattern. Таким образом мы можем получить выборку ссылок, в названиях Групп которых которых встречается "-Forma".

Подключение

Рецепт связан со следующим:

  • основной php-файл вызван из (farm)config.php;
  • конфигурация в ThisSite.ConfigEditMode;
  • непосредственный вызов на ThisSite.EditForm
  • рецепт использует файлы bootstrap-multiselect.css, bootstrap-multiselect.js

Настройки

В ThisSite.ConfigEditMode можно настроить переключение режимов radio/select: использовать ли множественный выбор тегов ИЛИ ровно один в группе.

Остальные настройки доступны на уровне PHP.

(farm)config.php после вызова php-файла рецепта

Чтобы отключить использование bootstrap-multiselect, занулите следующие массивы:

$HTMLHeaderFmt['scripts']['multytags-multiselect'] = "";
$HTMLHeaderFmt['scripts']['multytags-multiselect-init'] = "";

Чтобы изменить CSS-стили отображения мультиселектов в режиме редактирования, напишите их сюда:

$HTMLHeaderFmt['styles']['multytags'] = "%css-код%"; // или можете дополнить существующий ключ новыми значениями...

Создание PageVariables для использования в навигации:

(:source lang=php linenum tabwidth=4:)
/* по-умолчанию: */
$FmtPV['$Targets'] = "\$page['targets']";  // это просто содержимое поля (строка, значения разделены запятой)
$FmtPV['$TargetsBase'] = "phMultyTargetsOutput(\$page)"; // это необходимая PV, используется в режиме редактирования для авторасстановки тегов

/* примеры расширения: */
$FmtPV['$TargetBase'] = "phMultyTargetsOutput(\$page)"; // генерирует простые wiki-ссылки вида [[Group.Page|+]]. Ссылки не сортированы - выводятся, как были записаны. 
$FmtPV['$TargetSortAlfa'] = "phMultyTargetsOutput(\$page, \"sort\")"; // сортировка по алфавиту (хотя обычно они и так рассортированы по алфавиту)
$FmtPV['$TargetUsort'] = "phMultyTargetsOutput(\$page, \"cmp\")"; // сортировка через http://php.net/manual/ru/function.usort.php , здесь "cmp" - это имя пользовательской функции для сравнения элементов, котороую, как ожидается, напишет владелец сайта. Это может быть любое имя, кроме "sort".
$FmtPV['$TargetSelectedGroup'] = "phMultyTargetsOutput(\$page, NULL, \"Profiles\")"; // оставляет ссылки только из группы "Profiles"
$FmtPV['$TargetIgnoredGroup'] = "phMultyTargetsOutput(\$page, NULL, NULL, \"Profiles\")"; // оставляет ссылки только НЕ из группы "Profiles"
$FmtPV['$TargetOutputTEXT'] = "phMultyTargetsOutput(\$page, NULL, NULL, NULL, \"text\")"; // выводит ссылки в виде текста
$FmtPV['$TargetOutputHTML'] = "phMultyTargetsOutput(\$page, NULL, NULL, NULL, \"<a href='\\\$LinkUrl'>\\\$LinkText</a><br>\")"; // форматирует ссылки в html по шаблону через функцию MakeLink. $LinkUrl и $LinkText обязательны.

/* phMultyTargetsOutput_groupPattern */
$FmtPV['$TargetsForma'] = "phMultyTargetsOutput_groupPattern(\$page,\"-Forma\")"; // в результате получим в PV $TargetsForma получим все ссылки, ведущие на все группы, в имени которых встречается "-Forma". 

Синтаксис

(:multytags:off:): отключает на текущей странице механизм выбора "связанных страниц". Вместо него включится встроенный в PmWiki функционал, автоматически собирающий все вики-ссылки контента страницы. Внимание! Чтобы команда работала, необходимо учесть ее обработку в условиях запуска Мультитегов здесь: ConfigEditMode.

Служебная информация

Status
stable
Core
yes
PHPcookbook
phMultyTags.php

Version
20191004

FAQ

Как при выводе ссылок на странице делать заголовки у каждой новой группы?

Сортируем ссылки по группам, затем решаем в основном через CSS:

(:source lang=html5 linenum tabwidth=4:)
<li data-href='Myth.Myth1'><a href='Myth.Myth1'>1s myth</a></li>
<li data-href='Myth.Myth2'><a href='Myth.Myth2'>2s myth</a></li>
<li data-href='Persons.Persons1'><a href='Persons.Persons1'>Зевс</a></li>
<li data-href='Persons.Persons2'><a href='Persons.Persons2'>Еще кто-то</a></li>

li[data-href*="Myth"]:first-of-type:before {
  content: "Мифы:"; 
  display: block; 
  font-weight: bold;}

li[data-href*="Myth"] + li[data-href*="Persons"]:before {
  content: "Персонажи:"; 
  display: block; 
  font-weight: bold;}

http://www.cssdesk.com/3p6bA

Связанные страницы:

Todo:PublicRelease

  • сделать скриншоты