1<?php
2require_once(DOKU_PLUGIN.'autolink4/consts.php');
3
4//TODO: Bugs:
5// - lexer combines all plugin search strings. If you have too many links in a namespace (something between 500 and 1000),
6//   the regex gets too long. This has to be changed to an action plugin to fix that, and we can combined regexes in chunks.
7// - How does this play with ORPHANSWANTED?
8//TODO: Document:
9// - Regexes always match the thing that started first, or the longest string if there are two matches.
10//	'Mother in law' - [in law][Mother] => Mother
11//	'The Mother in law' - [Mother in law][Mother] => Mother in law
12
13/**
14 * Autolink 4 DokuWiki plugin
15 *
16 * @license    MIT
17 * @author     Eli Fenton
18 */
19class syntax_plugin_autolink4_regex extends DokuWiki_Syntax_Plugin {
20	use autotooltip4_consts;
21
22	/** @type helper_plugin_autotooltip $tooltip */
23	private $tooltip;
24	/** @type helper_plugin_autolink4 $tooltip */
25	private $helper;
26
27	public function __construct() {
28		if (!plugin_isdisabled('autotooltip')) {
29			$this->tooltip = plugin_load('helper', 'autotooltip');
30		}
31
32		$this->helper = plugin_load('helper', 'autolink4');
33		$this->helper->loadAndProcessConfigFile();
34	}
35
36
37	/**
38	 * @return string
39	 */
40	function getType() {
41		return 'substition';
42	}
43
44
45	/**
46	 * @return string
47	 */
48	function getPType() {
49		return 'normal';
50	}
51
52
53	/**
54	 * @return int
55	 */
56	function getSort() {
57		// Try not to interfere with any other lexer patterns.
58		return 999;
59	}
60
61
62	/**
63	 * @param $mode
64	 */
65	function connectTo($mode) {
66		global $ID;
67		foreach ($this->helper->getSubs() as $s) {
68			// Skip links to the current page.
69			if (!$this->_isSamePage($s[self::$TO], $ID)) {
70				$this->Lexer->addSpecialPattern($s[self::$MATCH], $mode, 'plugin_autolink4_regex');
71			}
72		}
73	}
74
75
76	/**
77	 * Handle the found text, and send it off to render().
78	 *
79	 * @param string $match - The found text, from addSpecialPattern.
80	 * @param int $state - The DokuWiki event state.
81	 * @param int $pos - The position in the full text.
82	 * @param Doku_Handler $handler
83	 * @return array|string
84	 */
85	function handle($match, $state, $pos, Doku_Handler $handler) {
86		return $this->helper->getMatch($match) ?? $match;
87	}
88
89
90	/**
91	 * Render the replaced links.
92	 *
93	 * @param string $mode
94	 * @param Doku_Renderer|Doku_Renderer_metadata $renderer
95	 * @param array|string $data - Data from handle()
96	 * @return bool
97	 */
98	function render($mode, Doku_Renderer $renderer, $data) {
99		if (is_string($data)) {
100			$renderer->doc .= $data;
101		} else if ($mode == 'xhtml') {
102			if ($this->helper->shouldRenderPlainText($data)) {
103				$renderer->doc .= $data[self::$TEXT];
104			}
105			else if ($this->tooltip && $data[self::$TOOLTIP]) {
106				$renderer->doc .= $this->tooltip->forWikilink($data[self::$TO], $data[self::$TEXT]);
107			}
108			else {
109				$renderer->internallink($data[self::$TO], $data[self::$TEXT]);
110			}
111		}
112		else if (!$renderer->capture) {
113			return false;
114		} else {
115			$renderer->doc .= $data[self::$TEXT];
116		}
117		return true;
118	}
119
120
121	/**
122	 * Are these two the same page>
123	 *
124	 * @param string $p1 - One page.
125	 * @param string $p2 - Another page.
126	 * @return bool
127	 */
128	function _isSamePage($p1, $p2) {
129		return $p1 == $p2;
130	}
131}
132