]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/EditToolbar.php
Update translations
[SourceForge/phpwiki.git] / lib / EditToolbar.php
1 <?php
2
3 /* Copyright 2004-2010 $ThePhpWikiProgrammingTeam
4  * Copyright 2008-2009 Marc-Etienne Vargenau, Alcatel-Lucent
5  *
6  * This file is part of PhpWiki.
7  *
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.
12  *
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.
17  *
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.
21  */
22
23 /**
24  * EDIT Toolbar Initialization.
25  * The default/themes/toolbar.js is from Mediawiki, this PHP is written from scratch.
26  *
27  * Features:
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)
31  */
32
33 class EditToolbar
34 {
35     function __construct()
36     {
37         global $WikiTheme;
38         /**
39          * @var WikiRequest $request
40          */
41         global $request;
42
43         $this->tokens = array();
44
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
51             $js = Javascript("
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") . "'
64 ");
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
69                 printXML($js);
70             }
71         } else {
72             $WikiTheme->addMoreAttr('body', "editfocus", "document.getElementById('edit-content]').editarea.focus()");
73         }
74
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
82                 printXML($init);
83                 printXML($js);
84                 printXML(JavaScript('define_f()'));
85             }
86         }
87
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) {
95             $key .= "+pages";
96         }
97         if (defined('TOOLBAR_TEMPLATE_PULLDOWN') and TOOLBAR_TEMPLATE_PULLDOWN) {
98             $key .= "+templates_" . $dbi->getTimestamp();
99         }
100         if (defined('TOOLBAR_IMAGE_PULLDOWN') and TOOLBAR_IMAGE_PULLDOWN) {
101             if (file_exists(getUploadFilePath())) {
102                 $key .= "+images_" . filemtime(getUploadFilePath());
103             }
104         }
105         $id = $cache->generateId($key);
106         $content = $cache->get($id, 'toolbarcache');
107
108         if (!empty($content)) {
109             $this->tokens['EDIT_TOOLBAR'] =& $content;
110         } else {
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;
115         }
116     }
117
118     public function getTokens()
119     {
120         return $this->tokens;
121     }
122
123     private function _generate()
124     {
125         global $WikiTheme, $request;
126
127         $toolbar = "document.writeln(\"<div class=\\\"edit-toolbar\\\" id=\\\"toolbar\\\">\");\n";
128
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 . ']]';
133             }
134             $signature = " ––" . $username . " " . CTime();
135             $toolarray = array(
136                 array(
137                     "image" => "ed_format_bold.png",
138                     "open" => "**",
139                     "close" => "**",
140                     "sample" => _("Bold text"),
141                     "title" => _("Bold text [alt-b]")),
142                 array("image" => "ed_format_italic.png",
143                     "open" => "//",
144                     "close" => "//",
145                     "sample" => _("Italic text"),
146                     "title" => _("Italic text [alt-i]")),
147                 array("image" => "ed_format_strike.png",
148                     "open" => "<s>",
149                     "close" => "</s>",
150                     "sample" => _("Strike-through text"),
151                     "title" => _("Strike")),
152                 array("image" => "ed_format_color.png",
153                     "open" => "%color=green% ",
154                     "close" => " %%",
155                     "sample" => _("Color text"),
156                     "title" => _("Color")),
157                 array("image" => "ed_pagelink.png",
158                     "open" => "[[",
159                     "close" => "]]",
160                     "sample" => _("PageName|optional label"),
161                     "title" => _("Link to page")),
162                 array("image" => "ed_link.png",
163                     "open" => "[[",
164                     "close" => "]]",
165                     "sample" => _("http://www.example.com|optional label"),
166                     "title" => _("External link (remember http:// prefix)")),
167                 array("image" => "ed_headline.png",
168                     "open" => "\\n== ",
169                     "close" => " ==\\n",
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,
179                     "close" => "",
180                     "sample" => "",
181                     "title" => _("Your signature")),
182                 array("image" => "ed_hr.png",
183                     "open" => "\\n----\\n",
184                     "close" => "",
185                     "sample" => "",
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",
189                     "close" => "",
190                     "sample" => "",
191                     "title" => _("Sample table")),
192                 array("image" => "ed_enumlist.png",
193                     "open" => "\\n# Item 1\\n# Item 2\\n# Item 3\\n",
194                     "close" => "",
195                     "sample" => "",
196                     "title" => _("Enumeration")),
197                 array("image" => "ed_list.png",
198                     "open" => "\\n* Item 1\\n* Item 2\\n* Item 3\\n",
199                     "close" => "",
200                     "sample" => "",
201                     "title" => _("List")),
202                 array("image" => "ed_toc.png",
203                     "open" => "<<CreateToc with_toclink||=1>>\\n",
204                     "close" => "",
205                     "sample" => "",
206                     "title" => _("Table of Contents")),
207                 array("image" => "ed_redirect.png",
208                     "open" => "<<RedirectTo page=\"",
209                     "close" => "\">>",
210                     "sample" => _("Page Name"),
211                     "title" => _("Redirect")),
212                 array("image" => "ed_templateplugin.png",
213                     "open" => "{{",
214                     "close" => "}}",
215                     "sample" => _("Template Name"),
216                     "title" => _("Template"))
217             );
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");
230             }
231
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");
244             }
245             /* Fails with Chrome */
246             if (!isBrowserSafari()) {
247                 $toolbar .= ("addInfobox('"
248                     . addslashes(_("Click a button to get an example text"))
249                     . "');\n");
250             }
251         }
252
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",
259                     'id' => "sr_undo",
260                     'src' => $undo_d_btn,
261                     'title' => _("Undo Search & Replace"),
262                     'alt' => _("Undo Search & Replace"),
263                     'onclick' => "do_undo()")),
264                 HTML::img
265                 (array('class' => "toolbar",
266                     'src' => $sr_btn,
267                     'alt' => _("Search & Replace"),
268                     'title' => _("Search & Replace"),
269                     'onclick' => "replace()")));
270         } else {
271             $sr_html = '';
272         }
273
274         //TODO: Delegate this to run-time with showing an hidden input at the right
275
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());
280
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));
287
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());
291
292         // don't use document.write for replace, otherwise self.opener is not defined.
293         $toolbar_end = "document.writeln(\"</div>\");";
294         if ($sr_html)
295             return HTML(Javascript($toolbar),
296                 "\n", $sr_html, "\n",
297                 Javascript($toolbar_end));
298         else
299             return HTML(Javascript($toolbar . $toolbar_end));
300     }
301
302     //result is cached
303     private function categoriesPulldown()
304     {
305         /**
306          * @var WikiRequest $request
307          */
308         global $request;
309         global $WikiTheme;
310
311         require_once 'lib/TextSearchQuery.php';
312         $dbi =& $request->_dbi;
313         // KEYWORDS formerly known as $KeywordLinkRegexp
314         $pages = $dbi->titleSearch(new TextSearchQuery(KEYWORDS, true));
315         if ($pages) {
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']";
323                 } else {
324                     $categories[] = "['$page', '%0A" . $page . "']";
325                 }
326             }
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);
340         }
341         return '';
342     }
343
344     // result is cached. Esp. the args are expensive
345     private function pluginPulldown()
346     {
347         global $WikiTheme;
348         global $AllAllowedPlugins;
349
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();
355         unset($pd);
356         sort($plugins);
357         if (!empty($plugins)) {
358             $plugin_js = '';
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') {
367                         $plugin_args = '';
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());
372                         if ($desc)
373                             $plugin_args = ' ' . str_replace($src, $replace, $desc);
374                         $toinsert = "%0A<<" . $pluginName . $plugin_args . ">>"; // args?
375                         $plugin_js .= ",['$pluginName','$toinsert']";
376                     }
377                 }
378             }
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('" .
386                     _("Insert Plugin")
387                     . "',[" . $plugin_js . "],'"
388                     . _("Insert") . "','"
389                     . _("Close") . "','tb-plugins')"));
390             return HTML("\n", $more_buttons);
391         }
392         return '';
393     }
394
395     // result is cached. Esp. the args are expensive
396     private function pagesPulldown($query, $case_exact = false, $regex = 'auto')
397     {
398         /**
399          * @var WikiRequest $request
400          */
401         global $request;
402
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) {
407             global $WikiTheme;
408             $pages = array();
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']";
413                 else
414                     $pages[] = "['$page', '$page']";
415             }
416             return HTML("\n", HTML::img(array('class' => "toolbar",
417                 'id' => 'tb-pages',
418                 'src' => $WikiTheme->getImageURL("ed_pages.png"),
419                 'title' => _("Insert PageLink"),
420                 'alt' => _("Insert PageLink"),
421                 'onclick' => "showPulldown('" .
422                     _("Insert PageLink")
423                     . "',[" . join(",", $pages) . "],'"
424                     . _("Insert") . "','"
425                     . _("Close") . "','tb-pages')")));
426         }
427         return '';
428     }
429
430     // result is cached. Esp. the args are expensive
431     private function imagePulldown()
432     {
433         global $WikiTheme, $request;
434
435         $image_dir = getUploadFilePath();
436         $pd = new imageOrVideoSet($image_dir, '*');
437         $images = $pd->getFiles();
438         unset($pd);
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());
443             unset($pd);
444         }
445         sort($images);
446         if (!empty($images)) {
447             $image_js = '';
448             foreach ($images as $image) {
449                 $image_js .= ",['$image','{{" . $image . "}}']";
450             }
451             $image_js = substr($image_js, 1);
452             $more_buttons = HTML::img(array('class' => "toolbar",
453                 'id' => 'tb-images',
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);
463         }
464         return '';
465     }
466
467     // result is cached. Esp. the args are expensive
468     // FIXME!
469     private function templatePulldown($query, $case_exact = false, $regex = 'auto')
470     {
471         global $request;
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()) {
476             global $WikiTheme;
477             $pages_js = '';
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']";
483             }
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('" .
493                         _("Insert Template")
494                         . "',[" . $pages_js . "],'"
495                         . _("Insert") . "','"
496                         . _("Close") . "','tb-templates')")));
497         }
498         return '';
499     }
500
501 }
502
503 // Local Variables:
504 // mode: php
505 // tab-width: 8
506 // c-basic-offset: 4
507 // c-hanging-comment-ender-p: nil
508 // indent-tabs-mode: nil
509 // End: