Skip to content

Commit d590888

Browse files
committed
initial commit
1 parent 6dadf8c commit d590888

File tree

5 files changed

+704
-3
lines changed

5 files changed

+704
-3
lines changed

README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
const
2-
=====
1+
====== Const Plugin for DokuWiki ======
32

4-
Dokuwiki Plugin
3+
All documentation for the Const Plugin is available online at:
4+
5+
* http://dokuwiki.org/plugin:const
6+
7+
(c) 2013 by lisps
8+
9+
This plugin uses the evalmath class (http://www.phpclasses.org/package/2695-PHP-Safely-evaluate-mathematical-expressions.html) by Miles Kaufmann (BSD License).
10+
11+
See LICENSE for license info.

action.php

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
<?php
2+
/**
3+
* DokuWiki Plugin const (Action Component)
4+
*
5+
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6+
* @author lisps
7+
*/
8+
9+
if (!defined('DOKU_INC'))
10+
define('DOKU_INC', realpath(dirname(__FILE__) . '/../../') . '/');
11+
if (!defined('DOKU_PLUGIN'))
12+
define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
13+
14+
require_once(DOKU_PLUGIN . 'action.php');
15+
16+
/**
17+
* All DokuWiki plugins to extend the parser/rendering mechanism
18+
* need to inherit from this class
19+
*/
20+
class action_plugin_const extends DokuWiki_Action_Plugin {
21+
/**
22+
* return some info
23+
*/
24+
private $autoindexer = 0;
25+
private $invalidate = FALSE;
26+
27+
/**
28+
* offsets-at-character-position. recorded as tuples {charpos,offset}, where charpos is the
29+
* position in the MODIFIED data, not the position in the original data, and offset is the
30+
* CUMULATIVE offset at that position, not the offset relative to the previous location.
31+
*/
32+
var $offsets = array();
33+
34+
/**
35+
* pagename for which calculation is made
36+
*
37+
*/
38+
var $page = '';
39+
40+
/**
41+
* During the run, contains the original wiki data.
42+
*/
43+
var $original;
44+
45+
/**
46+
* During the run, contains the modified wiki data.
47+
*/
48+
var $wikified;
49+
50+
51+
//hook before rendering starts
52+
function register(&$controller) {
53+
$controller->register_hook('PARSER_WIKITEXT_PREPROCESS', 'BEFORE', $this, '_doreplace');
54+
$controller->register_hook('PARSER_HANDLER_DONE', 'BEFORE', $this, '_fixsecedit');
55+
$controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, '_cache_control');
56+
}
57+
58+
59+
function _replacecallback($hits) {
60+
return ($this->autoindexer++);
61+
}
62+
63+
//trigger
64+
function _doreplace(&$event, $param) {
65+
global $ID;
66+
67+
require_once(dirname(__FILE__) . "/class.evalmath.php");
68+
$math = new evalmath();
69+
70+
$this->invalidate = FALSE;
71+
72+
$this->original = $event->data;
73+
$this->wikified = $this->original;
74+
75+
//catch anonymous access
76+
$username=isset($_SERVER['REMOTE_USER'])?$_SERVER['REMOTE_USER']:"anonymous";
77+
78+
//get const definitions
79+
$data = array();
80+
if (preg_match('§<const[^>]*>([^<]*)</const>§', $event->data, $data) > 0) {
81+
//split entries
82+
$data = array_pop($data);
83+
$data = preg_split('/[\r\n]+/', $data, -1, PREG_SPLIT_NO_EMPTY);
84+
85+
//process wiki-data
86+
$autoindex = 0;
87+
foreach ($data as $entry) {
88+
//normal const
89+
$item = explode("=", trim($entry));
90+
if (count($item) === 2) {
91+
//special string-replace
92+
switch ($item[1]) {
93+
case "%USER%":
94+
$item[1] = $username;
95+
$this->invalidate = TRUE;
96+
break; //pagename
97+
case "%ID%":
98+
$item[1] = noNS(cleanID(getID()));
99+
break; //pagename
100+
case "%NAMESPACE%":
101+
$item[1] = getNS(cleanID(getID()));
102+
break; //namespace
103+
case "%RANDOM%":
104+
$item[1] = strval(rand());
105+
$this->invalidate = TRUE;
106+
break; //random number
107+
case "%YEAR%":
108+
$item[1] = date("Y");
109+
break; //current year
110+
case "%MONTH%":
111+
$item[1] = date("m");
112+
break; //current month
113+
case "%MONTHNAME%":
114+
$item[1] = date("F");
115+
break; //current month
116+
case "%WEEK%":
117+
$item[1] = date("W");
118+
$this->invalidate = TRUE;
119+
break; //current week (iso)
120+
case "%DAY%":
121+
$item[1] = date("d");
122+
$this->invalidate = TRUE;
123+
break; //current day
124+
case "%DAYNAME%":
125+
$item[1] = date("l");
126+
$this->invalidate = TRUE;
127+
break; //current day
128+
case "%AUTOINDEX%":
129+
$item[1] = "%%INDEX#" . (++$autoindex) . "%%"; //special automatic indexer
130+
break;
131+
default:
132+
$item[1] = trim($item[1]);
133+
break;
134+
}
135+
136+
//replace in wiki
137+
$this->wikified = str_replace("%%" . trim($item[0]) . "%%", $item[1], $this->wikified);
138+
139+
//load evaluator
140+
@$math->evaluate($item[0]."=".$item[1]);
141+
} else {
142+
//evaluate expression
143+
$item = explode(":", $entry);
144+
if (count($item) === 2) {
145+
$this->wikified = str_replace("%%" . trim($item[0]) . "%%", @$math->evaluate($item[1]), $this->wikified);
146+
}
147+
}
148+
}
149+
150+
//autoindex?
151+
while ($autoindex > 0) {
152+
$this->autoindexer = 1;
153+
//replace all
154+
$this->wikified = preg_replace_callback("|%%INDEX#" . $autoindex . "%%|", array(
155+
$this,
156+
"_replacecallback"
157+
), $this->wikified);
158+
$autoindex--;
159+
}
160+
161+
$event->data = $this->wikified;
162+
163+
$this->original = explode("\n", $this->original);
164+
$this->wikified = explode("\n", $this->wikified);
165+
166+
// fill offset array to deal with section editing issues
167+
for ($l = 0; $l < count($this->wikified); $l++) {
168+
// record offsets at the start of this line
169+
$this->offsets[] = array(
170+
'pos' => $char_pos,
171+
'offset' => $text_offset
172+
);
173+
// calculate position / offset for next line
174+
$char_pos += strlen($this->wikified[$l]) + 1;
175+
$text_offset += strlen($this->wikified[$l]) - strlen($this->original[$l]);
176+
//echo '(' . $char_pos . '/' . $text_offset . ')' . ' ';
177+
}
178+
}
179+
180+
unset($this->original);
181+
unset($this->wikified);
182+
183+
//save invalidation info to metadata
184+
p_set_metadata($ID, array(
185+
'plugin_const' => array(
186+
'invalidate' => $this->invalidate
187+
)
188+
), FALSE, TRUE);
189+
}
190+
191+
/**
192+
* force cache invalidation for certain constants
193+
*/
194+
function _cache_control(&$event, $param) {
195+
global $conf;
196+
197+
$cache =& $event->data;
198+
199+
if ((isset($cache->page) == TRUE) && ($cache->mode == "i")) {
200+
//cache purge requested?
201+
$const = p_get_metadata($cache->page, 'plugin_const');
202+
203+
//force initial purge
204+
if (!isset($const['invalidate'])) {
205+
$const['invalidate'] = TRUE;
206+
}
207+
208+
$cache->depends["purge"] = $const["invalidate"];
209+
}
210+
}
211+
212+
/**
213+
* modifying the raw data has as side effect that the sectioning is based on the
214+
* modified data, not the original. This means that after processing, we need to
215+
* adjust the section start/end markers so that they point to start/end positions
216+
* in the original data, not the modified data.
217+
*/
218+
function _fixsecedit(&$event, $param) {
219+
global $ID;
220+
if($ID != $this->page) return;
221+
222+
$calls =& $event->data->calls;
223+
$count = count($calls);
224+
225+
// iterate through the instruction list and set the file offset values
226+
// back to the values they would be if no const syntax has been added by this plugin
227+
for ($i = 0; $i < $count; $i++) {
228+
if ($calls[$i][0] == 'section_open' || $calls[$i][0] == 'section_close' || $calls[$i][0] == 'header' || $calls[$i][0] == 'p_open') {
229+
$calls[$i][2] = $this->_convert($calls[$i][2]);
230+
}
231+
if ($calls[$i][0] == 'header') {
232+
$calls[$i][1][2] = $this->_convert($calls[$i][1][2]);
233+
}
234+
// be aware of headernofloat plugin
235+
if ($calls[$i][0] == 'plugin' && $calls[$i][1][0] == 'headernofloat') {
236+
$calls[$i][1][1]['pos'] = $this->_convert($calls[$i][1][1]['pos']);
237+
$calls[$i][2] = $this->_convert($calls[$i][2]);
238+
}
239+
}
240+
}
241+
242+
/**
243+
* Convert modified raw wiki offset value pos back to the unmodified value
244+
*/
245+
function _convert($pos) {
246+
// find the offset that applies to this character position
247+
$offset = 0;
248+
foreach ($this->offsets as $tuple) {
249+
if ($pos >= $tuple['pos']) {
250+
$offset = $tuple['offset'];
251+
} else {
252+
break;
253+
}
254+
}
255+
256+
// return corrected position
257+
return $pos - $offset;
258+
}
259+
}

0 commit comments

Comments
 (0)