1<?php
2
3use dokuwiki\Extension\SyntaxPlugin;
4
5/**
6 * DokuWiki Plugin yatp (Syntax Component)
7 *
8 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
9 * @author Feralheart <dokuwiki@feralheart.dev>
10 */
11class syntax_plugin_yatp_template extends SyntaxPlugin
12{
13    /** @inheritDoc */
14    public function getType()
15    {
16        return 'container';
17    }
18
19    /** @inheritDoc */
20    public function getPType()
21    {
22        return 'normal';
23    }
24
25    /** @inheritDoc */
26    public function getSort()
27    {
28        return 302;
29    }
30
31    /** @inheritDoc */
32    public function connectTo($mode)
33    {
34        $this->Lexer->addSpecialPattern("{{template>.+?}}", $mode, 'plugin_yatp_template');
35    }
36
37    /** @inheritDoc */
38    function handle($match, $state, $pos, Doku_Handler $handler) {
39        global $ID;
40
41        $helper = plugin_load('helper', 'yatp');
42
43        $match = substr($match, 11, -2);                        // strip markup
44        $replacers = preg_split('/(?<!\\\\)\|/', $match);        // Get the replacers
45        $wikipage = array_shift($replacers);
46
47        $replacers = $helper->messageReplacers($replacers);
48        $template = $helper->getTemplateFile($wikipage);
49
50        return array($template, $replacers);
51    }
52
53    /** @inheritDoc */
54    public function render($mode, Doku_Renderer $renderer, $data)
55    {
56        global $ID;
57        if ($mode !== 'xhtml') {
58            return false;
59        }
60
61        $helper = plugin_load('helper', 'yatp');
62
63        $templateName = $data[0];
64        if(!$templateName) return false;
65
66        $rawFile = $helper->getTemplate($templateName);
67        if(!empty($data[1]['keys']) && !empty($data[1]['vals'])) {
68            $rawFile = str_replace($data[1]['keys'], $data[1]['vals'], $rawFile);
69        }
70
71        // replace unmatched substitutions with "" or use DEFAULT_STR from data arguments if exists.
72        $left_overs = '/'.BEGIN_REPLACE_DELIMITER.'.*'.END_REPLACE_DELIMITER.'/';
73
74        if(!empty($data[1]['keys']) && !empty($data[1]['vals'])) {
75            $def_key = array_search(BEGIN_REPLACE_DELIMITER."DEFAULT_STR".END_REPLACE_DELIMITER, $data[1]['keys']);
76            $DEFAULT_STR = $def_key ? $data[1]['vals'][$def_key] : "";
77            $rawFile = preg_replace($left_overs, $DEFAULT_STR, $rawFile);
78        }
79
80        $metadata = p_get_metadata($ID, 'relation');
81        $existingRefs = isset($metadata['references']) ? $metadata['references'] : [];
82
83        $instr = p_get_instructions($rawFile);
84
85        foreach ($instr as $instruction) {
86            list($cmd, $params) = $instruction;
87
88            if ($cmd === 'internallink') {
89                $linkID = cleanID($params[0]);
90                if (!$linkID) continue;
91
92                $existingRefs[$linkID] = page_exists($linkID);
93            }
94        }
95
96        p_set_metadata($pageId, [
97            'relation' => [
98                'references' => $existingRefs
99            ]
100        ], true, true);
101
102        // render the instructructions on the fly
103        $info = ['cache' => false];
104        $text = p_render('xhtml', $instr, $info);
105
106        // remove toc, section edit buttons and category tags
107        $patterns = array('!<div class="toc">.*?(</div>\n</div>)!s',
108                          '#<!-- SECTION \[(\d*-\d*)\] -->#',
109                          '!<div class="category">.*?</div>!s');
110        $replace  = array('', '', '');
111        $text = preg_replace($patterns, $replace, $text);
112
113        // prevent caching to ensure the included page is always fresh
114        $renderer->info['cache'] = FALSE;
115        $renderer->info['depends']['pages'][] = $data[0];
116
117        // embed the included page
118        $renderer->doc .= '<div class="yatp">';
119        $renderer->doc .= $text;
120        $renderer->doc .= '</div>';
121
122        return true;
123    }
124}
125