DokuWiki

It's better when it's simple

Инструменты пользователя

Инструменты сайта


ru:tips:newssystem

Руководство по включению системы новостей в 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.

Требования

  • DokuWiki (тестировалось с версией 2006-03-09b, 2006-11-06 и 2007-06-26b)
  • Command плагин для Докувики
  • Template расширение для плагина command

Дополнение шаблона Вашего сайта

Надо перейти в каталог с активным шаблоном Докувики . В моей установке это каталог /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 ;-)
ru/tips/newssystem.txt · Последнее изменение: 2011-01-18 16:08 — 89.18.130.241

Если не указано иное, содержимое этой вики предоставляется на условиях следующей лицензии: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki