3 /* Copyright 2004-2010 $ThePhpWikiProgrammingTeam
4 * Copyright 2008-2009 Marc-Etienne Vargenau, Alcatel-Lucent
6 * This file is part of PhpWiki.
8 * PhpWiki is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * PhpWiki is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * EDIT Toolbar Initialization.
25 * The default/themes/toolbar.js is from Mediawiki, this PHP is written from scratch.
28 * - save-preview and formatting buttons from mediawiki
29 * - Search&Replace from walterzorn.de
30 * - pageinsert popup by Reini Urban (TODO: should be a pulldown)
35 function __construct()
39 * @var WikiRequest $request
43 $this->tokens = array();
45 //FIXME: enable Undo button for all other buttons also, not only the search/replace button
46 if (defined('JS_SEARCHREPLACE') and JS_SEARCHREPLACE) {
47 $this->tokens['JS_SEARCHREPLACE'] = 1;
48 $undo_btn = $WikiTheme->getImageURL("ed_undo.png");
49 $undo_d_btn = $WikiTheme->getImageURL("ed_undo_d.png");
50 // JS_SEARCHREPLACE from walterzorn.de
52 uri_undo_btn = '" . $undo_btn . "'
53 msg_undo_alt = '" . _("Undo") . "'
54 uri_undo_d_btn = '" . $undo_d_btn . "'
55 msg_undo_d_alt = '" . _("Undo disabled") . "'
56 msg_do_undo = '" . _("Operation undone") . "'
57 msg_replfound = '" . _("Substring “\\1” found \\2 times. Replace with “\\3”?") . "'
58 msg_replnot = '" . _("String “%s” not found.") . "'
59 msg_repl_title = '" . _("Search & Replace") . "'
60 msg_repl_search = '" . _("Search for") . "'
61 msg_repl_replace_with = '" . _("Replace with") . "'
62 msg_repl_ok = '" . _("OK") . "'
63 msg_repl_close = '" . _("Close") . "'
65 if (empty($WikiTheme->_headers_printed)) {
66 $WikiTheme->addMoreHeaders($js);
67 $WikiTheme->addMoreAttr('body', "SearchReplace", " onload='define_f()'");
68 } else { // from an actionpage: WikiBlog, AddComment, WikiForum
72 $WikiTheme->addMoreAttr('body', "editfocus", "document.getElementById('edit-content]').editarea.focus()");
75 if (defined('ENABLE_EDIT_TOOLBAR') and ENABLE_EDIT_TOOLBAR) {
76 $init = JavaScript("var data_path = '" . javascript_quote_string(DATA_PATH) . "';\n");
77 $js = JavaScript('', array('src' => $WikiTheme->_findData("toolbar.js")));
78 if (empty($WikiTheme->_headers_printed)) {
79 $WikiTheme->addMoreHeaders($init);
80 $WikiTheme->addMoreHeaders($js);
81 } else { // from an actionpage: WikiBlog, AddComment, WikiForum
84 printXML(JavaScript('define_f()'));
88 require_once 'lib/WikiPluginCached.php';
89 $cache = WikiPluginCached::newCache();
90 $dbi = $request->getDbh();
91 // regenerate if number of pages changes (categories, pages, templates, images uploaded)
92 $key = $dbi->numPages();
93 $key .= '+categories+plugin' . (isBrowserSafari() ? '+safari' : '');
94 if (defined('TOOLBAR_PAGELINK_PULLDOWN') and TOOLBAR_PAGELINK_PULLDOWN) {
97 if (defined('TOOLBAR_TEMPLATE_PULLDOWN') and TOOLBAR_TEMPLATE_PULLDOWN) {
98 $key .= "+templates_" . $dbi->getTimestamp();
100 if (defined('TOOLBAR_IMAGE_PULLDOWN') and TOOLBAR_IMAGE_PULLDOWN) {
101 if (file_exists(getUploadFilePath())) {
102 $key .= "+images_" . filemtime(getUploadFilePath());
105 $id = $cache->generateId($key);
106 $content = $cache->get($id, 'toolbarcache');
108 if (!empty($content)) {
109 $this->tokens['EDIT_TOOLBAR'] =& $content;
111 $content = $this->_generate();
112 // regenerate buttons every 1 hr/6 hrs
113 $cache->save($id, $content, DEBUG ? '+3600' : '+21600', 'toolbarcache');
114 $this->tokens['EDIT_TOOLBAR'] =& $content;
118 public function getTokens()
120 return $this->tokens;
123 private function _generate()
125 global $WikiTheme, $request;
127 $toolbar = "document.writeln(\"<div class=\\\"edit-toolbar\\\" id=\\\"toolbar\\\">\");\n";
129 if (defined('ENABLE_EDIT_TOOLBAR') and ENABLE_EDIT_TOOLBAR) {
130 $username = $request->_user->UserName();
131 if ((defined('FUSIONFORGE') && FUSIONFORGE) or DISABLE_MARKUP_WIKIWORD or (!isWikiWord($username))) {
132 $username = '[[' . $username . ']]';
134 $signature = " ––" . $username . " " . CTime();
137 "image" => "ed_format_bold.png",
140 "sample" => _("Bold text"),
141 "title" => _("Bold text [alt-b]")),
142 array("image" => "ed_format_italic.png",
145 "sample" => _("Italic text"),
146 "title" => _("Italic text [alt-i]")),
147 array("image" => "ed_format_strike.png",
150 "sample" => _("Strike-through text"),
151 "title" => _("Strike")),
152 array("image" => "ed_format_color.png",
153 "open" => "%color=green% ",
155 "sample" => _("Color text"),
156 "title" => _("Color")),
157 array("image" => "ed_pagelink.png",
160 "sample" => _("PageName|optional label"),
161 "title" => _("Link to page")),
162 array("image" => "ed_link.png",
165 "sample" => _("http://www.example.com|optional label"),
166 "title" => _("External link (remember http:// prefix)")),
167 array("image" => "ed_headline.png",
170 "sample" => _("Headline text"),
171 "title" => _("Level 1 headline")),
172 array("image" => "ed_nowiki.png",
173 "open" => "\\<verbatim\\>\\n",
174 "close" => "\\n\\</verbatim\\>",
175 "sample" => _("Insert non-formatted text here"),
176 "title" => _("Ignore wiki formatting")),
177 array("image" => "ed_sig.png",
178 "open" => $signature,
181 "title" => _("Your signature")),
182 array("image" => "ed_hr.png",
183 "open" => "\\n----\\n",
186 "title" => _("Horizontal line")),
187 array("image" => "ed_table.png",
188 "open" => "\\n{| class=\"bordered\"\\n|+ This is the table caption\\n|-\\n! Header A !! Header B !! Header C\\n|-\\n| Cell A1 || Cell B1 || Cell C1\\n|-\\n| Cell A2 || Cell B2 || Cell C2\\n|-\\n| Cell A3 || Cell B3 || Cell C3\\n|}\\n",
191 "title" => _("Sample table")),
192 array("image" => "ed_enumlist.png",
193 "open" => "\\n# Item 1\\n# Item 2\\n# Item 3\\n",
196 "title" => _("Enumeration")),
197 array("image" => "ed_list.png",
198 "open" => "\\n* Item 1\\n* Item 2\\n* Item 3\\n",
201 "title" => _("List")),
202 array("image" => "ed_toc.png",
203 "open" => "<<CreateToc with_toclink||=1>>\\n",
206 "title" => _("Table of Contents")),
207 array("image" => "ed_redirect.png",
208 "open" => "<<RedirectTo page=\"",
210 "sample" => _("Page Name"),
211 "title" => _("Redirect")),
212 array("image" => "ed_templateplugin.png",
215 "sample" => _("Template Name"),
216 "title" => _("Template"))
218 $btn = new SubmitImageButton(_("Save"), "edit[save]", 'toolbar',
219 $WikiTheme->getImageURL("ed_save.png"));
220 $btn->addTooltip(_("Save"));
221 $btn->setAccesskey("s");
222 $toolbar .= ('document.writeln("' . addslashes($btn->asXml()) . '");' . "\n");
223 // preview not supported yet on Wikiblog
224 if (empty($WikiTheme->_headers_printed)) {
225 $btn = new SubmitImageButton(_("Preview"), "edit[preview]", 'toolbar',
226 $WikiTheme->getImageURL("ed_preview.png"));
227 $btn->addTooltip(_("Preview"));
228 $btn->setAccesskey("p");
229 $toolbar .= ('document.writeln("' . addslashes($btn->asXml()) . '");' . "\n");
232 foreach ($toolarray as $tool) {
233 $image = $WikiTheme->getImageURL($tool["image"]);
234 $open = $tool["open"];
235 $close = $tool["close"];
236 $sample = addslashes($tool["sample"]);
237 // Note that we use the title both for the ALT tag and the TITLE tag of the image.
238 // Older browsers show a "speedtip" type message only for ALT.
239 // Ideally these should be different, realistically they
240 // probably don't need to be.
241 $tool = $WikiTheme->fixAccesskey($tool);
242 $title = addslashes($tool["title"]);
243 $toolbar .= ("addTagButton('$image','$title','$open','$close','$sample');\n");
245 /* Fails with Chrome */
246 if (!isBrowserSafari()) {
247 $toolbar .= ("addInfobox('"
248 . addslashes(_("Click a button to get an example text"))
253 if (defined('JS_SEARCHREPLACE') and JS_SEARCHREPLACE) {
254 $undo_d_btn = $WikiTheme->getImageURL("ed_undo_d.png");
255 $sr_btn = $WikiTheme->getImageURL("ed_replace.png");
256 //TODO: generalize the UNDO button and fix it for Search & Replace
257 $sr_html = HTML(HTML::img
258 (array('class' => "toolbar",
260 'src' => $undo_d_btn,
261 'title' => _("Undo Search & Replace"),
262 'alt' => _("Undo Search & Replace"),
263 'onclick' => "do_undo()")),
265 (array('class' => "toolbar",
267 'alt' => _("Search & Replace"),
268 'title' => _("Search & Replace"),
269 'onclick' => "replace()")));
274 //TODO: Delegate this to run-time with showing an hidden input at the right
276 // Button to generate categories, display in extra window as popup and insert
277 $sr_html = HTML($sr_html, $this->categoriesPulldown());
278 // Button to generate plugins, display in extra window as popup and insert
279 $sr_html = HTML($sr_html, $this->pluginPulldown());
281 // Button to generate pagenames, display in extra window as popup and insert
282 if (defined('TOOLBAR_PAGELINK_PULLDOWN') and TOOLBAR_PAGELINK_PULLDOWN)
283 $sr_html = HTML($sr_html, $this->pagesPulldown(TOOLBAR_PAGELINK_PULLDOWN));
284 // Button to insert from an template, display pagename in extra window as popup and insert
285 if (defined('TOOLBAR_TEMPLATE_PULLDOWN') and TOOLBAR_TEMPLATE_PULLDOWN)
286 $sr_html = HTML($sr_html, $this->templatePulldown(TOOLBAR_TEMPLATE_PULLDOWN));
288 // Button to add images, display in extra window as popup and insert
289 if (defined('TOOLBAR_IMAGE_PULLDOWN') and TOOLBAR_IMAGE_PULLDOWN)
290 $sr_html = HTML($sr_html, $this->imagePulldown());
292 // don't use document.write for replace, otherwise self.opener is not defined.
293 $toolbar_end = "document.writeln(\"</div>\");";
295 return HTML(Javascript($toolbar),
296 "\n", $sr_html, "\n",
297 Javascript($toolbar_end));
299 return HTML(Javascript($toolbar . $toolbar_end));
303 private function categoriesPulldown()
306 * @var WikiRequest $request
311 require_once 'lib/TextSearchQuery.php';
312 $dbi =& $request->_dbi;
313 // KEYWORDS formerly known as $KeywordLinkRegexp
314 $pages = $dbi->titleSearch(new TextSearchQuery(KEYWORDS, true));
316 $categories = array();
317 while ($p = $pages->next()) {
318 $page = $p->getName();
319 if ((defined('FUSIONFORGE') && FUSIONFORGE)) {
320 $categories[] = "['$page', '%0A----%0A%5B%5B" . $page . "%5D%5D']";
321 } elseif (DISABLE_MARKUP_WIKIWORD or (!isWikiWord($page))) {
322 $categories[] = "['$page', '%0A%5B" . $page . "%5D']";
324 $categories[] = "['$page', '%0A" . $page . "']";
327 if (!$categories) return '';
328 // Ensure this to be inserted at the very end. Hence we added the id to the function.
329 $more_buttons = HTML::img(array('class' => "toolbar",
330 'id' => 'tb-categories',
331 'src' => $WikiTheme->getImageURL("ed_category.png"),
332 'title' => _("Insert Categories"),
333 'alt' => "Insert Categories", // to detect this at js
334 'onclick' => "showPulldown('" .
335 _("Insert Categories")
336 . "',[" . join(",", $categories) . "],'"
337 . _("Insert") . "','"
338 . _("Close") . "','tb-categories')"));
339 return HTML("\n", $more_buttons);
344 // result is cached. Esp. the args are expensive
345 private function pluginPulldown()
348 global $AllAllowedPlugins;
350 $plugin_dir = 'lib/plugin';
351 if (defined('PHPWIKI_DIR'))
352 $plugin_dir = PHPWIKI_DIR . "/$plugin_dir";
353 $pd = new fileSet($plugin_dir, '*.php');
354 $plugins = $pd->getFiles();
357 if (!empty($plugins)) {
359 require_once 'lib/WikiPlugin.php';
360 $w = new WikiPluginLoader();
361 foreach ($plugins as $plugin) {
362 $pluginName = str_replace(".php", "", $plugin);
363 if (in_array($pluginName, $AllAllowedPlugins)) {
364 $p = $w->getPlugin($pluginName, false); // second arg?
365 // trap php files which aren't WikiPlugin~s
366 if (strtolower(substr(get_parent_class($p), 0, 10)) == 'wikiplugin') {
368 $desc = $p->getArgumentsDescription();
369 $src = array("\n", '"', "'", '|', '[', ']', '\\');
370 $replace = array('%0A', '%22', '%27', '%7C', '%5B', '%5D', '%5C');
371 $desc = str_replace("<br />", ' ', $desc->asXML());
373 $plugin_args = ' ' . str_replace($src, $replace, $desc);
374 $toinsert = "%0A<<" . $pluginName . $plugin_args . ">>"; // args?
375 $plugin_js .= ",['$pluginName','$toinsert']";
379 $plugin_js = substr($plugin_js, 1);
380 $more_buttons = HTML::img(array('class' => "toolbar",
381 'id' => 'tb-plugins',
382 'src' => $WikiTheme->getImageURL("ed_plugins.png"),
383 'title' => _("Insert Plugin"),
384 'alt' => _("Insert Plugin"),
385 'onclick' => "showPulldown('" .
387 . "',[" . $plugin_js . "],'"
388 . _("Insert") . "','"
389 . _("Close") . "','tb-plugins')"));
390 return HTML("\n", $more_buttons);
395 // result is cached. Esp. the args are expensive
396 private function pagesPulldown($query, $case_exact = false, $regex = 'auto')
399 * @var WikiRequest $request
403 require_once 'lib/TextSearchQuery.php';
404 $dbi =& $request->_dbi;
405 $page_iter = $dbi->titleSearch(new TextSearchQuery($query, $case_exact, $regex));
406 if ($page_iter->count() > 0) {
409 while ($p = $page_iter->next()) {
410 $page = $p->getName();
411 if (defined('DISABLE_MARKUP_WIKIWORD') and DISABLE_MARKUP_WIKIWORD or (!isWikiWord($page)))
412 $pages[] = "['$page', '%5B" . $page . "%5D']";
414 $pages[] = "['$page', '$page']";
416 return HTML("\n", HTML::img(array('class' => "toolbar",
418 'src' => $WikiTheme->getImageURL("ed_pages.png"),
419 'title' => _("Insert PageLink"),
420 'alt' => _("Insert PageLink"),
421 'onclick' => "showPulldown('" .
423 . "',[" . join(",", $pages) . "],'"
424 . _("Insert") . "','"
425 . _("Close") . "','tb-pages')")));
430 // result is cached. Esp. the args are expensive
431 private function imagePulldown()
433 global $WikiTheme, $request;
435 $image_dir = getUploadFilePath();
436 $pd = new imageOrVideoSet($image_dir, '*');
437 $images = $pd->getFiles();
439 if (defined('UPLOAD_USERDIR') and UPLOAD_USERDIR) {
440 $image_dir .= "/" . $request->_user->_userid;
441 $pd = new imageOrVideoSet($image_dir, '*');
442 $images = array_merge($images, $pd->getFiles());
446 if (!empty($images)) {
448 foreach ($images as $image) {
449 $image_js .= ",['$image','{{" . $image . "}}']";
451 $image_js = substr($image_js, 1);
452 $more_buttons = HTML::img(array('class' => "toolbar",
454 'src' => $WikiTheme->getImageURL("ed_image.png"),
455 'title' => _("Insert Image or Video"),
456 'alt' => _("Insert Image or Video"),
457 'onclick' => "showPulldown('" .
458 _("Insert Image or Video")
459 . "',[" . $image_js . "],'"
460 . _("Insert") . "','"
461 . _("Close") . "','tb-images')"));
462 return HTML("\n", $more_buttons);
467 // result is cached. Esp. the args are expensive
469 private function templatePulldown($query, $case_exact = false, $regex = 'auto')
472 require_once 'lib/TextSearchQuery.php';
473 $dbi =& $request->_dbi;
474 $page_iter = $dbi->titleSearch(new TextSearchQuery($query, $case_exact, $regex));
475 if ($page_iter->count()) {
478 while ($p = $page_iter->next()) {
479 $rev = $p->getCurrentRevision();
480 $toinsert = str_replace(array("\n", '"'), array('_nl', '_quot'), $rev->_get_content());
481 //$toinsert = str_replace("\n",'\n',addslashes($rev->_get_content()));
482 $pages_js .= ",['" . $p->getName() . "','_nl$toinsert']";
484 $pages_js = substr($pages_js, 1);
485 if (!empty($pages_js))
486 return HTML("\n", HTML::img
487 (array('class' => "toolbar",
488 'id' => 'tb-templates',
489 'src' => $WikiTheme->getImageURL("ed_template.png"),
490 'title' => _("Insert Template"),
491 'alt' => _("Insert Template"),
492 'onclick' => "showPulldown('" .
494 . "',[" . $pages_js . "],'"
495 . _("Insert") . "','"
496 . _("Close") . "','tb-templates')")));
507 // c-hanging-comment-ender-p: nil
508 // indent-tabs-mode: nil