Based on this a plugin was developed ⇒ a NEWS System.
This is a recipe to include a news system in DokuWiki. You'll get a form to write news articles. You'll get one summary page, where the headlines and the first few lines of text will show up. You'll get one complete page, where all news articles are listed. Articles are tagged and displayed with a publishing date, and may have a perishing date. That means, while writing an article, you could say that the article should disappear in, oh, let's say two weeks.
You may want to take a look at this stuff at work.
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.
You've got an „active template directory“ in your dokuwiki installation. In my installation, it's in /var/www/dokuwiki/lib/tpl/mytemplate/
. Go there.
Download and unpack one of the following archives there (or copy&paste them from far below on this page):
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
Edit your style.ini
. This here is just an excerpt, you'll have to add the line with news.css
in the section [stylesheets]
:
[stylesheets] layout.css = screen design.css = screen style.css = screen news.css = screen
After everything works, you'll just have to edit news.css
to get some sensible design matching your template. Maybe you'll want to edit the .php files too to get button text and error messages in your language.
You'll have to create a page with the following content. Let's assume you saved it as newstemplate
.
* targetpage: newsdata * head: 40| |Headline * start: 10|date(now)|Publishing date (first appearance of the article in the list) * stop: 10|date(2 weeks)|Perishing date (on this day the article will disappear) * text: 50*5| |Your article ----
This form definition will be interpreted by datainput.php
, which outputs an HTML input form following this definition and saves the submitted form data in a data page. To invoke datainput.php
, see step two.
This section may be skipped. It just contains some useful background information.
You'll see the syntax of one line of the „template“ right away:
* fieldname: fieldvalue
The fieldname is an arbitrary word at this point. It is used by datainput.php
to name the form fields in HTML. After submitting the form, datainput.php
saves the input on the wikipage denoted by the special field targetpage
, using the fieldnames „invented“ here. Another PHP script has to be written to actually interpret the dataset. E.g., the submission of the form generated by the definition above will result in the following dataset on the page newsdata
:
* head: Article Headline * start: 2007-12-12 * stop: 2007-12-24 * text: Sim salabim bam basela dusela dim. ----
Each form submission will be put on top of the existing datasets (that means: even if you make a typo in the targetpage
field, the operation is non-destructive – it just adds some data, never deletes any). The only way to edit or delete datasets is to manually edit the wikipage.
The field's value (i.e. the size/type definiton of the form fields) could be divided into:
Size | Default | Headline
… and 'Size' may be a lone integer (for one-lined text input) or something like X*Y
(columns times rows of a multi-line input field). It may also be hidden
(you'll need this in the case where multiple forms write to one datapage, but you want to distinct in the handling code between these forms … simply create multiple form templates, all with the same targetpage
, but with different values in a hidden field).
The 'Default' part is an arbitrary text, but may include the date()
function, which really just calls the PHP date() function and uses its output as default. In this example, the news articles will disappear 2 weeks after they were written, if the article author does not input another date.
'Headline' is the text which describes the input field. It will be displayed next to the corresponding input field on the page.
Therefore, datainput.php
gives you a generic, configurable input form generator for your wiki. It outputs data pages in the syntax required by the template extension to the command plugin. You could create input forms for arbitrary data sets – the only thing missing is the PHP code to actually display the data in your wiki. See the template extension for hints on how to do that – for this recipe, newslist.php
and newsdata.php
contain the „display code“, i.e. each one implements a different view on the saved datasets. See below on how to use these.
This command just takes the above created data page, interprets it and generates a form out of it:
#template(datainput.php|newstemplate)#
It is good practice to write step four below that on the same wiki page, so after submitting you'll see the reassuring effects of the form.
Complete suggestion for the news article input page (page writenews
):
====== Write new news ====== **[ [[news|all news]] | [[writenews|write news]] | [[newsdata|edit news]] ]** #template(datainput.php|newstemplate)# #template(newsitems.php|newsdata)#
Put this stuff somewhere into the start page of your wiki or whereever you like. I'd suggest putting a box around it
%template?previewlength=120&indexpage=news:news(newslist.php|newsdata)% **[ [[news:news|all news]] | [[news:writenews|write news]] | [[data:newsdata|edit news]] ]**
Shows a preview of news in a data page (in this case from the page newsdata
with a preview text length of 120 chars). The second line is just for convenience (access all news-related pages from there).
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.
You'll have to do that by hand. Don't worry, just open your data page and edit it. The format of the data page should explain itself. Mostly you will just correct some minor details, I expect, so I did not write a script to edit the stuff.
~~NOCACHE~~
on some pages.There are some reserved words among the field names, but not all of them are reserved by the same .php file.
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.
Here the field names start
, stop
, head
and text
are reserved. Any other field in the data page will be ignored.
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).
<? /** * 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/tips: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 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/tips: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 template extension * * Displays a preview of news articles. * * @link http://www.dokuwiki.org/tips: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>"; ?>
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