xref: /plugin/autotooltip/helper.php (revision b7bccb099269c6fd22b42bd76cc27d7697758b5e)
1<?php
2if(!defined('DOKU_INC')) die();
3
4/**
5 * Auto-Tooltip DokuWiki plugin
6 *
7 * @license    MIT
8 * @author     Eli Fenton
9 */
10class helper_plugin_autotooltip extends DokuWiki_Admin_Plugin {
11	private $localRenderer;
12
13	public function __construct() {
14		$this->localRenderer = new Doku_Renderer_xhtml;
15	}
16
17
18	/**
19	 * Return a simple tooltip.
20	 *
21	 * @param string $content - The on-page content. May contain newlines.
22	 * @param string $tooltip - The tooltip content. Newlines will be rendered as line breaks.
23	 * @param string $title - The title inside the tooltip.
24	 * @param string $preTitle - Text to display before the title. Newlines will be rendered as line breaks.
25	 * @param string $classes - CSS classes to add to this tooltip.
26	 * @param string $textStyle - CSS styles for the linked content
27	 * @return string
28	 */
29	function forText($content, $tooltip, $title='', $preTitle = '', $classes = '', $textStyle = '') {
30		if (empty($classes)) {
31			$classes = $this->getConf('style');
32		}
33		if (empty($classes)) {
34			$classes = 'default';
35		}
36
37		// Sanitize
38		$classes = htmlspecialchars($classes);
39		// Add the plugin prefix to all classes.
40		$classes = preg_replace('/(\w+)/', 'plugin-autotooltip__$1', $classes);
41
42		$partCount = (empty($title) ? 0 : 1) + (empty($preTitle) ? 0 : 1) + (empty($tooltip) ? 0 : 1);
43		if ($partCount > 1 || strchr($tooltip, "\n") !== FALSE || strlen($tooltip) > 40) {
44			$classes .= ' plugin-autotooltip_big';
45		}
46
47		$textClass = '';
48		if (empty($textStyle)) {
49			$textClass = 'plugin-autotooltip_linked';
50			if (strstr($content, '<a ') === FALSE) {
51				$textClass .= ' plugin-autotooltip_simple';
52			}
53		}
54
55		$contentParts = [];
56		if (!empty($preTitle)) {
57			$contentParts[] = $this->_formatTT($preTitle);
58		}
59		if (!empty($title)) {
60			$contentParts[] = '<span class="plugin-autotooltip-title">' . $title . '</span>';
61		}
62		if (!empty($tooltip)) {
63			$contentParts[] = $this->_formatTT($tooltip);
64		}
65
66		return '<span class="' . $textClass . '" style="' . $textStyle . '" onmouseover="autotooltip.show(this)" onmouseout="autotooltip.hide()">' .
67			$content .
68			'<span class="plugin-autotooltip-hidden-classes">' . $classes . '</span>' .
69			'<span class="plugin-autotooltip-hidden-tip">' .
70			implode('<br><br>', $contentParts) .
71			'</span>' .
72		'</span>';
73	}
74
75
76	/**
77	 * Render a tooltip, with the title and abstract of a page.
78	 *
79	 * @param string $id - A page id.
80	 * @param string $content - The on-page content. Newlines will be rendered as line breaks. Omit to use the page's title.
81	 * @param string $preTitle - Text to display before the title in the tooltip. Newlines will be rendered as line breaks.
82	 * @param string $classes - CSS classes to add to this tooltip.
83	 * @param string $linkStyle - Style attribute for the link.
84	 * @return string
85	 */
86	function forWikilink($id, $content = null, $preTitle = '', $classes = '', $linkStyle = '') {
87		$title = p_get_metadata($id, 'title');
88		$abstract = p_get_metadata($id, 'description abstract');
89
90		// By default, the abstract starts with the title. Remove it so it's not displayed twice, but still fetch
91		// both pieces of metadata, in case another plugin rewrote the abstract.
92		$abstract = preg_replace('/^' . $this->_pregEscape($title) . '(\r?\n)+/', '', $abstract);
93
94		$link = $this->localRenderer->internallink($id, $content ?: $title, null, true);
95
96		if (!empty($linkStyle)) {
97			$link = preg_replace('/<a /', '<a style="' . $linkStyle . '" ', $link);
98		}
99
100		if (page_exists($id)) {
101			// Remove the title attribute, since we have a better tooltip.
102			$link = preg_replace('/title="[^"]*"/', '', $link);
103			return $this->forText($link, $abstract, $title, $preTitle, $classes);
104		}
105		else {
106			return $link;
107		}
108	}
109
110
111	/**
112	 * Format tooltip text.
113	 *
114	 * @param string $tt - Tooltip text.
115	 * @return string
116	 */
117	private function _formatTT($tt) {
118		// Convert double-newlines into vertical space.
119		$tt = preg_replace('/(\r?\n){2,}/', '<br><br>', $tt);
120		// Single newlines get collapsed, just like in HTML.
121		return preg_replace('/(\r?\n)/', ' ', $tt);
122	}
123
124
125	/**
126	 * Escape a string for inclusion in a regular expression, assuming forward slash is used as the delimiter.
127	 *
128	 * @param string $r - The regex string, without delimiters.
129	 * @return string
130	 */
131	private function _pregEscape($r) {
132		return preg_replace('/\//', '\\/', preg_quote($r));
133	}
134}
135