Finar.ru
web.finar.ru
video.finar.ru
Темы для BootstrapNew!

PmWiki как CMS: шаг второй

продолжаем создавать классическую CMS из PmWiki

Автор: Люди, дата: 2010-12-21, просмотров 2218
Тэги

темы: PmWiki

Мы продолжаем разрабатывать уникальную Систему Управления Сайтами (CMS) на базе движка PmWiki. Мы адаптируем отличный wiki-движок к классическим задачам сайтостроения, в результате чего рождается уникальный симбиоз wiki-концепции с функциональностью традиционной CMS. Все примененные "фичи" используются в реальности на этом сайте прямо сейчас.

Предыдущая статья - PmWiki как CMS: шаг первый

Напомню, что преимущественно конфигурация PmWiki хранится в файле /local/config.php , в котором подключаются php-плагины или "рецепты" из директории /cookbook

Модификации config.php после публикации сайта:

установлен плагин SourceBlock 

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

определяем формат представления дат для всего сайта:

$TimeFmt = '%Y-%m-%d'; # dates as "2005-09-08"

разберемся с аттачами: мультизагрузка файлов в архиве с автоматическим разархивированием на сервере

В PmWiki аттачи (т.е. файлы, прикрепленные к странице) можно хранить либо все в одной куче, либо все в одной группе (в директориях второго уровня), либо в отдельной директории для каждой страницы. Очевидно, что наиболее осмысленны крайние варианты - либо уж кидать все одну кучу, либо держать в полном порядке. Сначала я решил устроить коммуну, и сбросить все в одну кучу, но позже передумал. В основном из архитектурных соображений - в случае чего, сваленные в кучу файлы рассортировать гораздо сложнее, чем свалить в кучу рассортированные.

Кроме того, "постраничное" хранение аттачей позволило сделать исключительно простой и удобный метод загрузки файлов на сервер с помощью плагина multiupload.php Достаточно собрать файлы в zip-архив и загрузить их на сервер через форму в разделе аплоада данной страницы (?action=upload). Необходимая уникальная директория будет создана автоматически, файл будет подгружен в нее, разархивирован и автоматически удален. Глупый юзер может загружать какой угодно хлам, лишь бы в нем не было кириллических имен файлов (хотя, может и с ними будет работать, не пробовал).

  1. $UploadPrefixFmt = '/$Group/$Name';
  2. $UploadMaxSize = 10485760; // лимит на загружаеый файл - 10 МБ
  3. include_once("$FarmD/cookbook/multiupload.php"); // плагин для загрузки группы файлов в zip-архиве
  4. $UploadExts = array( // разрешим аплоад файлов разных типов
  5.   'prproj' => 'text/plain',
  6. );

Минусом постраничного хранения является необходимость писать абсолютные пути к тем аттачам, которые могут попасть на другие страницы сайта при использовании команды include.

задаем новую переменную для страниц - дату создания.

Эта переменная будет служить основным критерием сортировки Базы Знаний сайта:

$FmtPV['$Created'] = "strftime(\$GLOBALS['TimeFmt'], \$page['ctime'])";

Стоит отметить, что это Page Variable (PV), а не Page Text Variable (PTV). Разница в том, что PV более "низкоуровневая" - ее значение записывается в отдельное "поле" страницы сайта, то есть в отдельную строку физического файла с описанием страницы, например "wiki.d/Base.PmWikiAsCMS-step2". Переменные PTV не записываются в отдельные поля, а остаются в поле с контентом страницы, где-то внутри него. Преимущества PV - это более быстрый поиск, выборки и сортировки, а также возможность создания отдельной формы для ввода значения в режиме редактирования. Недостаток - необходимость создания поля в конфиге CMS.

добавляем новые поля в форму редактирования материала:

$EnablePageTitlePriority = 1;
делаем приоритетным первое определение title в странице, чтобы при include других страниц, он не заменялся. Похоже, это может быть лишней директивой, т.к. далее обработка синтаксиса (:Title:) будет вообще отключена в плагине EditFormCustomFields

$ctimeDispFmt = "%Y-%m-%d";
формат вывода даты для поля даты создания статьи

include_once('cookbook/strptime.php');
т.к. периодически мощные доработки сайта я произвожу на локальном веб-сервере XAMPP под Windows, а нижеследующий плагин использует функцию strptime, доступную в PHP на уровне ядра только под Unix-like системами, придется эту функцию надстроить отдельным решением, а именно скриптом от француза Саурона 

include_once('cookbook/editformcustomfields.php');
плагин для генерации пользовательских форм с добавленными формами Description и Ctime (дата создания статьи)

DisableMarkup("keywords");
DisableMarkup("description");
Отключаем обработку keywords и description в теле wiki-контента, т.к. теперь для них есть отдельные поля как в форме редактирования, так и в самом wiki-файле. По-умолчанию, почему-то PmWiki хоть и хранит description в отдельной переменной, но при формировании страницы парсит ее из текста. Теперь будет брать из переменной, только соответствующую запись надо внести в шаблон.

Небольшая модификация разметки:

  1. Markup('[[<<]]','inline','/\\[\\[&lt;&lt;\\]\\]/',"<div class='clear'></div>");
  2. Markup("'+","<'''''","/'\\+(.*?)\\+'/",'<span style=\'font-size:122%\'>$1</span>');
  3. Markup("'-","<'''''","/'\\-(.*?)\\-'/",'<span style=\'font-size:80%\'>$1</span>');

Такими командами можно заменить дефолтную обработку pmwiki-разметки. В данном случае, это понадобилось, чтобы обеспечить валидность HTML-кода главной страницы.

Включаем функцию подсчета ссылок, в том числе мертвых

include_once('scripts/refcount.php');
Делается это с целью получить возможность найти все "задуманные", но не написанные статьи; а также все ссылки на них на всех страницах.

Комплексный анализ контента всего сайта осуществляется скриптом /scripts/refcount.php Скрипт рассчитан на работу с формой ввода поиска, использующей метод post. Однако, оказывается, параметры также могут задаваться через адресную строку, например вот так можно вывести все "мертвые" ссылки сайта кучей по одной ссылке. Синтаксис обращения можно понять изучив вышеуказанный пример и файл /scripts/refcount.php

Включаем поддержку отображения swf-файлов, удобное встраивание видео с vimeo и youtube

include_once("$FarmD/cookbook/swf-sites.php");
include_once("$FarmD/cookbook/swf.php");
см. Cookbook:Flash 

Научаем wiki искать статьи в группе Base, если соответствующей статьи еще нет в данной группе:

$PagePathFmt = array('$Group.$1','Base.$1','$1.$1','$1.$DefaultName'); Таким образом на базе движка будет организована система из многих сайтов (доменов), на каждом из которых будет поднят свой внешне независимый проект. Однако База Знаний (или, проще, статьи) для всех проектов будет единой.

Убираем подчеркивание и стрелку у картинок, являющихся ссылками на внешние сайты

Честно, я не до конца разобрался с этим кодом (не настолько интересная задача, чтобы заморачиваться). Взял отсюда , вставил, и все заработало :), хотя, вероятно, и несколько избыточно.

  1. $EnableUploadOverwrite = 0;
  2. function OtherGroupCss($group)
  3. {
  4.     global $pagename;
  5.     $current = PageVar($pagename, '$Group');
  6.     if($group == $current) return "";
  7.     return " othergroup";
  8. }
  9. $FmtPV['$OtherGroupCss'] = 'OtherGroupCss($group)';
  10. $LinkPageExistsFmt =
  11.    "<a href='\$LinkUrl'>\$LinkText</a>";
  12. $LinkPageCreateFmt =
  13.    "<a class='createlinktext' rel='nofollow' href='{\$PageUrl}'>\$LinkText</a><a class='createlink' href='\$PageUrl'>?</a>";
  14.  
  15.  
  16. $LinkFunctions['http:'] = 'TxtLinkIMap';
  17. $LinkFunctions['https:']  = 'TxtLinkIMap';
  18. $LinkFunctions['mailto:']  = 'MailLinkIMap';
  19. $LinkFunctions['Attach:'] = 'TxtLinkUpload';
  20. SDV($EnableUploadOverwrite,1);
  21. $IMapLinkFmt['Attach:'] =
  22.     "<a class='urllink' href='\$LinkUrl' rel='nofollow'>\$UploadText</a>";
  23. if ($EnableUploadOverwrite)
  24.     $IMapLinkFmt['Attach:'] .=
  25.     "<a class='createlink' href='\$LinkUpload'>&nbsp;&Delta;</a>";
  26. $UrlLinkTxtFmt = "<span class='url'>$UrlLinkFmt</span>";
  27. $MailLinkTxtFmt = "$UrlLinkFmt";
  28. $UrlLinkFmt    = $UrlLinkTxtFmt;
  29. $UrlLinkImgFmt =
  30.     "<a class='urllinkimg' href='\$LinkUrl' target='_blank' rel='nofollow'>\$LinkText</a>";
  31.  
  32. function TxtLinkIMap($pagename,$imap,$path,$title,$txt,$fmt=NULL) {
  33.   global $UrlLinkImgFmt, $UrlLinkTxtFmt;
  34.   if (!$fmt)
  35.       $fmt = preg_match('/^<img/',$txt) ? $UrlLinkImgFmt : $UrlLinkTxtFmt;
  36.   return LinkIMap($pagename,$imap,$path,$title,$txt,$fmt);
  37. }
  38.  
  39. function TxtLinkUpload($pagename, $imap, $path, $title, $txt, $fmt=NULL) {
  40.   global $FmtV;
  41.   $FmtV['$UploadText'] = str_replace('Attach:','',$txt);
  42.   return LinkUpload($pagename,$imap,$path,$title,$txt,$fmt);
  43. }
  44.  
  45. function MailLinkIMap($pagename,$imap,$path,$title,$txt,$fmt=NULL) {
  46.   global $UrlLinkImgFmt, $MailLinkTxtFmt;
  47.   if (!$fmt)
  48.       $fmt = preg_match('/^<img/',$txt) ? $UrlLinkImgFmt : $MailLinkTxtFmt;
  49.   return LinkIMap($pagename,$imap,$path,$title,$txt,$fmt);

Обеспечиваем валидность html-кода в toggle.php - генераторе JavaScript-кнопок

Рецепт Cookbook:Toggle , примененный еще на первом этапе для создания кнопок как в прошлом параграфе, всем хорош, кроме того, что вставляет JavaScript-код кнопки в контенте непосредственно перед ее применением, то есть внутри тега <body>. Это противоречит стандартам HTML, поэтому, специально, чтобы код первой страницы нашего сайта стал полностью валидным, пришлось немного доработать файл toggle.php. Вот как теперь выглядит его конец (со 154-й строчки):

  1. // здесь введена новая переменная $validStyle затем, чтобы в ней сохранить весь генерируемый  CSS, а затем вставить его в header страницы, дабы код страницы валидировался.
  2.     $validStyle = "#{$id} { display:{$style}; } ";
  3.     if ($args['printhidden']==1) $validStyle.= " @media print { #{$id} {display:block} } ";
  4.     if ($id2) {
  5.         $validStyle.= " #{$id2} { display:{$altstyle}; } ";
  6.         if ($args['printhidden']==1) $validStyle.= " @media print { #{$id2} {display:block} } ";
  7.  
  8.         }
  9.  
  10. $HTMLStylesFmt['toggle'] .= " @media print {.toggle{display:none}} .toggle img {border:none;} $validStyle";  // перемещено сюда с 54 строчки by Finar
  11.  
  12.  
  13.  
  14.    return Keep($out);
  15.  
  16.  
  17. }
  18. #EOF

tagger.php - мультитэги с древовидной структурой

Это еще один плагин, позволяющий реализовать мультитэговость. Описание его работы довольно объемно, поэтому выношу его в отдельную статью: Кровеносная система finar.ru - мультитэги с древовидной структурой


Оставить комментарий 


Ваше имя:
->