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) = array_pad(explode('&', $match, 2), 2, null);
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) = array_pad(explode(' ', $match, 2), 2, null);
29        list($ns, $num) = array_pad(explode('?', $match, 2), 2, null);
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        global $INPUT;
50
51        list($ns, $num, $flags, $refine) = $data;
52
53        $first = $INPUT->int('first');
54        if (!is_numeric($first)) $first = 0;
55
56        // get the blog entries for our namespace
57        /** @var helper_plugin_blog $my */
58        if ($my = plugin_load('helper', 'blog')) $entries = $my->getBlog($ns);
59        else return false;
60
61        // use tag refinements?
62        if ($refine) {
63            /** @var helper_plugin_tag $tag */
64            if (plugin_isdisabled('tag') || (!$tag = plugin_load('helper', 'tag'))) {
65                msg($this->getLang('missing_tagplugin'), -1);
66            } else {
67                $entries = $tag->tagRefine($entries, $refine);
68            }
69        }
70
71        // Normalise flags
72        $blog_flags     = $my->getFlags($flags);
73        $formpos        = $blog_flags['formpos'];
74        $newentrytitle  = $blog_flags['newentrytitle'];
75        $pagingcontrols = $blog_flags['pagingcontrols'];
76
77        if ($mode == 'xhtml') {
78            // prevent caching to ensure the included pages are always fresh
79            $renderer->nocache();
80        }
81
82        if (!$entries) {
83            if ((auth_quickaclcheck($ns.':*') >= AUTH_CREATE) && ($mode == 'xhtml')) {
84                if($formpos != 'none') $renderer->doc .= $this->_newEntryForm($ns, $newentrytitle);
85            }
86            return true; // nothing to display
87        }
88
89        // slice the needed chunk of pages
90        $isMore = count($entries) > ($first + $num);
91        $entries = array_slice($entries, $first, $num);
92
93        // load the include helper plugin
94        /** @var helper_plugin_include $include */
95        if (plugin_isdisabled('include') || (!$include = plugin_load('helper', 'include'))) {
96            msg($this->getLang('missing_includeplugin'), -1);
97            return false;
98        }
99
100        // current section level
101        $clevel = 0;
102
103        $perm_create = (auth_quickaclcheck($ns.':*') >= AUTH_CREATE);
104        $include_flags = $include->get_flags($flags);
105
106        if ($mode == 'xhtml') {
107            // show new entry form
108            if ($perm_create && $formpos == 'top') {
109                $renderer->doc .= $this->_newEntryForm($ns, $newentrytitle);
110            }
111
112            // get current section level
113            preg_match_all('|<div class="level(\d)">|i', $renderer->doc, $matches, PREG_SET_ORDER);
114            $n = count($matches)-1;
115            if ($n > -1) $clevel = $matches[$n][1];
116
117            // close current section
118            if ($clevel && !$include_flags['inline']) $renderer->doc .= '</div>'.DOKU_LF;
119            $renderer->doc .= '<div class="hfeed">'.DOKU_LF;
120        }
121
122
123        // now include the blog entries
124        foreach ($entries as $entry) {
125            if ($mode == 'xhtml' || $mode == 'code') {
126                if(isset($entry['id']) && (auth_quickaclcheck($entry['id']) >= AUTH_READ)) {
127                    // prevent blog include loops
128                    if(!array_key_exists($entry['id'], $this->included_pages) || !$this->included_pages[$entry['id']]) {
129                        $this->included_pages[$entry['id']] = true;
130                        $renderer->nest($include->_get_instructions($entry['id'], '', 'page', $clevel, $include_flags));
131                        $this->included_pages[$entry['id']] = false;
132                    }
133                }
134            } elseif ($mode == 'metadata') {
135                /** @var Doku_Renderer_metadata $renderer */
136                $renderer->meta['relation']['haspart'][$entry['id']] = true;
137            }
138        }
139
140        if ($mode == 'xhtml') {
141            // resume the section
142            $renderer->doc .= '</div>'.DOKU_LF;
143            if ($clevel && !$include_flags['inline']) $renderer->doc .= '<div class="level'.$clevel.'">'.DOKU_LF;
144
145            // show older / newer entries links
146            if ($pagingcontrols) $renderer->doc .= $this->_browseEntriesLinks($isMore, $first, $num);
147
148            // show new entry form
149            if ($perm_create && $formpos == 'bottom') {
150                $renderer->doc .= $this->_newEntryForm($ns, $newentrytitle);
151            }
152        }
153
154        return in_array($mode, array('xhtml', 'metadata', 'code'));
155    }
156
157    /* ---------- (X)HTML Output Functions ---------- */
158
159    /**
160     * Displays links to older newer entries of the blog namespace
161     *
162     * @param $more
163     * @param $first
164     * @param $num
165     * @return string
166     */
167    function _browseEntriesLinks($more, $first, $num) {
168        global $ID;
169
170        $ret = '';
171        $last = $first+$num;
172        if ($first > 0) {
173            $first -= $num;
174            if ($first < 0) $first = 0;
175            $ret .= '<p class="centeralign">'.DOKU_LF.'<a href="'.wl($ID, 'first='.$first).'"'.
176                ' class="wikilink1">&lt;&lt; '.$this->getLang('newer').'</a>';
177            if ($more) $ret .= ' | ';
178            else $ret .= '</p>';
179        } else if ($more) {
180            $ret .= '<p class="centeralign">'.DOKU_LF;
181        }
182        if ($more) {
183            $ret .= '<a href="'.wl($ID, 'first='.$last).'" class="wikilink1">'.
184                $this->getLang('older').' &gt;&gt;</a>'.DOKU_LF.'</p>'.DOKU_LF;
185        }
186        return $ret;
187    }
188
189    /**
190     * Displays a form to enter the title of a new entry in the blog namespace
191     * and then open that page in the edit mode
192     *
193     * @param $ns
194     * @param $newentrytitle
195     * @return string
196     */
197    function _newEntryForm($ns, $newentrytitle) {
198        global $lang;
199        global $ID;
200
201        return '<div class="newentry_form">'.DOKU_LF.
202            '<form id="blog__newentry_form" method="post" action="'.script().'" accept-charset="'.$lang['encoding'].'">'.DOKU_LF.
203            DOKU_TAB.'<fieldset>'.DOKU_LF.
204            DOKU_TAB.DOKU_TAB.'<legend>'.hsc($newentrytitle).'</legend>'.DOKU_LF.
205            DOKU_TAB.DOKU_TAB.'<input type="hidden" name="id" value="'.$ID.'" />'.DOKU_LF.
206            DOKU_TAB.DOKU_TAB.'<input type="hidden" name="do" value="newentry" />'.DOKU_LF.
207            DOKU_TAB.DOKU_TAB.'<input type="hidden" name="ns" value="'.$ns.'" />'.DOKU_LF.
208            DOKU_TAB.DOKU_TAB.'<input class="edit" type="text" name="title" id="blog__newentry_title" size="40" tabindex="1" />'.DOKU_LF.
209            DOKU_TAB.DOKU_TAB.'<input class="button" type="submit" value="'.$lang['btn_create'].'" tabindex="2" />'.DOKU_LF.
210            DOKU_TAB.'</fieldset>'.DOKU_LF.
211            '</form>'.DOKU_LF.
212            '</div>'.DOKU_LF;
213    }
214}
215// vim:ts=4:sw=4:et:enc=utf-8:
216