1<?php
2
3// must be run within Dokuwiki
4if ( !defined( 'DOKU_INC' ) ) die();
5
6if ( !defined( 'DOKU_PLUGIN' ) ) define( 'DOKU_PLUGIN', DOKU_INC . 'lib/plugins/' );
7
8require_once( DOKU_PLUGIN . 'action.php' );
9
10class action_plugin_tagentry extends DokuWiki_Action_Plugin {
11
12    /**
13     * register the eventhandlers
14     */
15	public function register(Doku_Event_Handler $controller) {
16        // hook
17        $controller->register_hook(
18            'HTML_EDITFORM_OUTPUT', 'BEFORE', $this,
19            'handle_editform_output'
20        );
21    }
22
23    /**
24     * Create the additional fields for the edit form.
25     */
26    function handle_editform_output( &$event, $param ) {
27        $pos = $event->data->findElementByAttribute( 'type', 'submit' );
28        if ( !$pos ){ return; }
29        $prefixHidden = empty( $event->data->_hidden['prefix'] );
30        $suffixHidden = empty( $event->data->_hidden['suffix'] );
31        if ( $prefixHidden || ! $suffixHidden ){
32            return;
33        }
34        // get all tags
35        $tagns = $this->getConf( 'namespace' );
36        if ( $thlp =& plugin_load( 'helper', 'tag' ) ) {
37            if ( $this->getConf( 'tagsrc' ) == 'Pagenames in tag NS' ) {
38                $tagnst = $thlp->getConf( 'namespace' );
39                if ( !empty( $tagnst ) )
40                    $tagns = $tagnst;
41            }
42        }
43        if ( $this->getConf( 'tagsrc' ) == 'All tags' && $thlp ) {
44            $alltags = array_map( 'trim', idx_getIndex( 'subject', '_w' ) );
45        } else {
46            $alltags = $this->_getpages( $tagns );
47        }
48
49        // get already assigned tags for this page
50        $assigned = false;
51        if ( 1 ) { // parse wiki-text to pick up tags for draft/prevew
52            $wikipage = '';
53            $wt = $event->data->findElementByType( 'wikitext' );
54            if ( $wt !== false ) {
55                $wikipage = $event->data->_content[$wt]['_text'];
56            }
57            if ( !empty( $wikipage ) ){
58                if ( preg_match( '@\{\{tag>(.*?)\}\}@', $wikipage, $m ) ) {
59                    $assigned = explode( ' ', $m[1] );
60                }
61            }
62        }
63        if ( !is_array( $assigned ) ) {
64            // those are from the prev. saved version.
65            global $ID;
66            $meta     = array();
67            $meta     = p_get_metadata( $ID );
68            $assigned = $meta['subject'];
69        }
70        $options = array(
71            'blacklist' => explode( ' ', $this->getConf( 'blacklist' ) ),
72            'assigned' => $assigned,
73        );
74        $out = '<div id="plugin__tagentry_wrapper">';
75        $out .= $this->_format_tags( $alltags, $options );
76        $out .= '</div>';
77        $event->data->insertElement( $pos++, $out );
78    }
79
80    /**
81     * callback function for dokuwiki search()
82     *
83     * Build a list of tags from the tag namespace
84     * $opts['ns'] is the namespace to browse
85     */
86    function _tagentry_search_tagpages( &$data, $base, $file, $type, $lvl, $opts ) {
87        $return = true;
88        $item   = array();
89        if ( $type == 'd' ) {
90            // TODO: check if namespace mismatch -> break recursion early.
91            return true;
92        } elseif ( $type == 'f' && !preg_match( '#\.txt$#', $file ) ) {
93            return false;
94        }
95        $id = pathID( $file );
96        if ( getNS( $id ) != $opts['ns'] )
97            return false;
98        if ( isHiddenPage( $id ) ) {
99            return false;
100        }
101        if ( $type == 'f' && auth_quickaclcheck( $id ) < AUTH_READ ) {
102            return false;
103        }
104        $data[] = noNS( $id );
105        return $return;
106    }
107
108    /**
109     * list all tags from the topic index.
110     * (requires newer version of the tag plugin)
111     *
112     * @param $thlp  pointer to tag plugin's helper
113     * @return array list of tag names, sorted by frequency
114     */
115    function _gettags( &$thlp ) {
116        $data = array();
117        if ( !is_array( $thlp->topic_idx ) )
118            return $data;
119        foreach ( $thlp->topic_idx as $k => $v ) {
120            if ( !is_array( $v ) || empty( $v ) || ( !trim( $v[0] ) ) )
121                continue;
122            $data[$k] = count( $v );
123        }
124        arsort( $data );
125        return ( array_keys( $data ) );
126    }
127
128    /**
129     * list all pages in the namespace.
130     *
131     * @param $tagns namespace to search.
132     * @return array list of tag names.
133     */
134    function _getpages( $tagns = 'wiki:tags' ) {
135        global $conf;
136        require_once( DOKU_INC . 'inc/search.php' );
137        $data = array();
138        search( $data, $conf['datadir'], array(
139             $this,
140            '_tagentry_search_tagpages'
141        ), array(
142             'ns' => $tagns
143        ) );
144        return ( $data );
145    }
146
147    function clipstring( $s, $len = 22 ) {
148        return substr( $s, 0, $len ) . ( ( strlen( $s ) > $len ) ? '..' : '' );
149    }
150
151    function escapeJSstring( $o ) {
152        return ( // TODO: use JSON ?!
153            str_replace( "\n", '\\n', str_replace( "\r", '', str_replace( '\'', '\\\'', str_replace( '\\', '\\\\', $o ) ) ) ) );
154    }
155
156    /** case insenstive in_array();.
157     */
158    function in_iarray( $needle, $haystack ) {
159        if ( !is_array( $haystack ) )
160            return false;
161        foreach ( $haystack as $t ) {
162            if ( strcasecmp( $needle, $t ) == 0 )
163                return true;
164        }
165        return false;
166    }
167
168    /**
169     * render and return the tag-select box.
170     *
171     * @param $alltags array of tags to display.
172     * @param $options array
173     * @return string XHTML form.
174     */
175    function _format_tags( $alltags, $options ) {
176        $rv = '';
177        if ( !is_array( $alltags ) ){ return $rv; }
178        if ( count( $alltags ) < 1 ){ return $rv; }
179        //$rv .= '<div>';
180        //$rv .= ' <div><label>' . $this->getLang( 'assign' ) . '</label></div>';
181        $rv .= '<div class="taglist"' . $dstyle . '>';
182        //$rv .= '<div>';
183
184        // Trie les tags
185        natcasesort( $alltags );
186
187        // Boucle sur les tags
188        $i = 0;
189        foreach ( $alltags as $tagname ) {
190
191            // Blacklist
192            $hasBlacklist = is_array( $options['blacklist'] );
193            $inBlacklist = $this->in_iarray( $tagname, $options['blacklist'] );
194
195            if ( $hasBlacklist && $inBlacklist ){ continue; }
196
197            $i++;
198
199            $rv .= '<label><input type="checkbox" id="plugin__tagentry_cb' . $tagname . '"';
200            $rv .= ' value="1" name="' . $tagname . '"';
201            if ( $this->in_iarray( $tagname, $options['assigned'] ) ){
202                $rv .= ' checked="checked"';
203            }
204
205            $rv .= ' onclick="tagentry_clicktag(\'' . $this->escapeJSstring( $tagname ) . '\', this);"';
206
207            // MODIF : 23/12/2013 14:43:26
208            $rv .= ' /> ' . $this->_getTagTitle( $tagname )  ;
209            $rv .= '</label>';
210            //$rv.=' /> '.$this->clipstring($tagname).'</label>&nbsp;';
211            // MODIF : 23/12/2013 14:43:26
212
213
214            $rv .= "\n";
215        }
216
217        //$rv .= '</div>';
218        //$rv .= '</div>';
219        return ( $rv );
220    }
221
222    // MODIF : 23/12/2013 14:55:07
223    /**
224     * Return Header title or tag name
225     * @param $tagname The name of tag without namespace
226     * @return Title of the tag page or tag name formatted
227     */
228    function _getTagTitle( $tagname ) {
229        global $conf;
230        if ( $conf['useheading'] ) {
231            $tagplugin = plugin_load( 'helper', 'tag' );
232            if ( plugin_isdisabled( 'tag' ) || !$tagplugin ) {
233                msg( 'The Tag Plugin must be installed to display tagentry.', -1 );
234                return $this->clipstring( $tagname );
235            }
236
237            $id    = $tagname;
238            $exist = false;
239            resolve_pageID( $tagplugin->namespace, $id, $exist );
240            if ( $exist ) {
241                return p_get_first_heading( $id, false );
242            }
243        }
244        return $this->clipstring( $tagname );
245    }
246    // MODIF : 23/12/2013 14:55:07
247}
248