-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathhelper.php
More file actions
237 lines (205 loc) · 7.06 KB
/
Copy pathhelper.php
File metadata and controls
237 lines (205 loc) · 7.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
<?php
if(!defined('DOKU_INC')) die();
use dokuwiki\File\PageResolver;
/**
* Auto-Tooltip DokuWiki plugin
*
* @license MIT
* @author Eli Fenton
*/
class helper_plugin_autotooltip extends DokuWiki_Plugin {
private $localRenderer;
private static $metaCache = [];
public function __construct() {
$this->localRenderer = new Doku_Renderer_xhtml;
}
/**
* Return methods of this helper
*
* @return array with methods description
*/
public function getMethods() {
$result = array();
$result[] = array(
'name' => 'forText',
'desc' => 'Manually construct a tooltip',
'params' => array(
'content' => 'string',
'tooltip' => 'string',
'title (optional)' => 'string',
'preTitle (optional)' => 'string',
'classes (optional)' => 'string',
'textClasses (optional)' => 'string',
),
'return' => array('result' => 'string')
);
$result[] = array(
'name' => 'forWikilink',
'desc' => 'Generate a tooltip from a wikilink',
'params' => array(
'id' => 'string',
'content (optional)' => 'string',
'preTitle (optional)' => 'string',
'classes (optional)' => 'string',
'textClasses (optional)' => 'string',
),
'return' => array('result' => 'string')
);
return $result;
}
/**
* Return a simple tooltip.
*
* @param string $content - The on-page content. May contain newlines.
* @param string $tooltip - The tooltip content. Newlines will be rendered as line breaks.
* @param string $title - The title inside the tooltip.
* @param string $preTitle - Text to display before the title. Newlines will be rendered as line breaks.
* @param string $classes - CSS classes to add to this tooltip.
* @param string $textClasses - CSS classes to add to the linked text.
* @param string $link - Link to this external URL. TODO: It would be better to parse arbitrary wikitext
* in $content, but that requires a refactor to use $renderer instead of generated HTML.
* @return string
*/
public function forText($content, $tooltip, $title='', $preTitle = '', $classes = '', $textClasses = '', $link = '') {
if (empty($classes)) {
$classes = $this->getConf('style');
}
if (empty($classes)) {
$classes = 'default';
}
$delay = $this->getConf('delay') ?: 0;
// Sanitize
$classes = htmlspecialchars($classes);
// Add the plugin prefix to all classes.
$classes = preg_replace('/(\w+)/', 'plugin-autotooltip__$1', $classes);
$partCount = (empty($title) ? 0 : 1) + (empty($preTitle) ? 0 : 1) + (empty($tooltip) ? 0 : 1);
if ($partCount > 1 || strchr($tooltip, "\n") !== FALSE || strlen($tooltip) > 40) {
$classes .= ' plugin-autotooltip_big';
}
if (empty($textClasses)) {
$textClasses = 'plugin-autotooltip_linked';
if (strstr($content, '<a ') === FALSE) {
$textClasses .= ' plugin-autotooltip_simple';
}
}
$contentParts = [];
if (!empty($preTitle)) {
$contentParts[] = $this->_formatTT($preTitle);
}
if (!empty($title)) {
$contentParts[] = '<span class="plugin-autotooltip-title">' . $title . '</span>';
}
if (!empty($tooltip)) {
$contentParts[] = $this->_formatTT($tooltip);
}
if (!empty($link)) {
$content = '<a href="'.$link.'">'.$content.'</a>';
}
return '<span class="' . $textClasses . '" onmouseover="autotooltip.show(event)" onmouseout="autotooltip.hide()" data-delay="' . $delay . '">' .
$content .
'<span class="plugin-autotooltip-hidden-classes">' . $classes . '</span>' .
'<!-- googleoff: all -->' .
'<span class="plugin-autotooltip-hidden-tip">' .
implode('<br><br>', $contentParts) .
'</span>' .
'<!-- googleon: all -->' .
'</span>';
}
/**
* Render a tooltip, with the title and abstract of a page.
*
* @param string $id - A page id.
* @param string $content - The on-page content. Newlines will be rendered as line breaks. Omit to use the page's title.
* @param string $preTitle - Text to display before the title in the tooltip. Newlines will be rendered as line breaks.
* @param string $classes - CSS classes to add to this tooltip.
* @param string $textClasses - CSS classes to add to the linked text.
* @return string
*/
public function forWikilink($id, $content = null, $preTitle = '', $classes = '', $textClasses = '') {
global $ID;
//$id = resolve_id(getNS($ID), $id, false);
$resolver = new PageResolver($ID);
$id = $resolver->resolveId($id, null, true);
$meta = self::read_meta_fast($id);
$title = $meta['title'];
$link = $this->localRenderer->internallink($id, $content ?: $title, null, true);
if (page_exists(preg_replace('/\#.*$/', '', $id))) {
$link = $this->stripNativeTooltip($link);
return $this->forText($link, $meta['abstract'], $title, $preTitle, $classes, $textClasses);
}
else {
return $link;
}
}
/**
* Is this id excluded from the plugin?
*
* @param string $id
* @return boolean
*/
public function isExcluded($id) {
$inclusions = $this->getConf('linkall_inclusions');
$exclusions = $this->getConf('linkall_exclusions');
return (!empty($inclusions) && !preg_match("/$inclusions/", $id)) ||
(!empty($exclusions) && preg_match("/$exclusions/", $id));
}
/**
* Strip the native title= tooltip from an anchor tag.
*
* @param string $link
* @return string
*/
public function stripNativeTooltip($link) {
return preg_replace('/title="[^"]*"/', '', $link);
}
/**
* Reads specific metadata about 10x faster than p_get_metadata. p_get_metadata only uses caching for the current
* page, and uses the very slow php serialization. However, in a wiki with infrequently accessed pages, it's
* extremely slow.
*
* @param string $id
* @return array - An array containing 'title' and 'abstract.'
*/
static function read_meta_fast($id) {
global $ID;
$resolver = new PageResolver($ID);
$id = $resolver->resolveId(preg_replace('/\#.*$/', '', $id), null, true);
if (isset(self::$metaCache[$id])) {
return self::$metaCache[$id];
}
$results = [
'title' => p_get_metadata(cleanID($id), 'title'),
'abstract' => p_get_metadata(cleanID($id), 'plugin_description keywords') ?: p_get_metadata(cleanID($id), 'description abstract')
];
// By default, the abstract starts with the title. Remove it so it's not displayed twice, but still fetch
// both pieces of metadata, in case another plugin rewrote the abstract.
$results['abstract'] = preg_replace(
'/^' . self::_pregEscape($results['title']) . '(\r?\n)+/',
'',
$results['abstract']
);
self::$metaCache[$id] = $results;
return $results;
}
/**
* Format tooltip text.
*
* @param string $tt - Tooltip text.
* @return string
*/
private function _formatTT($tt) {
// Convert double-newlines into vertical space.
$tt = preg_replace('/(\r?\n){2,}/', '<br><br>', $tt);
// Single newlines get collapsed, just like in HTML.
return preg_replace('/(\r?\n)/', ' ', $tt);
}
/**
* Escape a string for inclusion in a regular expression, assuming forward slash is used as the delimiter.
*
* @param string $r - The regex string, without delimiters.
* @return string
*/
private static function _pregEscape($r) {
return preg_replace('/\//', '\\/', preg_quote($r));
}
}