1<?php
2/**
3 * Tag Plugin: displays list of keywords with links to categories this page
4 * belongs to. The links are marked as tags for Technorati and other services
5 * using tagging.
6 *
7 * Usage: {{tag>category tags space separated}}
8 *
9 * @license  GPL 2 (http://www.gnu.org/licenses/gpl.html)
10 * @author   Matthias Schulte <dokuwiki@lupo49.de>
11 */
12
13/** Count syntax, allows to list tag counts */
14class syntax_plugin_tag_count extends DokuWiki_Syntax_Plugin {
15
16    /**
17     * @return string Syntax type
18     */
19    function getType() { return 'substition'; }
20    /**
21     * @return int Sort order
22     */
23    function getSort() { return 305; }
24    /**
25     * @return string Paragraph type
26     */
27    function getPType() { return 'block';}
28
29    /**
30     * @param string $mode Parser mode
31     */
32    function connectTo($mode) {
33        $this->Lexer->addSpecialPattern('\{\{count>.*?\}\}', $mode, 'plugin_tag_count');
34    }
35
36    /**
37     * Handle matches of the count syntax
38     *
39     * @param string $match The match of the syntax
40     * @param int    $state The state of the handler
41     * @param int    $pos The position in the document
42     * @param Doku_Handler    $handler The handler
43     * @return array|false Data for the renderer
44     */
45    function handle($match, $state, $pos, Doku_Handler $handler) {
46
47        $match = trim(substr($match, 8, -2));     // get given tags
48        [$tags, $nsstring] = array_pad(explode('&', $match,2),2,'');             // split to tags and allowed namespaces
49        $allowedNamespaces = explode(' ', $nsstring); // split given namespaces into an array
50
51        if($allowedNamespaces && $allowedNamespaces[0] == '') {
52            unset($allowedNamespaces[0]);    // When exists, remove leading space after the delimiter
53            $allowedNamespaces = array_values($allowedNamespaces);
54        }
55
56        if (empty($allowedNamespaces)) {
57            $allowedNamespaces = null;
58        }
59
60        if (!$tags) {
61            $tags = '+';
62        }
63
64        /** @var helper_plugin_tag $helper */
65        if(!($helper = $this->loadHelper('tag'))) {
66            return false;
67        }
68
69        return [
70            $helper->parseTagList($tags),
71            $allowedNamespaces
72        ];
73    }
74
75    /**
76     * Render xhtml output or metadata
77     *
78     * @param string         $format      Renderer mode (supported modes: xhtml and metadata)
79     * @param Doku_Renderer  $renderer  The renderer
80     * @param array          $data      The data from the handler function
81     * @return bool If rendering was successful.
82     */
83    function render($format, Doku_Renderer $renderer, $data) {
84        if ($data === false) return false;
85
86        list($tags, $allowedNamespaces) = $data;
87
88        // deactivate (renderer) cache as long as there is no proper cache handling
89        // implemented for the count syntax
90        $renderer->nocache();
91
92        if($format == "xhtml") {
93            /** @var helper_plugin_tag $helper */
94            if(!($helper = $this->loadHelper('tag'))) return false;
95
96            // get tags and their occurrences
97            if($tags[0] == '+') {
98                // no tags given, list all tags for allowed namespaces
99                $occurrences = $helper->tagOccurrences($tags, $allowedNamespaces, true);
100            } else {
101                $occurrences = $helper->tagOccurrences($tags, $allowedNamespaces);
102            }
103
104            $class = "inline"; // valid: inline, ul, pagelist
105            $col = "page";
106
107            $renderer->doc .= '<table class="'.$class.'">';
108            $renderer->doc .= '<tr>';
109            $renderer->doc .= '<th class="'.$col.'">'.$this->getLang('tag').'</th>';
110            $renderer->doc .= '<th class="'.$col.'">'.$this->getLang('count').'</th>';
111            $renderer->doc .= '</tr>';
112
113            if(empty($occurrences)) {
114                // Skip output
115                $renderer->doc .= '<tr>';
116                $renderer->doc .= '<td class="'.$class.'" colspan="2">'.$this->getLang('empty_output').'</td>';
117                $renderer->doc .= '</tr>';
118            } else {
119                foreach($occurrences as $tagname => $count) {
120                    if($count <= 0) continue; // don't display tags with zero occurrences
121
122                    $renderer->doc .= '<tr>';
123                    $renderer->doc .= '<td class="'.$class.'">'.$helper->tagLink($tagname).'</td>';
124                    $renderer->doc .= '<td class="'.$class.'">'.$count.'</td>';
125                    $renderer->doc .= '</tr>';
126                }
127            }
128            $renderer->doc .= '</table>';
129        }
130        return true;
131    }
132}
133