source: documentation/trunk/packages/plugins/greenstonedocs/syntax.php@ 30114

Last change on this file since 30114 was 30114, checked in by jmt12, 9 years ago

Updated Greenstone customizations for Detritus, but rearranged to move into separate plugin. Initial checkin of plugins, template, special wiki pages.

File size: 11.0 KB
Line 
1<?php
2/**
3 * A plugin to provide compatibility between the marked up text format used
4 * by the Greenstone Documentation Generation scripts and Dokuwiki
5 *
6 * Features:
7 * - hide the <!-- id:XXX --> markers used during translation process
8 *
9 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
10 */
11
12if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
14require_once(DOKU_PLUGIN.'syntax.php');
15
16/**
17 * All DokuWiki plugins to extend the parser/rendering mechanism
18 * need to inherit from this class
19 */
20class syntax_plugin_greenstonedocs
21extends DokuWiki_Syntax_Plugin
22{
23
24 /** The plugin should only effect pages within this namespace.
25 */
26 private $target_namespace_prefix;
27
28
29 /** @function __construct()
30 */
31 public function __construct()
32 {
33 global $conf;
34
35 $this->target_namespace_prefix = $this->getConf('currentnamespace');
36
37 // Prerequisite testing. Ensure the following list of plugins are also
38 // installed and complain otherwise.
39 if ($this->getConf('checkprereq'))
40 {
41 $prereqs = array_flip(explode(' ', $this->getConf('prerequisiteplugins')));
42 if ($dh = opendir(DOKU_PLUGIN))
43 {
44 while (($file = readdir($dh)) !== false)
45 {
46 $path = DOKU_PLUGIN . $file;
47 if (substr($file, 0, 1) != '.' && is_dir($path))
48 {
49 if (isset($prereqs[$file]))
50 {
51 unset($prereqs[$file]);
52 }
53 }
54 }
55 closedir($dh);
56 }
57 if (count($prereqs) > 0)
58 {
59 ksort($prereqs);
60 foreach ($prereqs as $plugin_name => $value)
61 {
62 msg("The Greenstone Wiki requires the plugin: " . $plugin_name, -1);
63 }
64 }
65 else
66 {
67 $this->_resetConf('checkprereq');
68 }
69 }
70 // Check the plugin configuration and, if checked, proceed to auto-
71 // matically update the internal links within the Greenstone wiki pages
72 // to have a different base namespace
73 if ($this->getConf('updatenamespace'))
74 {
75 // Determine the starting point for the update
76 $base_dir = DOKU_INC . 'data/pages/' . $this->getConf('currentnamespace') . '/';
77 // - ensure trailing : for consistency in namespaces
78 $current_namespace = $this->getConf('currentnamespace');
79 if (strlen($current_namespace) > 0 && substr($current_namespace, -1) != ':')
80 {
81 $current_namespace .= ':';
82 }
83 $old_namespace = $this->getConf('oldnamespace');
84 if (strlen($old_namespace) > 0 && substr($old_namespace, -1) != ':')
85 {
86 $old_namespace .= ':';
87 }
88 // - recursive call to do the actual search and replace
89 $raw_child_namespaces = explode(' ', $this->getConf('childnamespaces'));
90 $child_namespaces = array();
91 foreach ($raw_child_namespaces as $raw_child_namespace)
92 {
93 if (strlen($raw_child_namespace) > 0 && substr($raw_child_namespace, -1) != ':')
94 {
95 $raw_child_namespace .= ':';
96 }
97 $child_namespaces[] = $raw_child_namespace;
98 }
99 // Begin search
100 $this->_replaceInternalLinkNamespace($base_dir, $old_namespace, $current_namespace, $child_namespaces);
101 // Finally, we reset the configuration option back to off.
102 $this->_resetConf('updatenamespace');
103 // Let users know what has happened
104 msg("Sucessfully performed one-time update of namespace in Greenstone Documentation.", 1);
105 }
106 }
107 /** __construct() **/
108
109
110 /**
111 */
112 function _resetConf($key)
113 {
114 // Reset the configuration option back to off.
115 // - file on disk
116 $config_file_path = DOKU_CONF . 'local.php';
117 $content = file_get_contents($config_file_path);
118 $option_prefix = '$conf[\'plugin\'][\'greenstonedocs\'][\'' . $key . '\']';
119 if (strpos($content, $option_prefix) !== false)
120 {
121 $content = str_replace($option_prefix . ' = 1;',
122 $option_prefix . ' = 0;',
123 $content);
124 }
125 else
126 {
127 $content .= "\n" . $option_prefix . " = 0;";
128 }
129 file_put_contents($config_file_path, $content);
130 // - in memory cache
131 $conf[$key] = 0;
132 }
133 /** _resetConf($key) **/
134
135
136 /** @function _replaceInternalLinkNamespace()
137 */
138 function _replaceInternalLinkNamespace($dir, $old_namespace, $new_namespace, $child_namespaces)
139 {
140 $files = array();
141 if ($dh = opendir($dir))
142 {
143 while (($file = readdir($dh)) !== false)
144 {
145 if (substr($file, 0, 1) != '.')
146 {
147 $files[] = $file;
148 }
149 }
150 closedir($dh);
151 }
152 foreach ($files as $file)
153 {
154 $path = $dir . $file;
155 // - continue the recursive search through child directories
156 if (is_dir($path))
157 {
158 $this->_replaceInternalLinkNamespace($path . '/', $old_namespace, $new_namespace, $child_namespaces);
159 }
160 else if (substr($file, -4) == '.txt')
161 {
162 // - none of these files are *that* large, so read them
163 // into memory for processing
164 $page_content = file_get_contents($path);
165 // - we are looking for internal links that contain the
166 // old namespace (or '') followed by an expected child
167 // namespace - and then replace the old namespace
168 $pattern = '/(\[\[)' . $old_namespace . '(' . implode('|', $child_namespaces) . ')(.+?\]\])/';
169 $replace = '${1}'. $new_namespace . '${2}${3}';
170 $replace_count = 0;
171 $page_content = preg_replace($pattern, $replace, $page_content, -1, $replace_count);
172 // - special case: also fix up the mismatched imgcaption tags
173 $pattern = '/(<imgcaption .+?>)(<\/imgcaption>)\s*(\{\{.+?\}\})/s';
174 $replace = '${1}${3}${2}';
175 $page_content = preg_replace($pattern, $replace, $page_content, -1, $replace_count);
176 if ($replace_count > 0)
177 {
178 file_put_contents($path, $page_content);
179 }
180 }
181 }
182 }
183 /** @function _replaceInternalLinkNamespace() **/
184
185
186 /**
187 * Should return the type of syntax this plugin defines.
188 * - notice that the typo (substition == substitution) is necessary
189 */
190 function getType()
191 {
192 return 'substition';
193 }
194
195 /**
196 * Returns a number used to determine in which order modes are added.
197 */
198 function getSort()
199 {
200 return 0;
201 }
202
203 /**
204 * Connect lookup pattern to lexer.
205 */
206 function connectTo($mode)
207 {
208 $current_full_namespace = getNS(getID('id',true));
209 // Note that the result is FALSE if no match, and should be 0 if name-
210 // space starts with prefix.
211 if (strpos($current_full_namespace, $this->target_namespace_prefix) === 0)
212 {
213 // Hiding the section/translation ID tags in headers
214 $this->Lexer->addSpecialPattern( '^[ \t]*={2,6}\s?<!-- s?id:.+? -->[^\n]+={2,6}[ \t]*(?=\n)', $mode, 'plugin_greenstonedocs');
215 // Hiding the translation ID tags in paragraph text
216 $this->Lexer->addSpecialPattern('<!-- id:[^\s]+ -->', $mode, 'plugin_greenstonedocs');
217 // Hiding the translation ID tags in image captions
218 $this->Lexer->addSpecialPattern('\%!-- id:[^\s]+ --\%', $mode, 'plugin_greenstonedocs');
219 }
220 }
221
222 /**
223 * Handler to prepare matched data for the rendering process.
224 *
225 * <p>
226 * The <tt>$aState</tt> parameter gives the type of pattern
227 * which triggered the call to this method:
228 * </p>
229 * <dl>
230 * <dt>DOKU_LEXER_ENTER</dt>
231 * <dd>a pattern set by <tt>addEntryPattern()</tt></dd>
232 * <dt>DOKU_LEXER_MATCHED</dt>
233 * <dd>a pattern set by <tt>addPattern()</tt></dd>
234 * <dt>DOKU_LEXER_EXIT</dt>
235 * <dd> a pattern set by <tt>addExitPattern()</tt></dd>
236 * <dt>DOKU_LEXER_SPECIAL</dt>
237 * <dd>a pattern set by <tt>addSpecialPattern()</tt></dd>
238 * <dt>DOKU_LEXER_UNMATCHED</dt>
239 * <dd>ordinary text encountered within the plugin's syntax mode
240 * which doesn't match any pattern.</dd>
241 * </dl>
242 * @param $aMatch String The text matched by the patterns.
243 * @param $aState Integer The lexer state for the match.
244 * @param $aPos Integer The character position of the matched text.
245 * @param $aHandler Object Reference to the Doku_Handler object.
246 * @return Integer The current lexer state for the match.
247 * @public
248 * @see render()
249 * @static
250 */
251 function handle($match, $state, $pos, &$handler)
252 {
253 if (preg_match('/wiki/i', $match))
254 {
255 return array($state, $match, array('action'=>'debug',
256 'pos'=>$pos));
257 }
258 // Special case for IDs (section and language) in header strings
259 if (preg_match('/={2,6}\s?<!-- (s?id):.+? -->[^\n]+={2,6}/', $match))
260 {
261 //msg("<b>[DEBUG]</b> Title: " . htmlspecialchars($match), 2, '', '', MSG_ADMINS_ONLY);
262 $match = preg_replace('/<!-- sid:.+? -->/', '', $match);
263 $match = preg_replace('/<!-- id:.+? -->/', '', $match);
264 $handler->header($match, $state, $pos);
265 return true;
266 }
267 // any other match gets replaced with empty string
268 return array($state, $match, array('action'=>'erase', 'pos'=>$pos));
269 }
270
271 /**
272 * Handle the actual output creation.
273 *
274 * <p>
275 * The method checks for the given <tt>$aFormat</tt> and returns
276 * <tt>FALSE</tt> when a format isn't supported. <tt>$aRenderer</tt>
277 * contains a reference to the renderer object which is currently
278 * handling the rendering. The contents of <tt>$aData</tt> is the
279 * return value of the <tt>handle()</tt> method.
280 * </p>
281 * @see handle()
282 */
283 function render($mode, &$renderer, $data)
284 {
285 if($mode == 'xhtml')
286 {
287 list($state, $match, $params) = $data;
288 switch ($params['action'])
289 {
290 case 'debug':
291 $renderer->doc .= 'SQUIG-squig-squig';
292 break;
293 // By default we do an erase replace
294 default:
295 $renderer->doc .= '';
296 }
297 return true;
298 }
299 return false;
300 }
301}
302
303//Setup VIM: ex: et ts=4 enc=utf-8 :
304?>
Note: See TracBrowser for help on using the repository browser.