1<?php
2/**
3 * Blog Plugin: displays a number of recent entries from the blog subnamespace
4 *
5 * @license  GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author   Esther Brunner <wikidesign@gmail.com>
7 * @author   Robert Rackl <wiki@doogie.de>
8 */
9
10class syntax_plugin_blog_blog extends DokuWiki_Syntax_Plugin {
11    private $included_pages = array();
12
13    function getType() { return 'substition'; }
14    function getPType() { return 'block'; }
15    function getSort() { return 307; }
16
17    function connectTo($mode) {
18        $this->Lexer->addSpecialPattern('\{\{blog>.*?\}\}',$mode,'plugin_blog_blog');
19    }
20
21    function handle($match, $state, $pos, Doku_Handler $handler) {
22        global $ID;
23
24        $match = substr($match, 7, -2); // strip {{blog> from start and }} from end
25        list($match, $flags) = explode('&', $match, 2);
26        $flags =  explode('&', $flags);
27        array_unshift($flags, 'link'); // always make the first header of a blog entry a permalink (unless nolink is set)
28        list($match, $refine) = explode(' ', $match, 2);
29        list($ns, $num) = explode('?', $match, 2);
30
31        if (!is_numeric($num)) {
32            if (is_numeric($ns)) {
33                $num = $ns;
34                $ns  = '';
35            } else {
36                $num = 5;
37            }
38        }
39
40        if ($ns == '') $ns = cleanID($this->getConf('namespace'));
41        elseif (($ns == '*') || ($ns == ':')) $ns = '';
42        elseif ($ns == '.') $ns = getNS($ID);
43        else $ns = cleanID($ns);
44
45        return array($ns, $num, $flags, $refine);
46    }
47
48    function render($mode, Doku_Renderer $renderer, $data) {
49        list($ns, $num, $flags, $refine) = $data;
50
51        $first = $_REQUEST['first'];
52        if (!is_numeric($first)) $first = 0;
53
54        // get the blog entries for our namespace
55        /** @var helper_plugin_blog $my */
56        if ($my = plugin_load('helper', 'blog')) $entries = $my->getBlog($ns);
57        else return false;
58
59        // use tag refinements?
60        if ($refine) {
61            /** @var helper_plugin_tag $tag */
62            if (plugin_isdisabled('tag') || (!$tag = plugin_load('helper', 'tag'))) {
63                msg($this->getLang('missing_tagplugin'), -1);
64            } else {
65                $entries = $tag->tagRefine($entries, $refine);
66            }
67        }
68
69        // Normalise flags
70        $blog_flags     = $my->getFlags($flags);
71        $formpos        = $blog_flags['formpos'];
72        $newentrytitle  = $blog_flags['newentrytitle'];
73        $pagingcontrols = $blog_flags['pagingcontrols'];
74
75        if ($mode == 'xhtml') {
76            // prevent caching to ensure the included pages are always fresh
77            $renderer->nocache();
78        }
79
80        if (!$entries) {
81            if ((auth_quickaclcheck($ns.':*') >= AUTH_CREATE) && ($mode == 'xhtml')) {
82                if($formpos != 'none') $renderer->doc .= $this->_newEntryForm($ns, $newentrytitle);
83            }
84            return true; // nothing to display
85        }
86
87        // slice the needed chunk of pages
88        $isMore = count($entries) > ($first + $num);
89        $entries = array_slice($entries, $first, $num);
90
91        // load the include helper plugin
92        /** @var helper_plugin_include $include */
93        if (plugin_isdisabled('include') || (!$include = plugin_load('helper', 'include'))) {
94            msg($this->getLang('missing_includeplugin'), -1);
95            return false;
96        }
97
98        // current section level
99        $clevel = 0;
100
101        $perm_create = (auth_quickaclcheck($ns.':*') >= AUTH_CREATE);
102        $include_flags = $include->get_flags($flags);
103
104        if ($mode == 'xhtml') {
105            // show new entry form
106            if ($perm_create && $formpos == 'top') {
107                $renderer->doc .= $this->_newEntryForm($ns, $newentrytitle);
108            }
109
110            // get current section level
111            preg_match_all('|<div class="level(\d)">|i', $renderer->doc, $matches, PREG_SET_ORDER);
112            $n = count($matches)-1;
113            if ($n > -1) $clevel = $matches[$n][1];
114
115            // close current section
116            if ($clevel && !$include_flags['inline']) $renderer->doc .= '</div>'.DOKU_LF;
117            $renderer->doc .= '<div class="hfeed">'.DOKU_LF;
118        }
119
120
121        // now include the blog entries
122        foreach ($entries as $entry) {
123            if ($mode == 'xhtml' || $mode == 'code') {
124                if(auth_quickaclcheck($entry['id']) >= AUTH_READ) {
125                    // prevent blog include loops
126                    if(!$this->included_pages[$entry['id']]) {
127                        $this->included_pages[$entry['id']] = true;
128                        $renderer->nest($include->_get_instructions($entry['id'], '', 'page', $clevel, $include_flags));
129                        $this->included_pages[$entry['id']] = false;
130                    }
131                }
132            } elseif ($mode == 'metadata') {
133                /** @var Doku_Renderer_metadata $renderer */
134                $renderer->meta['relation']['haspart'][$entry['id']] = true;
135            }
136        }
137
138        if ($mode == 'xhtml') {
139            // resume the section
140            $renderer->doc .= '</div>'.DOKU_LF;
141            if ($clevel && !$include_flags['inline']) $renderer->doc .= '<div class="level'.$clevel.'">'.DOKU_LF;
142
143            // show older / newer entries links
144            if ($pagingcontrols) $renderer->doc .= $this->_browseEntriesLinks($isMore, $first, $num);
145
146            // show new entry form
147            if ($perm_create && $formpos == 'bottom') {
148                $renderer->doc .= $this->_newEntryForm($ns, $newentrytitle);
149            }
150        }
151
152        return in_array($mode, array('xhtml', 'metadata', 'code'));
153    }
154
155    /* ---------- (X)HTML Output Functions ---------- */
156
157    /**
158     * Displays links to older newer entries of the blog namespace
159     *
160     * @param $more
161     * @param $first
162     * @param $num
163     * @return string
164     */
165    function _browseEntriesLinks($more, $first, $num) {
166        global $ID;
167
168        $ret = '';
169        $last = $first+$num;
170        if ($first > 0) {
171            $first -= $num;
172            if ($first < 0) $first = 0;
173            $ret .= '<p class="centeralign">'.DOKU_LF.'<a href="'.wl($ID, 'first='.$first).'"'.
174                ' class="wikilink1">&lt;&lt; '.$this->getLang('newer').'</a>';
175            if ($more) $ret .= ' | ';
176            else $ret .= '</p>';
177        } else if ($more) {
178            $ret .= '<p class="centeralign">'.DOKU_LF;
179        }
180        if ($more) {
181            $ret .= '<a href="'.wl($ID, 'first='.$last).'" class="wikilink1">'.
182                $this->getLang('older').' &gt;&gt;</a>'.DOKU_LF.'</p>'.DOKU_LF;
183        }
184        return $ret;
185    }
186
187    /**
188     * Displays a form to enter the title of a new entry in the blog namespace
189     * and then open that page in the edit mode
190     *
191     * @param $ns
192     * @param $newentrytitle
193     * @return string
194     */
195    function _newEntryForm($ns, $newentrytitle) {
196        global $lang;
197        global $ID;
198
199        return '<div class="newentry_form">'.DOKU_LF.
200            '<form id="blog__newentry_form" method="post" action="'.script().'" accept-charset="'.$lang['encoding'].'">'.DOKU_LF.
201            DOKU_TAB.'<fieldset>'.DOKU_LF.
202            DOKU_TAB.DOKU_TAB.'<legend>'.hsc($newentrytitle).'</legend>'.DOKU_LF.
203            DOKU_TAB.DOKU_TAB.'<input type="hidden" name="id" value="'.$ID.'" />'.DOKU_LF.
204            DOKU_TAB.DOKU_TAB.'<input type="hidden" name="do" value="newentry" />'.DOKU_LF.
205            DOKU_TAB.DOKU_TAB.'<input type="hidden" name="ns" value="'.$ns.'" />'.DOKU_LF.
206            DOKU_TAB.DOKU_TAB.'<input class="edit" type="text" name="title" id="blog__newentry_title" size="40" tabindex="1" />'.DOKU_LF.
207            DOKU_TAB.DOKU_TAB.'<input class="button" type="submit" value="'.$lang['btn_create'].'" tabindex="2" />'.DOKU_LF.
208            DOKU_TAB.'</fieldset>'.DOKU_LF.
209            '</form>'.DOKU_LF.
210            '</div>'.DOKU_LF;
211    }
212}
213// vim:ts=4:sw=4:et:enc=utf-8:
214