1<?php
2/**
3 * DokuWiki Plugin ajax (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  i-net software <tools@inetsoftware.de>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12class action_plugin_tagsections_ajax extends DokuWiki_Action_Plugin {
13
14    private $inited = null;
15
16    /**
17     * Registers a callback function for a given event
18     *
19     * @param Doku_Event_Handler $controller DokuWiki's event controller object
20     * @return void
21     */
22    public function register(Doku_Event_Handler $controller) {
23       $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call');
24    }
25
26    /**
27     * [Custom event handler which performs action]
28     *
29     * @param Doku_Event $event  event object by reference
30     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
31     *                           handler was registered]
32     * @return void
33     */
34
35    public function handle_ajax_call(Doku_Event &$event, $param) {
36
37        global $INPUT, $ID, $INFO, $ACT;
38
39        if ( $event->data != 'tagsections' ) return false;
40
41        if ((!$filter = $this->loadHelper('tagsections'))) return false;
42        $event->preventDefault();
43
44        $result = array();
45        $ID = getID();
46        $range = $INPUT->str('range');
47        $ns = $INPUT->str('ns');
48
49        if ( $INPUT->has('contentOfPage') ) {
50            $ACT = 'show';
51            $INFO = pageinfo();
52            return tpl_content();
53        }
54
55        if ( $INPUT->has('saveTags') ) {
56            return $this->__saveTags($INPUT->arr('tags'), $range);
57        }
58
59        if ( $INPUT->has('listOfPages') ) {
60            $result['listOfPages'] = $this->__namespace_tree($ns);
61        }
62
63
64        if ( $INPUT->has('availableTags') ) {
65            // Lets just use all tags for now.
66            $availableTags = $filter->getTagsByNamespace('');
67            $result['availableTags'] = $filter->categorysizeTags($availableTags);
68        }
69
70        if ( $INPUT->has('tagsForSection') ) {
71            $tagsForSection = $this->__getTagsForSection($filter, $range);
72            $result['tagsForSection'] = $filter->categorysizeTags($tagsForSection);
73        }
74
75        echo json_encode($result);
76    }
77
78    private function __getTagsForSection($filter, $RANGE) {
79        global  $ID;
80
81        if ($RANGE) {
82            list($PRE,$TEXT,$SUF) = rawWikiSlices($RANGE,$ID);
83
84            // Render for tags
85            $instructions = p_get_instructions($TEXT);
86            $renderer = new Doku_Renderer_metadata();
87
88            // loop through the instructions
89            foreach ($instructions as $instruction){
90                // execute the callback against the renderer
91                call_user_func_array(array(&$renderer, $instruction[0]), (array) $instruction[1]);
92            }
93
94            // Return subject Tags
95            return $renderer->meta['subject'];
96
97        } else {
98            return $filter->getTagsBySiteID($ID);
99        }
100    }
101
102    private function __namespace_tree($ns) {
103        global $conf;
104
105
106        $ns_dir  = utf8_encodeFN(str_replace(':','/',$ns));
107
108        $data = array();
109        search($data,$conf['datadir'],'search_index',array('ns' => $ns_dir));
110
111        // insert the current ns into the hierarchy if it isn't already part of it
112        $ns_parts = explode(':', $ns);
113        $tmp_ns = '';
114        $pos = 0;
115        foreach ($ns_parts as $level => $part) {
116            if ($tmp_ns) $tmp_ns .= ':'.$part;
117            else $tmp_ns = $part;
118
119            // find the namespace parts or insert them
120            while ($data[$pos]['id'] != $tmp_ns) {
121                if ($pos >= count($data) || ($data[$pos]['level'] <= $level+1 && strnatcmp(utf8_encodeFN($data[$pos]['id']), utf8_encodeFN($tmp_ns)) > 0)) {
122                    array_splice($data, $pos, 0, array(array('level' => $level+1, 'id' => $tmp_ns, 'open' => 'true')));
123                    break;
124                }
125                ++$pos;
126            }
127        }
128
129        // return $data;
130        return html_buildlist($data,'idx','media_nstree_item','media_nstree_li');
131    }
132
133    private function __saveTags($tags, $RANGE) {
134        global $ID, $PRE, $TEXT, $SUF;
135
136        list($PRE,$TEXT,$SUF) = rawWikiSlices($RANGE,$ID);
137
138        $newTags = '';
139        if ( is_array($tags) && !empty($tags) ) {
140            $newTags = "\n\n".'{{tag>' . implode(' ', $tags) . '}}';
141        }
142
143        $reg = '/([ \n\t]*{{tag>.*?}})/s';
144        if ( preg_match($reg, $TEXT) ) {
145            // Put tags in TEXT
146            $TEXT = preg_replace($reg, $newTags, $TEXT);
147        } else {
148
149            $reg = '/([ \t]*={2,}[^\n]+={2,}[ \t]*(?=\n))/';
150            if ( $this->getConf('tagsAfterHeading') == 1 && preg_match($reg, $TEXT) ) {
151                // Not yet there. At the beginning.
152                $TEXT = preg_replace($reg, "$1" . $newTags, $TEXT);
153            } else {
154                // Not yet there. Add at the end.
155                $TEXT .= $newTags;
156            }
157        }
158
159        //save it
160        saveWikiText($ID,con($PRE,$TEXT,$SUF,true),'Update tags using tagsections in range ' . $range, true); //use pretty mode for con
161        //unlock it
162        unlock($ID);
163    }
164}
165
166// vim:ts=4:sw=4:et:
167