1<?php
2/**
3 * DokuWiki Action Plugin Feedmod
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Michael Klier <chi@chimeric.de>
7 */
8// must be run within Dokuwiki
9if(!defined('DOKU_INC')) die();
10
11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
12if(!defined('DOKU_LF')) define('DOKU_LF', "\n");
13
14require_once(DOKU_PLUGIN.'action.php');
15
16/**
17 * All DokuWiki plugins to extend the admin function
18 * need to inherit from this class
19 */
20class action_plugin_feedmod extends DokuWiki_Action_Plugin {
21
22    function getInfo() {
23        return array(
24                'author' => 'Gina Häußge, Michael Klier, Rainer Kaufmann',
25                'email'  => 'chi@chimeric.de',
26                'date'   => @file_get_contents(DOKU_PLUGIN.'feedmod/VERSION'),
27                'name'   => 'feedmod',
28                'desc'   => 'Modifies feed items for nicer full html feeds.',
29                'url'    => 'http://dokuwiki.org/plugin:feedmod'
30            );
31    }
32
33    // register hook
34    function register(Doku_Event_Handler $controller) {
35        $controller->register_hook('FEED_ITEM_ADD', 'BEFORE', $this, '_feedmod');
36    }
37
38    /**
39     * Removes the headline which is already set in the item title and adds a link
40     * to the discussion section if a discussion exists
41     *
42     * @author Michael Klier <chi@chimeric.de>
43     */
44    function _feedmod(&$event, $param) {
45        global $conf;
46        global $opt;    // options feed.php is called with
47
48        if($opt['item_content'] == 'html') {
49
50            // only act if were linking to the current version of the page
51            if($opt['link_to'] == 'current') {
52
53                $url = parse_url($event->data['item']->link);
54                $base_url = getBaseURL();
55
56                // determine page id by rewrite mode
57                switch($conf['userewrite']) {
58
59                    case 0:
60                        preg_match('#id=([^&]*)#', $url['query'], $match);
61                        if($base_url != '/') {
62                            $id = cleanID(str_replace($base_url, '', $match[1]));
63                        } else {
64                            $id = cleanID($match[1]);
65                        }
66                        break;
67
68                    case 1:
69                        if($base_url != '/') {
70                            $id = cleanID(str_replace('/',':',str_replace($base_url, '', $url['path'])));
71                        } else {
72                            $id = cleanID(str_replace('/',':', $url['path']));
73                        }
74                        break;
75
76                    case 2:
77                        preg_match('#doku.php/([^&]*)#', $url['path'], $match);
78                        if($base_url != '/') {
79                            $id = cleanID(str_replace($base_url, '', $match[1]));
80                        } else {
81                            $id = cleanID($match[1]);
82                        }
83                        break;
84                }
85
86                // don't add drafts to the feed
87                if(p_get_metadata($id, 'type') == 'draft') {
88                    $event->preventDefault();
89                    return;
90                }
91
92                // retrieve first heading from page instructions
93                $ins = p_cached_instructions(wikiFN($id));
94                $headers = array_filter($ins, array($this, '_filterHeaders'));
95                $headingIns = array_shift($headers);
96                $firstheading = $headingIns[1][0];
97
98                // strip first heading and replace item title
99                $event->data['item']->description = preg_replace('#[^\n]*?>\s*?' . preg_quote(hsc($firstheading), '#') . '\s*?<.*\n#', '', $event->data['item']->description, 1);
100                $event->data['item']->title = $firstheading;
101
102                // check for discussion file
103                if(@file_exists(metaFN($id, '.comments'))) {
104                    $clink  = '<span class="plugin_feedmod_comments">' . DOKU_LF;
105                    $clink .= '  <a href="' . $event->data['item']->link . '#discussion__section" title="'. $this->getLang('comments') . '">' . $this->getLang('comments') . '</a>' . DOKU_LF;
106                    $clink .= '</span>' . DOKU_LF;
107                    $event->data['item']->description .= $clink;
108                }
109
110                // check for file footer and append it
111                if(@file_exists(DOKU_PLUGIN.'feedmod/_footer.txt')) {
112                    $footer = file_get_contents(DOKU_PLUGIN.'feedmod/_footer.txt');
113                    $footer = str_replace('@URL@', $event->data['item']->link, $footer);
114                    $footer = str_replace('@PAGE@', $id, $footer);
115                    $footer = str_replace('@TITLE@', $event->data['item']->title, $footer);
116                    $footer = str_replace('@AUTHOR@', $event->data['item']->author, $footer);
117                    $event->data['item']->description .= $footer;
118                }
119            }
120        }
121    }
122
123    /**
124     * Returns true if $entry is a valid header instruction, false otherwise.
125     *
126     * @author Gina Häußge <osd@foosel.net>
127     */
128    function _filterHeaders($entry) {
129        // normal headers
130        if (is_array($entry) && $entry[0] == 'header' && count($entry) == 3 && is_array($entry[1]) && count($entry[1]) == 3)
131            return true;
132
133        // permalink headers from include plugin
134        if (is_array($entry) && $entry[0] == 'plugin' && is_array($entry[1]) && $entry[1][0] == 'include_header' && is_array($entry[1][1]) && count($entry[1][1]) == 2)
135            return true;
136
137        // no known header
138        return false;
139    }
140}
141
142// vim:ts=4:sw=4:et:enc=utf-8:
143