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   Esther Brunner <wikidesign@gmail.com>
11 */
12
13// must be run within Dokuwiki
14if (!defined('DOKU_INC')) die();
15
16if (!defined('DOKU_LF')) define('DOKU_LF', "\n");
17if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t");
18if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
19
20if ( class_exists('syntax_plugin_tag_tag') ) {
21
22    /**
23     * Tag syntax plugin, allows to specify tags in a page
24     */
25    class syntax_plugin_tagsections_tag extends syntax_plugin_tag_tag {
26
27        function __construct() {
28            if (plugin_isdisabled('tag') || (!$this->Htag = plugin_load('helper', 'tag'))) {
29                msg('tag plugin is required by tagsections plugin, but missing', -1);
30                return false;
31            }
32        }
33
34        /**
35         * @return string Syntax type
36         */
37        function getType() { return 'baseonly'; }
38        /**
39         * @return int Sort order
40         */
41        function getSort() { return 300; }
42
43        /**
44         * @param string $mode Parser mode
45         */
46        function connectTo($mode) {
47            $this->Lexer->addSpecialPattern('\{\{tag>.*?\}\}', $mode, 'plugin_tagsections_tag');
48        }
49
50        /**
51         * Render xhtml output or metadata
52         *
53         * @param string         $mode      Renderer mode (supported modes: xhtml and metadata)
54         * @param Doku_Renderer  $renderer  The renderer
55         * @param array          $data      The data from the handler function
56         * @return bool If rendering was successful.
57         */
58        function render($mode, Doku_Renderer $renderer, $data) {
59
60            if ($data === false) return false;
61
62            // XHTML output
63            if ($mode == 'xhtml') {
64
65                // If we are directly after an opening Tag of a section level. This only applies if the option is enabled.
66                $secLevelRegex = '/<h([1-9])(.*?)(>.*?)(<\/h\1>\s*?)(<div class=")(level\1)(">\s*?)/s';
67                $matches = array();
68
69                if ( preg_match_all($secLevelRegex, $renderer->doc, $matches, PREG_SET_ORDER) ) {
70
71                    $matches = array_pop($matches);
72                    $levelTags = $tags = implode(' ', array_map(array($this, '__tags'), $data));
73                    $tagList = implode('', array_map(array($this, '__tagList'), $data));
74
75                    $matches[2] = preg_replace("/(class=\")(.*?)/", "$1$tags $2", $matches[2]);
76
77                    if ( !$this->getConf('addTagsToSectionElements') ) {
78                        $levelTags = '';
79                    }
80
81                    $renderer->doc = str_replace($matches[0], "<h{$matches[1]}{$matches[2]}{$matches[3]}$tagList{$matches[4]}{$matches[5]}$levelTags {$matches[6]}{$matches[7]}", $renderer->doc);
82
83                    return true;
84                }
85            }
86
87            return parent::render($mode, $renderer, $data);
88        }
89
90        function __clean($entry) {
91            return cleanID(str_replace(':', '_', $entry));
92        }
93
94        function __tags($entry) {
95            $entries = explode(':', $entry);
96            return implode(' ', array_unique(array_merge($entries, array($this->__clean($entry)))));
97        }
98
99        function __tagList($entry) {
100
101            $entries = explode(':', $entry);
102            $list = array_unique(array_merge($entries, array($this->__clean($entry))));
103
104            if ( ($my = $this->loadHelper('tag')) && $this->getConf('useTagLinks')) {
105                return '<span class="tagsections header tag '.implode(' ', $list).'">'.$my->tagLink($entry, array_pop($entries)).'</span>';
106            } else {
107
108                $name = array_pop($entries);
109                $format = $this->getConf('alternateLinkFormat');
110                if ( !empty($format) ) {
111                    $format = str_replace(array( "{TAG}", "{NAME}", "{RAW}" ), array( urlencode(cleanID($entry)), urlencode(cleanID($name)), cleanID($entry) ), $format);
112                    $link = tpl_link($format, $name, 'rel="tag" title="'.$entry.'"', true);
113                } else {
114                    $link = $name;
115                }
116
117                return '<span class="tagsections header tag '.implode(' ', $list).'">'.$link.'</span>';
118            }
119        }
120    }
121}
122// vim:ts=4:sw=4:et:
123