1<?php
2
3// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
4
5use dokuwiki\Extension\SyntaxPlugin;
6
7/**
8 * DokuWiki Plugin watchcycle (Syntax Component)
9 *
10 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11 * @author  Szymon Olewniczak <dokuwiki@cosmocode.de>
12 */
13
14class syntax_plugin_watchcycle extends SyntaxPlugin
15{
16    /**
17     * @return string Syntax mode type
18     */
19    public function getType()
20    {
21        return 'disabled';
22    }
23
24    /**
25     * @return int Sort order - Low numbers go before high numbers
26     */
27    public function getSort()
28    {
29        return 100;
30    }
31
32    /**
33     * Connect lookup pattern to lexer.
34     *
35     * @param string $mode Parser mode
36     */
37    public function connectTo($mode)
38    {
39        $this->Lexer->addSpecialPattern('~~WATCHCYCLE.*?~~', $mode, 'plugin_watchcycle');
40    }
41
42    /**
43     * Handle matches of the watchcycle syntax. We assume that maintainer name doesn't contain semicolons.
44     *
45     * @param string       $match   The match of the syntax
46     * @param int          $state   The state of the handler
47     * @param int          $pos     The position in the document
48     * @param Doku_Handler $handler The handler
49     *
50     * @return bool|array Data for the renderer
51     */
52    public function handle($match, $state, $pos, Doku_Handler $handler)
53    {
54        /* @var DokuWiki_Auth_Plugin $auth */
55        global $auth;
56
57        if (!plugin_load('helper', 'sqlite')) {
58            msg($this->getLang('error sqlite missing'), -1);
59            return false;
60        }
61        if (!preg_match('/~~WATCHCYCLE:[^:]+:\d+~~/', $match)) {
62            msg('watchcycle: invalid syntax', -1);
63            return false;
64        }
65
66        $match = substr($match, strlen('~~WATCHCYCLE:'), strlen($match) - 2);
67
68        [$maintainer, $cycle] = array_map('trim', explode(':', $match));
69
70        /* @var \helper_plugin_watchcycle $helper */
71        $helper = plugin_load('helper', 'watchcycle');
72        if ($helper->validateMaintainerString($maintainer) === false) {
73            msg($this->getLang('error invalid maintainers'), -1);
74            return false;
75        }
76
77        $data = ['maintainer' => $maintainer, 'cycle' => (int)$cycle];
78
79        return $data;
80    }
81
82    /**
83     * Render xhtml output or metadata
84     *
85     * @param string        $mode     Renderer mode (supported modes: xhtml)
86     * @param Doku_Renderer $renderer The renderer
87     * @param array         $data     The data from the handler() function
88     *
89     * @return bool If rendering was successful.
90     */
91
92    public function render($mode, Doku_Renderer $renderer, $data)
93    {
94        if (!$data) {
95            return false;
96        }
97
98        $method = "render_$mode";
99        if (method_exists($this, $method)) {
100            call_user_func([$this, $method], $renderer, $data);
101            return true;
102        }
103        return false;
104    }
105
106    /**
107     * Render metadata
108     *
109     * @param Doku_Renderer $renderer The renderer
110     * @param array         $data     The data from the handler() function
111     */
112    public function render_metadata(Doku_Renderer $renderer, $data)
113    {
114        $plugin_name = $this->getPluginName();
115
116        $renderer->meta['plugin'][$plugin_name] = $data;
117    }
118
119    /**
120     * Render xhtml
121     *
122     * @param Doku_Renderer $renderer The renderer
123     * @param array         $data     The data from the handler() function
124     */
125    public function render_xhtml(Doku_Renderer $renderer, $data)
126    {
127        global $ID;
128        /** @var \DokuWiki_Auth_Plugin $auth */
129        global $auth;
130
131        /* @var \helper_plugin_watchcycle $helper */
132        $helper = plugin_load('helper', 'watchcycle');
133
134        $watchcycle = p_get_metadata($ID, 'plugin watchcycle');
135
136        $days_ago = $helper->daysAgo($watchcycle['last_maintainer_rev']);
137
138        $check_needed = false;
139        if ($days_ago > $watchcycle['cycle']) {
140            $check_needed = true;
141        }
142
143        $class = '';
144        if ($check_needed) {
145            $class = 'class="check_needed"';
146        }
147        $renderer->doc .= '<div id="plugin__watchcycle" ' . $class . '>' . NL;
148        $renderer->doc .= '<div class="column">';
149        $renderer->doc .= inlineSVG(DOKU_PLUGIN . 'watchcycle/admin.svg');
150        $renderer->doc .= '</div>';
151
152        $renderer->doc .= '<div class="column">';
153        $renderer->doc .= $this->getMaintainerHtml($watchcycle['maintainer']);
154
155
156        if ($watchcycle['changes'] == -1) {
157            $renderer->doc .= $this->getLang('never checked');
158            $renderer->doc .= ' (' . $this->getLang('check needed') . ')' . '<br />' . NL;
159        } else {
160            $renderer->doc .= sprintf($this->getLang('last check'), $days_ago);
161            if ($check_needed) {
162                $renderer->doc .= ' (' . $this->getLang('check needed') . ')';
163            }
164            $renderer->doc .= '<br />' . NL;
165
166            $urlParameters = ['rev' => $watchcycle['last_maintainer_rev'], 'do' => 'diff'];
167            $changes_lang = $this->getLang('change ' . ($watchcycle['changes'] == 1 ? 'singular' : 'plural'));
168            $changes_link = $watchcycle['changes'] . ' ' . $changes_lang;
169            $changes_link = '<a href="' . wl($ID, $urlParameters) . '">' . $changes_link . '</a>';
170            $renderer->doc .= sprintf($this->getLang('since last check'), $changes_link) . '<br />' . NL;
171        }
172
173        $renderer->doc .= '</div>';
174
175        $renderer->doc .= '</div>';
176    }
177
178    /**
179     * Returns a formatted maintainers string with mailto links.
180     *
181     * @param string $def
182     * @return string
183     */
184    protected function getMaintainerHtml($def)
185    {
186        /* @var \helper_plugin_watchcycle $helper */
187        $helper = plugin_load('helper', 'watchcycle');
188
189        $all = $helper->getMaintainers($def);
190        $flat = [];
191        foreach ($all as $name => $info) {
192            if (is_array($info)) {
193                $flat[] = $this->email($info['mail'], $info['name']);
194            } elseif ($info === null) {
195                $flat[] = $name;
196            }
197        }
198
199        return sprintf($this->getLang('maintained by'), implode(', ', $flat)) . '<br />' . NL;
200    }
201}
202
203// vim:ts=4:sw=4:et:
204