1<?php
2/**
3 * DokuWiki Plugin issuelink (Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
7 */
8
9use dokuwiki\plugin\issuelinks\classes\Issue;
10use dokuwiki\plugin\issuelinks\services\ServiceInterface;
11
12class syntax_plugin_issuelinks extends DokuWiki_Syntax_Plugin
13{
14
15    protected $syntaxPatterns = [];
16
17    /**
18     * @return string Syntax mode type
19     */
20    public function getType()
21    {
22        return 'substition';
23    }
24
25    /**
26     * @return int Sort order - Low numbers go before high numbers
27     */
28    public function getSort()
29    {
30        return 50;
31    }
32
33    /**
34     * Connect lookup pattern to lexer.
35     *
36     * @param string $mode Parser mode
37     */
38    public function connectTo($mode)
39    {
40        $serviceProvider = dokuwiki\plugin\issuelinks\classes\ServiceProvider::getInstance();
41        $this->syntaxPatterns = $serviceProvider->getSyntaxKeys();
42
43        foreach ($this->syntaxPatterns as $pattern => $class) {
44            $this->Lexer->addSpecialPattern("\[\[$pattern>.*?\]\]", $mode, 'plugin_issuelinks');
45        }
46    }
47
48    /**
49     * Handle matches of the issuelinks syntax
50     *
51     * @param string       $match   The match of the syntax
52     * @param int          $state   The state of the handler
53     * @param int          $pos     The position in the document
54     * @param Doku_Handler $handler The handler
55     *
56     * @return array Data for the renderer
57     *
58     * @throws Exception
59     */
60    public function handle($match, $state, $pos, Doku_Handler $handler)
61    {
62        list($pmServiceKey, $issueSyntax) = explode('>', trim($match, '[]'));
63
64        $serviceClassName = $this->syntaxPatterns[$pmServiceKey];
65        /** @var ServiceInterface $serviceClass */
66        $serviceClass = $serviceClassName::getInstance();
67
68        $issue = $serviceClass->parseIssueSyntax($issueSyntax);
69
70        if (null === $issue) {
71            return [$pmServiceKey, $issueSyntax];
72        }
73
74        global $ID, $REV, $ACT;
75        $isLatest = empty($REV);
76        if (act_clean($ACT) === 'show' && $isLatest && page_exists($ID)) {
77            $this->saveLinkToDatabase(
78                $issue->getServiceName(),
79                $issue->getProject(),
80                $issue->getKey(),
81                $issue->isMergeRequest()
82            );
83        }
84
85        return [
86            'service' => $issue->getServiceName(),
87            'project' => $issue->getProject(),
88            'issueId' => $issue->getKey(),
89            'isMergeRequest' => $issue->isMergeRequest(),
90        ];
91    }
92
93    /**
94     * @param string $project
95     * @param int    $issue_id
96     *
97     * @throws InvalidArgumentException
98     */
99    private function saveLinkToDatabase($pmServiceName, $project, $issue_id, $isMergeRequest)
100    {
101        global $ID;
102        $currentRev = @filemtime(wikiFN($ID));
103
104        /** @var helper_plugin_issuelinks_db $db_helper */
105        $db_helper = $this->loadHelper('issuelinks_db');
106        $db_helper->deleteAllIssuePageRevisions($ID, $pmServiceName, $project, $issue_id, $isMergeRequest, 'link');
107        $db_helper->savePageRevIssues($ID, $currentRev, $pmServiceName, $project, $issue_id, $isMergeRequest, 'link');
108    }
109
110    /**
111     * Render xhtml output or metadata
112     *
113     * @param string        $mode     Renderer mode (supported modes: xhtml)
114     * @param Doku_Renderer $renderer The renderer
115     * @param array         $data     The data from the handler() function
116     *
117     * @return bool If rendering was successful.
118     */
119    public function render($mode, Doku_Renderer $renderer, $data)
120    {
121        if ($mode !== 'xhtml' || count($data) === 2) {
122            $renderer->interwikilink(null, null, 'google.com', implode(' ', $data));
123            return true;
124        }
125
126        /** @noinspection ExceptionsAnnotatingAndHandlingInspection We already checked for this in the handler */
127        $issue = Issue::getInstance($data['service'], $data['project'], $data['issueId'], $data['isMergeRequest']);
128        $issue->getFromDB();
129        $renderer->doc .= $issue->getIssueLinkHTML();
130        return true;
131    }
132}
133
134// vim:ts=4:sw=4:et:
135