Содержание
Руководство по включению системы новостей в DokuWiki
Данный документ предлагает рецепт включения системы новостей в Докувики. Вы получаете:
- форму для написания новых новостных заметок;
- одну страницу с аннотацией новостей, на которой отображается заголовок и несколько первых строчек новости;
- одну страницу с полным списком новостей. Новостные заметки помечаются и отображаются датой публикации, а также могут содержать дату потери актуальности (perishing date). Это означает, что при написании заметки можно указать что заметка станет неактуальной, скажем, через две недели.
Можно увидеть пример работы данного решения.
And, oh, you can tinker around with that stuff, it all boils down to using the template plugin and a bit of PHP code in your site template.
Требования
Дополнение шаблона Вашего сайта
Надо перейти в каталог с активным шаблоном Докувики . В моей установке это каталог /var/www/dokuwiki/lib/tpl/mytemplate/
.
Скачать и распаковать в папку с активным шаблоном один из следующих архивов (или скопировать и вставить в файл прямо с этой страницы чуть ниже):
user@server:/var/www/dokuwiki/lib/tpl/mytemplate$ wget http://fsinfo.cs.uni-dortmund.de/~dave/newssystem-0.1.tar.bz2 user@server:/var/www/dokuwiki/lib/tpl/mytemplate$ tar xvjf newssystem-0.1.tar.bz2
Далее, редактируем style.ini
активного шаблона. В разделе [stylesheets]
добавляем строчку news.css
, что показано в отрывке, приведенном ниже:
[stylesheets] layout.css = screen design.css = screen style.css = screen news.css = screen
После выполненной работы Вам должны отредактировать news.css
для получения удобного дизайна соответсвующего Вашему шаблону. Возможно потребуется редактирование .php файлов для получения названий кнопкок и сообщений об ошибках на Вашем языке.
Как использовать
Во-первых: установить формат формы ввода сообщений
Нужно создать страницу со следующим содержанием (предположим, Вы сохранили ее под именем newstemplate
):
* targetpage: newsdata * head: 40| |Заголовок новости * start: 10|date(now)|Дата публикации (1-е появление в списке анонса новостей) * stop: 10|date(2 weeks)|Perishing date (on this day the article will disappear) * text: 50*5| |Your article ----
Данное описание формы будет интерпретироваться datainput.php
, который генерирует HTML из формы ввода следуя этому описанию и сохраняет отосланные данные формы на странице данных. Для активации datainput.php
, см. 2-й шаг.
Замечания по поводу того, что делает datainput.php
Данная секция может быть пропущена. Она содержит некоторую полезную вспомогательную информацию.
Вы видите ниже синтаксис одной строчки шаблона «template»:
* fieldname: fieldvalue
В данном случае fieldname
это обычное слово. Оно используется datainput.php
для именования поля формы в HTML. После отсылки формы, datainput.php
сохраняет введенную информацию на специальной странице, обозначенной специальным полем targetpage
, используя «вымышленные» здесь имена полей. Другой PHP скрипт написан для интерпритации набора данных. Например, отосланное формой генеруируется с использованием определений, определенных выше, и получая в результате следующий набор данных на странице newsdata
:
* head: Заголовок Статьи * start: 2007-12-12 * stop: 2007-12-24 * text: Сим салабим бам базелла дузелла дим. ----
Каждый набор данных отосланный формой будет помещаться перед существующими наборами «старых» данных (что означает: даже если сделать опечатку в поле targetpage
, операция не деструктивная – только добавяться некоторые новые данные, никогда никакие данные не удаляются). Единственный путь отредактировать новость или удалить - «вручную» редактировать страницу с данными.
Значения поля (например, определение размера/типа поля формы) могут быть:
Size | Default | Headline
… и 'Size' может быть единственным целым (для ввода однострочного текста) или что-то подобное X*Y
(столбцов * строчек
для ввода многострочного текста). Также может быть hidden
(это Вам может пригодится в случае когда множество форм пишут в одну страницу данных, но Вы хотите разделить обработывающий код между этими формами … проще создать множество шаблонов форм, все с одинаковым targetpage
, но с различными значениями в hidden
поле).
'Default' - эта часть обычный текст, но может включать функцию date()
, которая really just calls the PHP date() function and uses its output as default. В данном примере, новостная заметка исчезнет через 2 недели после она была опубликована, если только автор записи не введет другую дату.
'Headline' - текст который описывает поле ввода. Он будет отображен напротив соответствующего поля ввода.
Вследствие этого datainput.php
дает Вам обобщенный, конфигурируемый генератор форм ввода данных. Он выдает страницы данных в синтаксисе требуемых плагином template для command. Вы можете создать формы ввода для обычных наборов данных – за исключением одной вещи - PHP кода отображающего дату в Вашей вики. Смотрите template extension для for советов как сделать это – для этого рецепта, newslist.php
and newsdata.php
содержат «display code», т.е. each one implements a different view on the saved datasets. См. ниже как использовать это.
Во-вторых: генерация формы ввода
Эта команда только берет созданную выше страницу данных, интерпретирует ее и генерирует на выходе форму:
#template(datainput.php|newstemplate)#
Это хорошая практика, чтобы написать ниже шаг 4 который на той же самой вики странице, так что после отсылки вы увидите убеждающий эффект на форме.
Завершающий совет для новостной странице ввода (страница writenews
):
====== Write new news ====== **[ [[news|all news]] | [[writenews|write news]] | [[newsdata|edit news]] ]** #template(datainput.php|newstemplate)# #template(newsitems.php|newsdata)#
В третьих: показать превью статьи
Поместите эту штуковину где нибудь на стартовой странице Вашей вики или где Вам нравится. Я бы посоветовал поместить внутрь box
%template?previewlength=120&indexpage=news:news(newslist.php|newsdata)% **[ [[news:news|all news]] | [[news:writenews|write news]] | [[data:newsdata|edit news]] ]**
Просмотр превью новости на странице данных (в этом случае со страницы newsdata
с длиной превью текста в 120 символов). Вторая строка только для удобства (доступ отсюда ко всем связанным с данной страницами).
Fourth: Show complete news articles
This is the wiki page news:news
:
====== News ====== **[ [[news:news|all news]] | [[news:writenews|write news]] | [[data:newsdata|edit news]] ]** #template(newsitems.php|newsdata)#
The first two lines are there for convenience, the actual stuff is done in the last line.
В-четвертых: Редактирование новостной статьи
Вы это сделаете вручную. Не беспокойтесь - откройте Вашу страницу данных и редактирйте ее. Формат страницы данных должен обяснять сам себя. В основном вы будите корректировать незначительные детали, я полагаю, так что я не пишу скрипты для редактирования этой штуковины.
Bugs
- You can't use bullet lists in news articles. The template plugin seems to disallow that.
- You'll need to use
~~NOCACHE~~
on some pages.
Stuff to remember when tinkering around with this stuff
There are some reserved words among the field names, but not all of them are reserved by the same .php file.
datainput.php
You may use datainput.php
to generate arbitrary data input forms. Just remember that the field name targetpage
is reserved. All other field names will be used when writing to the target page – therefore, you may invent some, and they will be used.
The special default value date(something)
will resolve the date represetation of the string 'something' on generation of the form.
newslist.php/newsitems.php
Here the field names start
, stop
, head
and text
are reserved. Any other field in the data page will be ignored.
Author
The author is Dave Kliczbor maligree [at] gmx [dot] de. Feel free to tinker around with this stuff and completely rewrite this wiki page (if you must).
Files
datainput.php
<? /** * DataInput template extension * * Gives you a data input form based on a "data page". * You could define simple text input forms and an output data page. * * You'll need another template extension to display the data! * * @link http://www.dokuwiki.org/wiki:recipes:newssystem * @author Dave Kliczbor <maligree@gmx.de> */ $params = $TEMPLATECOMMAND_SOURCE->getParamHash(); $prefix = "plugin_datainput_"; //now, go through all data sets foreach( $TEMPLATECOMMAND_SOURCE->getHtmlRecords() as $rec_num => $record ) { //ok, display only if showonly is not set or showonly matches the record number if( (!isset($params['showonly'])) || ($params['showonly'] == "$rec_num") ) { //data record is only valid if "target" is set if( isset($record['targetpage']) ) { $targetpage = htmlspecialchars(trim($record['targetpage'])); //security check ... evaluate form only when template data set is unchanged // (i.e. committed hidden field is still in the same template data record number) //and check anyway if the user is allowed to edit teh targetpage if( ($_POST["X-".$prefix.$targetpage] == "$rec_num") && (auth_quickaclcheck($targetpage) >= AUTH_EDIT) ) { $newrecord = ''; foreach( $_POST as $postkey => $postvalue ) { // we only need $_POST fields that start with $prefix if( strpos($postkey, $prefix) === 0 ) { $key = substr($postkey, strlen($prefix)); //DEBUG-Code //echo '<p>' . $key . '</p><p>' . $postvalue . '</p><p>'; if( strpos(trim($postvalue), "\n") !== false ) { // this is a multilined value, so we need to prepend a linebreak // to achieve a multilined value for the template plugin $postvalue = "\n" . $postvalue; } $newrecord .= " * " . $key . ": " . $postvalue . "\n"; } } $newrecord .= "\n----\n\n"; $oldrecord = rawwiki($targetpage); saveWikiText($targetpage, $newrecord.$oldrecord, "New news article"); msg('Your news article has been saved successfully.'); } else if( isset($_POST["X-".$prefix.$targetpage]) ){ msg('Your news article could not be saved. Try to log in to gain permission to write news articles or politely ask your admin to give you permission.'); } echo '<form id="'.$prefix.$targetpage.'" method="POST" action="'.$_SERVER['REQUEST_URI'].'">'; echo '<input type="hidden" name="X-'.$prefix.$targetpage.'" value="'.$rec_num.'">'; //walk through all fields in one data set foreach( $record as $fieldname => $fieldvalue ) { $fieldname = htmlspecialchars(trim($fieldname)); //...but not through certain fields if( $fieldname != 'targetpage' ) { //explode field value by '|' $matches = explode('|', $fieldvalue); //$matches[0] == field type; $matches[1] = default value; $matches[2] == friendly field title; $fieldtype = htmlspecialchars(trim($matches[0])); $fieldtitle = htmlspecialchars($matches[2]); // parse default values if( isset($params['default_'.$fieldname]) ) { $default_value = strtr($params['default_'.$fieldname], "_", " "); } else { $default_value = htmlspecialchars(trim($matches[1])); if( preg_match('/^date\((.*)\)/', trim($matches[1]), $dateparam) !== 0 ) { $default_value = date("Y-m-d", strtotime($dateparam[1])); } } // output fields if( fieldtype == 'hidden' ) { echo '<input type="hidden" name="'.$prefix.$fieldname.'" value="'.fieldtitle.'">'."\n"; } else if( preg_match('/^(\d+)\*(\d+)$/', $fieldtype, $dimensions) > 0 ) { echo '<p>' . $fieldtitle . '</p>' . '<p><textarea name="'.$prefix.$fieldname.'" cols="'.$dimensions[1].'" rows="'.$dimensions[2].'">'.$default_value.'</textarea></p>'."\n"; } else if( preg_match('/^\d+$/', $fieldtype) == 1 ) { echo '<p>' . $fieldtitle . '</p>' . '<p><input type="text" name="'.$prefix.$fieldname.'" size="'.$fieldtype.'" value="'.$default_value.'" /></p>'."\n"; } else { //DEBUG-Code //echo '|' . $fieldtype . "|-|" . $fieldtitle . '|'; } } } echo '<input type="submit" value="Submit!">'; echo '</form>'; } } } ?>
newsitems.php
<? /** * NewsItems template extension * * Displays the complete list of news articles from a data page, * taking care of start and stop dates. * * @link http://www.dokuwiki.org/wiki:recipes:newssystem * @author Dave Kliczbor <maligree@gmx.de> */ foreach( $TEMPLATECOMMAND_SOURCE->getTextRecords() as $rec_num => $record ) { if( (!isset($record['start']) || strtotime($record['start']) < time()) && (!isset($record['stop']) || strtotime($record['stop']) > time()) ) { //format start timestamp if( !isset($record['start']) ) { $date = ''; } else { $date = date('l, d.m.Y ', strtotime($record['start'])); } echo "\n\n=== " . $record['head'] . " ===\n//<sub>" . $date . "</sub>//\n\n"; echo $record['text'] . "\n\n----\n"; } } ?>
newslist.php
<? /** * NewsList template extension * * Displays a preview of news articles. * * @link http://www.dokuwiki.org/wiki:recipes:newssystem * @author Dave Kliczbor <maligree@gmx.de> */ require_once(DOKU_INC.'inc/parser/xhtml.php'); $xhtml_renderer = new Doku_Renderer_xhtml(); echo '</p><ul class="newslist">'; foreach( $TEMPLATECOMMAND_SOURCE->getHtmlRecords() as $rec_num => $record ) { if( (!isset($record['start']) || strtotime($record['start']) < time()) && (!isset($record['stop']) || strtotime($record['stop']) > time()) ) { //format start timestamp if( !isset($record['start']) ) { $date = ''; } else { $date = "Submitted on " . date('d.m.', strtotime($record['start'])) . " ... "; } $params = $TEMPLATECOMMAND_SOURCE->getParamHash(); $page = wl( (isset($params['indexpage']) ? $params['indexpage'] : 'news:news') ); $link = $page.'#'.$xhtml_renderer->_headerToLink($record['head']); echo '<li class="newslist"><b><a class="wikilink1" href="' . $link . '">' . $record['head'] . '</a></b>'."\n"; $preview_length = ( isset($params['previewlength']) ? $params['previewlength'] : 200 ); $preview_string = substr( trim( preg_replace ('/\<.*?\>/', ' ', $record['text'] ) ), 0, $preview_length ); echo '<div class="news_preview">' . $preview_string . ' ... <br /> (<span class="newsdate">' . $date . '</span> <a class="wikilink1" href="' . $link . '">to full article</a>)</div>'; echo "</li>\n"; # echo ' * [["'.$link.'#'.$record['head'].'|' . $record['head'] . ']] ' . $date . "\n"; } } echo "</ul><p>"; ?>
news.css
li.newslist { padding-bottom:1ex; } .news_preview { font-size:90%; line-height:115%; color:__darker__; margin:0; padding:0; } .newsdate { font-size:90%; color:__darkgray__; } div.listabocheck { # display:inline; border:1px dotted __dark__; background-color:__light__; margin-bottom:1em; }
I like the word «stuff», or didn't you notice?
I notice that.
Thank you very much for your recipe.
No problem