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