1<?php
2/**
3 * Feed Plugin: creates a feed link for a given blog namespace
4 *
5 * @license  GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author   Esther Brunner <wikidesign@gmail.com>
7 */
8
9/**
10 * Class syntax_plugin_feed
11 */
12class syntax_plugin_feed extends DokuWiki_Syntax_Plugin
13{
14
15    /**
16     * To support feeds in your plugin, add an array here
17     *
18     * The array key is important:
19     *   - $plugin->getLang($key) is used for the feed title
20     *   - and a function 'get'.$key (for example getTopic for 'topic') must exist in your helper.php!
21     *
22     * The first param should eigther be 'id' or 'ns' as it will go through cleanID()
23     *
24     * Unless the second parameter is 'num', your plugin will have to handle it on its own
25     */
26    protected function _registeredFeeds()
27    {
28        $feeds = array(
29            'blog' => array('plugin' => 'blog', 'params' => array('ns', 'num')),
30            'comments' => array('plugin' => 'discussion', 'params' => array('ns', 'num')),
31            'threads' => array('plugin' => 'discussion', 'params' => array('ns', 'num')),
32            'editor' => array('plugin' => 'editor', 'params' => array('ns', 'user')),
33            'topic' => array('plugin' => 'tag', 'params' => array('ns', 'tag')),
34            'tasks' => array('plugin' => 'task', 'params' => array('ns', 'filter')),
35        );
36        foreach ($feeds as $key => $value) {
37            if (!@file_exists(DOKU_PLUGIN . $value['plugin'] . '/helper.php')) {
38                unset($feeds[$key]);
39            }
40        }
41        return $feeds;
42    }
43
44    /**
45     * Syntax Type
46     *
47     * Needs to return one of the mode types defined in $PARSER_MODES in parser.php
48     *
49     * @return string
50     */
51    public function getType()
52    {
53        return 'substition';
54    }
55
56    /**
57     * Sort for applying this mode
58     *
59     * @return int
60     */
61    public function getSort()
62    {
63        return 308;
64    }
65
66    /**
67     * @param string $mode
68     */
69    public function connectTo($mode)
70    {
71        $this->Lexer->addSpecialPattern('\{\{\w+?feed>.+?\}\}', $mode, 'plugin_feed');
72    }
73
74    /**
75     * Handler to prepare matched data for the rendering process
76     *
77     * @param string $match The text matched by the patterns
78     * @param int $state The lexer state for the match
79     * @param int $pos The character position of the matched text
80     * @param Doku_Handler $handler The Doku_Handler object
81     * @return  array Return an array with all data you want to use in render
82     */
83    public function handle($match, $state, $pos, Doku_Handler $handler)
84    {
85        global $ID;
86
87        $match = substr($match, 2, -2); // strip markup
88        list($feed, $data) = explode('>', $match, 2);
89        $feed = substr($feed, 0, -4);
90        list($params, $title) = explode('|', $data, 2);
91        list($namespace, $parameter) = explode('?', $params, 2);
92
93        if (($namespace == '*') || ($namespace == ':')) {
94            $namespace = '';
95        } elseif ($namespace == '.') {
96            $namespace = getNS($ID);
97        } else {
98            $namespace = cleanID($namespace);
99        }
100
101        return array($feed, $namespace, trim($parameter), trim($title));
102    }
103
104    /**
105     * Handles the actual output creation.
106     *
107     * @param   $mode     string        output format being rendered
108     * @param   $renderer Doku_Renderer the current renderer object
109     * @param   $data     array         data created by handler()
110     * @return  boolean                 rendered correctly?
111     */
112    public function render($mode, Doku_Renderer $renderer, $data)
113    {
114        list($feed, $namespace, $parameter, $title) = $data;
115
116        $feeds = $this->_registeredFeeds();
117        if (!isset($feeds[$feed])) {
118            msg('Unknown plugin feed ' . hsc($feed) . '.', -1);
119            return false;
120        }
121
122        $plugin = $feeds[$feed]['plugin'];
123        if (plugin_isdisabled($plugin) || (!$po = plugin_load('helper', $plugin))) {
124            msg('Missing or invalid helper plugin for ' . hsc($feed) . '.', -1);
125            return false;
126        }
127
128        $fn = 'get' . ucwords($feed);
129
130        if (!$title) $title = ucwords(str_replace(array('_', ':'), array(' ', ': '), $namespace));
131        if (!$title) $title = ucwords(str_replace('_', ' ', $parameter));
132
133        if ($mode == 'xhtml') {
134            /** @var Doku_Renderer_xhtml $renderer */
135            $url = DOKU_BASE . 'lib/plugins/feed/feed.php?plugin=' . $plugin .
136                '&amp;fn=' . $fn .
137                '&amp;' . $feeds[$feed]['params'][0] . '=' . urlencode($namespace);
138            if ($parameter) {
139                $url .= '&amp;' . $feeds[$feed]['params'][1] . '=' . urlencode($parameter);
140            }
141            $url .= '&amp;title=' . urlencode($po->getLang($feed));
142
143            $title = hsc($title);
144            $renderer->doc .= '<a href="' . $url . '" class="feed" rel="nofollow"' .
145                ' type="application/rss+xml" title="' . $title . '">' . $title . '</a>';
146
147            return true;
148
149            // for metadata renderer
150        } elseif ($mode == 'metadata') {
151            /** @var Doku_Renderer_metadata $renderer */
152            if ($renderer->capture) {
153                $renderer->doc .= $title;
154            }
155
156            return true;
157        }
158        return false;
159    }
160}
161