xref: /plugin/autotooltip/helper.php (revision 4cbd2578e15d5abe799472d234291cb1237d1880)
16bfd3f23SEli Fenton<?php
26bfd3f23SEli Fentonif(!defined('DOKU_INC')) die();
36bfd3f23SEli Fenton
46bfd3f23SEli Fenton/**
56bfd3f23SEli Fenton * Auto-Tooltip DokuWiki plugin
66bfd3f23SEli Fenton *
76bfd3f23SEli Fenton * @license    MIT
86bfd3f23SEli Fenton * @author     Eli Fenton
96bfd3f23SEli Fenton */
106bfd3f23SEli Fentonclass helper_plugin_autotooltip extends DokuWiki_Admin_Plugin {
116bfd3f23SEli Fenton	private $localRenderer;
126bfd3f23SEli Fenton
136bfd3f23SEli Fenton	public function __construct() {
146bfd3f23SEli Fenton		$this->localRenderer = new Doku_Renderer_xhtml;
156bfd3f23SEli Fenton	}
166bfd3f23SEli Fenton
176bfd3f23SEli Fenton
186bfd3f23SEli Fenton	/**
199e2add7bSEli Fenton	 * Return methods of this helper
209e2add7bSEli Fenton	 *
219e2add7bSEli Fenton	 * @return array with methods description
229e2add7bSEli Fenton	 */
239e2add7bSEli Fenton	function getMethods() {
249e2add7bSEli Fenton		$result = array();
259e2add7bSEli Fenton		$result[] = array(
269e2add7bSEli Fenton			'name' => 'forText',
279e2add7bSEli Fenton			'desc' => 'Manually construct a tooltip',
289e2add7bSEli Fenton			'params' => array(
299e2add7bSEli Fenton				'content' => 'string',
309e2add7bSEli Fenton				'tooltip' => 'string',
319e2add7bSEli Fenton				'title (optional)' => 'string',
329e2add7bSEli Fenton				'preTitle (optional)' => 'string',
339e2add7bSEli Fenton				'classes (optional)' => 'string',
349e2add7bSEli Fenton				'textStyles (optional)' => 'string',
359e2add7bSEli Fenton			),
369e2add7bSEli Fenton			'return' => array('result' => 'string')
379e2add7bSEli Fenton		);
389e2add7bSEli Fenton		$result[] = array(
399e2add7bSEli Fenton			'name' => 'forWikilink',
409e2add7bSEli Fenton			'desc' => 'Generate a tooltip from a wikilink',
419e2add7bSEli Fenton			'params' => array(
429e2add7bSEli Fenton				'id' => 'string',
439e2add7bSEli Fenton				'content (optional)' => 'string',
449e2add7bSEli Fenton				'preTitle (optional)' => 'string',
459e2add7bSEli Fenton				'classes (optional)' => 'string',
469e2add7bSEli Fenton				'textStyles (optional)' => 'string',
479e2add7bSEli Fenton			),
489e2add7bSEli Fenton			'return' => array('result' => 'string')
499e2add7bSEli Fenton		);
509e2add7bSEli Fenton		return $result;
519e2add7bSEli Fenton	}
529e2add7bSEli Fenton
539e2add7bSEli Fenton
549e2add7bSEli Fenton	/**
556bfd3f23SEli Fenton	 * Return a simple tooltip.
566bfd3f23SEli Fenton	 *
5707c401fcSEli Fenton	 * @param string $content - The on-page content. May contain newlines.
58948a1374SEli Fenton	 * @param string $tooltip - The tooltip content. Newlines will be rendered as line breaks.
59948a1374SEli Fenton	 * @param string $title - The title inside the tooltip.
60948a1374SEli Fenton	 * @param string $preTitle - Text to display before the title. Newlines will be rendered as line breaks.
616bfd3f23SEli Fenton	 * @param string $classes - CSS classes to add to this tooltip.
62969d3afcSEli Fenton	 * @param string $textStyle - CSS styles for the linked content
636bfd3f23SEli Fenton	 * @return string
646bfd3f23SEli Fenton	 */
65e4338dabSEli Fenton	function forText($content, $tooltip, $title='', $preTitle = '', $classes = '', $textStyle = '') {
66b7bccb09SEli Fenton		if (empty($classes)) {
67be213c94SEli Fenton			$classes = $this->getConf('style');
68be213c94SEli Fenton		}
69b7bccb09SEli Fenton		if (empty($classes)) {
70be213c94SEli Fenton			$classes = 'default';
71be213c94SEli Fenton		}
72*4cbd2578SEli Fenton		$delay = $this->getConf('delay') ?: 0;
73be213c94SEli Fenton
74be213c94SEli Fenton		// Sanitize
75be213c94SEli Fenton		$classes = htmlspecialchars($classes);
76be213c94SEli Fenton		// Add the plugin prefix to all classes.
77be213c94SEli Fenton		$classes = preg_replace('/(\w+)/', 'plugin-autotooltip__$1', $classes);
78be213c94SEli Fenton
79be213c94SEli Fenton		$partCount = (empty($title) ? 0 : 1) + (empty($preTitle) ? 0 : 1) + (empty($tooltip) ? 0 : 1);
80be213c94SEli Fenton		if ($partCount > 1 || strchr($tooltip, "\n") !== FALSE || strlen($tooltip) > 40) {
81be213c94SEli Fenton			$classes .= ' plugin-autotooltip_big';
826bfd3f23SEli Fenton		}
836bfd3f23SEli Fenton
84969d3afcSEli Fenton		$textClass = '';
85969d3afcSEli Fenton		if (empty($textStyle)) {
86969d3afcSEli Fenton			$textClass = 'plugin-autotooltip_linked';
87969d3afcSEli Fenton			if (strstr($content, '<a ') === FALSE) {
88b7bccb09SEli Fenton				$textClass .= ' plugin-autotooltip_simple';
89969d3afcSEli Fenton			}
90969d3afcSEli Fenton		}
916bfd3f23SEli Fenton
92e4338dabSEli Fenton		$contentParts = [];
93e4338dabSEli Fenton		if (!empty($preTitle)) {
94948a1374SEli Fenton			$contentParts[] = $this->_formatTT($preTitle);
95e4338dabSEli Fenton		}
96e4338dabSEli Fenton		if (!empty($title)) {
97e4338dabSEli Fenton			$contentParts[] = '<span class="plugin-autotooltip-title">' . $title . '</span>';
98e4338dabSEli Fenton		}
99e4338dabSEli Fenton		if (!empty($tooltip)) {
100948a1374SEli Fenton			$contentParts[] = $this->_formatTT($tooltip);
101e4338dabSEli Fenton		}
102e4338dabSEli Fenton
103*4cbd2578SEli Fenton		return '<span class="' . $textClass . '" style="' . $textStyle . '" onmouseover="autotooltip.show(this)" onmouseout="autotooltip.hide()" data-delay="' . $delay . '">' .
1046bfd3f23SEli Fenton			$content .
10507c401fcSEli Fenton			'<span class="plugin-autotooltip-hidden-classes">' . $classes . '</span>' .
106e4338dabSEli Fenton			'<span class="plugin-autotooltip-hidden-tip">' .
107e4338dabSEli Fenton			implode('<br><br>', $contentParts) .
108e4338dabSEli Fenton			'</span>' .
10907c401fcSEli Fenton		'</span>';
1106bfd3f23SEli Fenton	}
1116bfd3f23SEli Fenton
1126bfd3f23SEli Fenton
1136bfd3f23SEli Fenton	/**
1146bfd3f23SEli Fenton	 * Render a tooltip, with the title and abstract of a page.
1156bfd3f23SEli Fenton	 *
1166bfd3f23SEli Fenton	 * @param string $id - A page id.
117948a1374SEli Fenton	 * @param string $content - The on-page content. Newlines will be rendered as line breaks. Omit to use the page's title.
118948a1374SEli Fenton	 * @param string $preTitle - Text to display before the title in the tooltip. Newlines will be rendered as line breaks.
1196bfd3f23SEli Fenton	 * @param string $classes - CSS classes to add to this tooltip.
120969d3afcSEli Fenton	 * @param string $linkStyle - Style attribute for the link.
1216bfd3f23SEli Fenton	 * @return string
1226bfd3f23SEli Fenton	 */
123e4338dabSEli Fenton	function forWikilink($id, $content = null, $preTitle = '', $classes = '', $linkStyle = '') {
1246bfd3f23SEli Fenton		$title = p_get_metadata($id, 'title');
1256bfd3f23SEli Fenton
126812ebc9aSEli Fenton		$link = $this->localRenderer->internallink($id, $content ?: $title, null, true);
1276bfd3f23SEli Fenton
128969d3afcSEli Fenton		if (!empty($linkStyle)) {
129969d3afcSEli Fenton			$link = preg_replace('/<a /', '<a style="' . $linkStyle . '" ', $link);
130969d3afcSEli Fenton		}
131969d3afcSEli Fenton
1326bfd3f23SEli Fenton		if (page_exists($id)) {
133*4cbd2578SEli Fenton			$abstract = $this->getAbstract($id, $title);
134*4cbd2578SEli Fenton			$link = $this->stripNativeTooltip($link);
135be213c94SEli Fenton			return $this->forText($link, $abstract, $title, $preTitle, $classes);
1366bfd3f23SEli Fenton		}
1376bfd3f23SEli Fenton		else {
1386bfd3f23SEli Fenton			return $link;
1396bfd3f23SEli Fenton		}
1406bfd3f23SEli Fenton	}
1416bfd3f23SEli Fenton
1426bfd3f23SEli Fenton
1436bfd3f23SEli Fenton	/**
144*4cbd2578SEli Fenton	 * Get a formatted abstract.
145*4cbd2578SEli Fenton	 *
146*4cbd2578SEli Fenton	 * @param string $id
147*4cbd2578SEli Fenton	 * @param string $title
148*4cbd2578SEli Fenton	 * @return string
149*4cbd2578SEli Fenton	 */
150*4cbd2578SEli Fenton	function getAbstract($id, $title) {
151*4cbd2578SEli Fenton		// Check the "description" plugin.
152*4cbd2578SEli Fenton		$abstract = p_get_metadata($id, 'plugin_description keywords');
153*4cbd2578SEli Fenton		// Default doku abstract is the first part of the page.
154*4cbd2578SEli Fenton		if (empty($abstract)) {
155*4cbd2578SEli Fenton			$abstract = p_get_metadata($id, 'description abstract');
156*4cbd2578SEli Fenton		}
157*4cbd2578SEli Fenton
158*4cbd2578SEli Fenton
159*4cbd2578SEli Fenton		// By default, the abstract starts with the title. Remove it so it's not displayed twice, but still fetch
160*4cbd2578SEli Fenton		// both pieces of metadata, in case another plugin rewrote the abstract.
161*4cbd2578SEli Fenton		return preg_replace('/^' . $this->_pregEscape($title) . '(\r?\n)+/', '', $abstract);
162*4cbd2578SEli Fenton	}
163*4cbd2578SEli Fenton
164*4cbd2578SEli Fenton
165*4cbd2578SEli Fenton	/**
166*4cbd2578SEli Fenton	 * Strip the native title= tooltip from an anchor tag.
167*4cbd2578SEli Fenton	 *
168*4cbd2578SEli Fenton	 * @param string $link
169*4cbd2578SEli Fenton	 * @return string
170*4cbd2578SEli Fenton	 */
171*4cbd2578SEli Fenton	function stripNativeTooltip($link) {
172*4cbd2578SEli Fenton		return preg_replace('/title="[^"]*"/', '', $link);
173*4cbd2578SEli Fenton	}
174*4cbd2578SEli Fenton
175*4cbd2578SEli Fenton
176*4cbd2578SEli Fenton	/**
1776bfd3f23SEli Fenton	 * Format tooltip text.
1786bfd3f23SEli Fenton	 *
1796bfd3f23SEli Fenton	 * @param string $tt - Tooltip text.
1806bfd3f23SEli Fenton	 * @return string
1816bfd3f23SEli Fenton	 */
1826bfd3f23SEli Fenton	private function _formatTT($tt) {
183948a1374SEli Fenton		// Convert double-newlines into vertical space.
184948a1374SEli Fenton		$tt = preg_replace('/(\r?\n){2,}/', '<br><br>', $tt);
185948a1374SEli Fenton		// Single newlines get collapsed, just like in HTML.
186948a1374SEli Fenton		return preg_replace('/(\r?\n)/', ' ', $tt);
1876bfd3f23SEli Fenton	}
188d852dc10SEli Fenton
189d852dc10SEli Fenton
190d852dc10SEli Fenton	/**
191d852dc10SEli Fenton	 * Escape a string for inclusion in a regular expression, assuming forward slash is used as the delimiter.
192d852dc10SEli Fenton	 *
193d852dc10SEli Fenton	 * @param string $r - The regex string, without delimiters.
194d852dc10SEli Fenton	 * @return string
195d852dc10SEli Fenton	 */
196d852dc10SEli Fenton	private function _pregEscape($r) {
197d852dc10SEli Fenton		return preg_replace('/\//', '\\/', preg_quote($r));
198d852dc10SEli Fenton	}
1996bfd3f23SEli Fenton}
200