]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/EditToolbar.php
Valid XHTML code for all themes
[SourceForge/phpwiki.git] / lib / EditToolbar.php
1 <?php
2 // rcs_id('$Id$');
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
19  * along with PhpWiki; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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, use acdropdown)
31  */
32
33 class EditToolbar {
34
35     function EditToolbar() {
36         global $WikiTheme;
37
38         $this->tokens = array();
39
40         //FIXME: enable Undo button for all other buttons also, not only the search/replace button
41         if (JS_SEARCHREPLACE) {
42             $this->tokens['JS_SEARCHREPLACE'] = 1;
43             $undo_btn = $WikiTheme->getImageURL("ed_undo.png"); 
44             $undo_d_btn = $WikiTheme->getImageURL("ed_undo_d.png"); 
45             // JS_SEARCHREPLACE from walterzorn.de
46             $js = Javascript("
47 uri_undo_btn   = '".$undo_btn."'
48 msg_undo_alt   = '"._("Undo")."'
49 uri_undo_d_btn = '".$undo_d_btn."'
50 msg_undo_d_alt = '"._("Undo disabled")."'
51 msg_do_undo    = '"._("Operation undone")."'
52 msg_replfound  = '"._("Substring \"\\1\" found \\2 times. Replace with \"\\3\"?")."'
53 msg_replnot    = '"._("String \"%s\" not found.")."'
54 msg_repl_title     = '"._("Search & Replace")."'
55 msg_repl_search    = '"._("Search for")."'
56 msg_repl_replace_with = '"._("Replace with")."'
57 msg_repl_ok        = '"._("OK")."'
58 msg_repl_close     = '"._("Close")."'
59 ");
60             if (empty($WikiTheme->_headers_printed)) {
61                 $WikiTheme->addMoreHeaders($js);
62                 $WikiTheme->addMoreAttr('body', "SearchReplace"," onload='define_f()'");
63             } else { // from an actionpage: WikiBlog, AddComment, WikiForum
64                 printXML($js);
65             }
66         } else {
67             $WikiTheme->addMoreAttr('body', "editfocus", "document.getElementById('edit-content]').editarea.focus()");
68         }
69     
70         if (ENABLE_EDIT_TOOLBAR) {
71             $js = JavaScript('',array('src' => $WikiTheme->_findData("toolbar.js")));
72             if (empty($WikiTheme->_headers_printed)) {
73                 $WikiTheme->addMoreHeaders($js);
74             }
75             else { // from an actionpage: WikiBlog, AddComment, WikiForum
76                 printXML($js);
77                 printXML(JavaScript('define_f()'));
78             }
79         }
80
81         require_once("lib/WikiPluginCached.php");
82         $cache = WikiPluginCached::newCache();
83         $dbi = $GLOBALS['request']->getDbh();
84         // regenerate if number of pages changes (categories, pages, templates)
85         $key = $dbi->numPages();
86         $key .= '+categories+plugin' . (isBrowserSafari() ? '+safari' : '');
87         if (TOOLBAR_PAGELINK_PULLDOWN) {
88             $key .= "+pages";
89         }
90         if (TOOLBAR_TEMPLATE_PULLDOWN) {
91             $key .= "+templates_" . $dbi->getTimestamp();
92         }
93         $id = $cache->generateId($key);
94         $content = $cache->get($id, 'toolbarcache');
95
96         if (!empty($content)) {
97             $this->tokens['EDIT_TOOLBAR'] =& $content;
98         } else {
99             $content = $this->_generate();
100             // regenerate buttons every 1 hr/6 hrs
101             $cache->save($id, $content, DEBUG ? '+3600' : '+21600', 'toolbarcache'); 
102             $this->tokens['EDIT_TOOLBAR'] =& $content;
103         }
104     }
105
106     function getTokens () {
107         return $this->tokens;
108     }
109
110     function _generate () {
111         global $WikiTheme, $request;
112
113         $toolbar = "document.writeln(\"<div class=\\\"edit-toolbar\\\" id=\\\"toolbar\\\">\");\n";
114
115         if (ENABLE_EDIT_TOOLBAR) {
116             $username = $request->_user->UserName();
117             if (GFORGE or DISABLE_MARKUP_WIKIWORD or (!isWikiWord($username))) {
118                 $username = '[['.$username.']]';
119             }
120             $signature = " ––".$username." ".CTime();
121             $toolarray = array(
122                            array(
123                                  "image"=>"ed_format_bold.png",
124                                  "open"=>"**",
125                                  "close"=>"**",
126                                  "sample"=>_("Bold text"),
127                                  "title"=>_("Bold text [alt-b]")),
128                            array("image"=>"ed_format_italic.png",
129                                  "open"=>"//",
130                                  "close"=>"//",
131                                  "sample"=>_("Italic text"),
132                                  "title"=>_("Italic text [alt-i]")),
133                            array("image"=>"ed_format_strike.png",
134                                  "open"=>"<s>",
135                                  "close"=>"</s>",
136                                  "sample"=>_("Strike-through text"),
137                                  "title"=>_("Strike")),
138                            array("image"=>"ed_format_color.png",
139                                  "open"=>"%color=green% ",
140                                  "close"=>" %%",
141                                  "sample"=>_("Color text"),
142                                  "title"=>_("Color")),
143                            array("image"=>"ed_pagelink.png",
144                                  "open"=>"[[",
145                                  "close"=>"]]",
146                                  "sample"=>_("PageName|optional label"),
147                                  "title"=>_("Link to page")),
148                            array("image"=>"ed_link.png",
149                                  "open"=>"[[",
150                                  "close"=>"]]",
151                                  "sample"=>_("http://www.example.com|optional label"),
152                                  "title"=>_("External link (remember http:// prefix)")),
153                            array("image"=>"ed_headline.png",
154                                  "open"=>"\\n== ",
155                                  "close"=>" ==\\n",
156                                  "sample"=>_("Headline text"),
157                                  "title"=>_("Level 1 headline")),
158                            array("image"=>"ed_nowiki.png",
159                                  "open"=>"\\<verbatim\\>\\n",
160                                  "close"=>"\\n\\</verbatim\\>",
161                                  "sample"=>_("Insert non-formatted text here"),
162                                  "title"=>_("Ignore wiki formatting")),
163                            array("image"=>"ed_sig.png",
164                                  "open" => $signature,
165                                  "close" => "",
166                                  "sample"=>"",
167                                  "title"=>_("Your signature")),
168                            array("image"=>"ed_hr.png",
169                                  "open"=>"\\n----\\n",
170                                  "close"=>"",
171                                  "sample"=>"",
172                                  "title"=>_("Horizontal line")),
173                            array("image"=>"ed_table.png",
174                                  "open"=>"\\n{| class=\"bordered\"\\n|+ This is the table caption\\n|= This is the table summary\\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",
175                                  "close"=>"",
176                                  "sample"=>"",
177                                  "title"=>_("Sample table")),
178                            array("image"=>"ed_enumlist.png",
179                                  "open"=>"\\n# Item 1\\n# Item 2\\n# Item 3\\n",
180                                  "close"=>"",
181                                  "sample"=>"",
182                                  "title"=>_("Enumeration")),
183                            array("image"=>"ed_list.png",
184                                  "open"=>"\\n* Item 1\\n* Item 2\\n* Item 3\\n",
185                                  "close"=>"",
186                                  "sample"=>"",
187                                  "title"=>_("List")),
188                            array("image"=>"ed_toc.png",
189                                  "open"=>"<<CreateToc with_toclink||=1>>\\n",
190                                  "close"=>"",
191                                  "sample"=>"",
192                                  "title"=>_("Table of Contents")),
193                            array("image"=>"ed_redirect.png",
194                                  "open"=>"<<RedirectTo page=\"",
195                                  "close"=>"\">>",
196                                  "sample"=>_("Page Name"),
197                                  "title"=>_("Redirect")),
198                            array("image"=>"ed_templateplugin.png",
199                                  "open"=>"{{",
200                                  "close"=>"}}",
201                                  "sample"=>_("Template Name"),
202                                  "title"=>_("Template"))
203                            );
204             $btn = new SubmitImageButton(_("Save"), "edit[save]", 'toolbar', 
205                                          $WikiTheme->getImageURL("ed_save.png"));
206             $btn->addTooltip(_("Save"));
207             $btn->setAccesskey("s");
208             $toolbar .= ('document.writeln("'.addslashes($btn->asXml()).'");'."\n");
209             // preview not supported yet on Wikiblog
210             if (empty($WikiTheme->_headers_printed)) {
211                 $btn = new SubmitImageButton(_("Preview"), "edit[preview]", 'toolbar', 
212                                              $WikiTheme->getImageURL("ed_preview.png"));
213                 $btn->addTooltip(_("Preview"));
214                 $btn->setAccesskey("p");
215                 $toolbar .= ('document.writeln("'.addslashes($btn->asXml()).'");'."\n");
216             }
217     
218             foreach ($toolarray as $tool) {
219                 global $WikiTheme;
220                 $image = $WikiTheme->getImageURL($tool["image"]);
221                 $open  = $tool["open"];
222                 $close = $tool["close"];
223                 $sample = addslashes( $tool["sample"] );
224                 // Note that we use the title both for the ALT tag and the TITLE tag of the image.
225                 // Older browsers show a "speedtip" type message only for ALT.
226                 // Ideally these should be different, realistically they
227                 // probably don't need to be.
228                 $tool = $WikiTheme->fixAccesskey($tool);
229                 $title = addslashes( $tool["title"] );
230                 $toolbar .= ("addTagButton('$image','$title','$open','$close','$sample');\n");
231             }
232             /* Fails with Chrome */
233             if (!isBrowserSafari()) {
234                 $toolbar .= ("addInfobox('" 
235                              . addslashes( _("Click a button to get an example text") ) 
236                              . "');\n");
237             }
238         }
239
240         if (JS_SEARCHREPLACE) {
241             $undo_d_btn = $WikiTheme->getImageURL("ed_undo_d.png"); 
242             //$redo_btn = $WikiTheme->getImageURL("ed_redo.png");
243             $sr_btn   = $WikiTheme->getImageURL("ed_replace.png");
244             //TODO: generalize the UNDO button and fix it for Search & Replace
245             $sr_html = HTML(HTML::img
246                             (array('class'=>"toolbar",
247                                    'id'   =>"sr_undo",
248                                    'src'  =>$undo_d_btn,
249                                    'title'=>_("Undo Search & Replace"),
250                                    'alt'  =>_("Undo Search & Replace"),
251                                    //'disabled'=>"disabled",   //non-XHTML conform
252                                    //'onfocus' =>"if(this.blur && undo_buffer_index==0) this.blur()",
253                                    'onclick' =>"do_undo()")),
254                             HTML::img
255                             (array('class'=>"toolbar",
256                                    'src'  => $sr_btn,
257                                    'alt'  =>_("Search & Replace"),
258                                    'title'=>_("Search & Replace"),
259                                    'onclick'=>"replace()")));
260         } else {
261             $sr_html = '';
262         }
263
264         //TODO: Delegate this to run-time with showing an hidden input at the right, and do 
265         // a seperate moacdropdown and xmlrpc:titleSearch.
266
267         // Button to generate categories, display in extra window as popup and insert
268         $sr_html = HTML($sr_html, $this->categoriesPulldown());
269         // Button to generate plugins, display in extra window as popup and insert
270         $sr_html = HTML($sr_html, $this->pluginPulldown());
271
272         // Button to generate pagenames, display in extra window as popup and insert
273         if (TOOLBAR_PAGELINK_PULLDOWN)
274             $sr_html = HTML($sr_html, $this->pagesPulldown(TOOLBAR_PAGELINK_PULLDOWN));
275         // Button to insert from an template, display pagename in extra window as popup and insert
276         if (TOOLBAR_TEMPLATE_PULLDOWN)
277             $sr_html = HTML($sr_html, $this->templatePulldown(TOOLBAR_TEMPLATE_PULLDOWN));
278
279         // Button to add images, display in extra window as popup and insert
280         if (TOOLBAR_IMAGE_PULLDOWN)
281             $sr_html = HTML($sr_html, $this->imagePulldown(TOOLBAR_IMAGE_PULLDOWN));
282
283         // don't use document.write for replace, otherwise self.opener is not defined.
284         $toolbar_end = "document.writeln(\"</div>\");";
285         if ($sr_html)
286             return HTML(Javascript($toolbar),
287                         "\n", $sr_html, "\n",
288                         Javascript($toolbar_end));
289         else
290             return HTML(Javascript($toolbar . $toolbar_end));
291     }
292
293     //result is cached
294     function categoriesPulldown() {
295         global $WikiTheme;
296
297         require_once('lib/TextSearchQuery.php');
298         $dbi =& $GLOBALS['request']->_dbi;
299         // KEYWORDS formerly known as $KeywordLinkRegexp
300         $pages = $dbi->titleSearch(new TextSearchQuery(KEYWORDS, true));
301         if ($pages) {
302             $categories = array();
303             while ($p = $pages->next()) {
304                 $page = $p->getName();
305                 if (GFORGE) {
306                     $categories[] = "['$page', '%0A----%0A%5B%5B".$page."%5D%5D']";
307                 } else if (DISABLE_MARKUP_WIKIWORD or (!isWikiWord($page))) {
308                     $categories[] = "['$page', '%0A%5B".$page."%5D']";
309                 } else {
310                     $categories[] = "['$page', '%0A".$page."']";
311                 }
312             }
313             if (!$categories) return '';
314             // Ensure this to be inserted at the very end. Hence we added the id to the function.
315             $more_buttons = HTML::img(array('class'=> "toolbar",
316                                             'id' => 'tb-categories',
317                                             'src'  => $WikiTheme->getImageURL("ed_category.png"),
318                                             'title'=>_("AddCategory"),
319                                             'alt'=>"AddCategory", // to detect this at js
320                                             'onclick'=>"showPulldown('".
321                                             _("Insert Categories")
322                                             ."',[".join(",",$categories)."],'"
323                                             ._("Insert")."','"
324                                             ._("Close")."','tb-categories')"));
325             return HTML("\n", $more_buttons);
326         }
327         return '';
328     }
329
330     // result is cached. Esp. the args are expensive
331     function pluginPulldown() {
332         global $WikiTheme;
333         global $AllAllowedPlugins;
334
335         $plugin_dir = 'lib/plugin';
336         if (defined('PHPWIKI_DIR'))
337             $plugin_dir = PHPWIKI_DIR . "/$plugin_dir";
338         $pd = new fileSet($plugin_dir, '*.php');
339         $plugins = $pd->getFiles();
340         unset($pd);
341         sort($plugins);
342         if (!empty($plugins)) {
343             $plugin_js = '';
344             require_once("lib/WikiPlugin.php");
345             $w = new WikiPluginLoader;
346             foreach ($plugins as $plugin) {
347                 $pluginName = str_replace(".php", "", $plugin);
348                 if (in_array($pluginName, $AllAllowedPlugins)) {
349                     $p = $w->getPlugin($pluginName, false); // second arg?
350                     // trap php files which aren't WikiPlugin~s
351                     if (strtolower(substr(get_parent_class($p), 0, 10)) == 'wikiplugin') {
352                         $plugin_args = '';
353                         $desc = $p->getArgumentsDescription();
354                         $src = array("\n",'"',"'",'|','[',']','\\');
355                         $replace = array('%0A','%22','%27','%7C','%5B','%5D','%5C');
356                         $desc = str_replace("<br />",' ',$desc->asXML());
357                         if ($desc)
358                             $plugin_args = ' '.str_replace($src, $replace, $desc);
359                         $toinsert = "%0A<<".$pluginName.$plugin_args.">>"; // args?
360                         $plugin_js .= ",['$pluginName','$toinsert']";
361                     }
362                 }
363             }
364             $plugin_js = substr($plugin_js, 1);
365             $more_buttons = HTML::img(array('class'=>"toolbar",
366                                             'id' => 'tb-plugins',
367                                             'src'  => $WikiTheme->getImageURL("ed_plugins.png"),
368                                             'title'=>_("AddPlugin"),
369                                             'alt'=>_("AddPlugin"),
370                                             'onclick'=>"showPulldown('".
371                                             _("Insert Plugin")
372                                             ."',[".$plugin_js."],'"
373                                             ._("Insert")."','"
374                                             ._("Close")."','tb-plugins')"));
375             return HTML("\n", $more_buttons);
376         }
377         return '';
378     }
379
380     // result is cached. Esp. the args are expensive
381     function pagesPulldown($query, $case_exact=false, $regex='auto') {
382         require_once('lib/TextSearchQuery.php');
383         $dbi =& $GLOBALS['request']->_dbi;
384         $page_iter = $dbi->titleSearch(new TextSearchQuery($query, $case_exact, $regex));
385         if ($page_iter->count() > 0) {
386             global $WikiTheme;
387             $pages = array();
388             while ($p = $page_iter->next()) {
389                 $page = $p->getName();
390                 if (DISABLE_MARKUP_WIKIWORD or (!isWikiWord($page)))
391                     $pages[] = "['$page', '%5B".$page."%5D']";
392                 else
393                     $pages[] = "['$page', '$page']";
394             }
395             return HTML("\n", HTML::img(array('class'=>"toolbar",
396                                               'id' => 'tb-pages',
397                                               'src'  => $WikiTheme->getImageURL("ed_pages.png"),
398                                               'title'=>_("AddPageLink"),
399                                               'alt'=>_("AddPageLink"),
400                                               'onclick'=>"showPulldown('".
401                                               _("Insert PageLink")
402                                               ."',[".join(",",$pages)."],'"
403                                               ._("Insert")."','"
404                                               ._("Close")."','tb-pages')")));
405         }
406         return '';
407     }
408
409     // result is cached. Esp. the args are expensive
410     function imagePulldown($query, $case_exact=false, $regex='auto') {
411         global $WikiTheme;
412
413         $image_dir = getUploadFilePath();
414         $pd = new fileSet($image_dir, '*');
415         $images = $pd->getFiles();
416         unset($pd);
417         if (UPLOAD_USERDIR) {
418             $image_dir .= "/" . $request->_user->_userid;
419             $pd = new fileSet($image_dir, '*');
420             $images = array_merge($images, $pd->getFiles());
421             unset($pd);
422         }
423         sort($images);
424         if (!empty($images)) {
425             $image_js = '';
426             foreach ($images as $image) {
427                 // Select only image and video files
428                 if (is_image($image) or is_video($image)) {
429                     $image_js .= ",['$image','{{".$image."}}']";
430                 }
431             }
432             $image_js = substr($image_js, 1);
433             $more_buttons = HTML::img(array('class'=>"toolbar",
434                                             'id' => 'tb-images',
435                                             'src'  => $WikiTheme->getImageURL("ed_image.png"),
436                                             'title'=>_("Add Image or Video"),
437                                             'alt'=>_("Add Image or Video"),
438                                             'onclick'=>"showPulldown('".
439                                             _("Insert Image or Video")
440                                             ."',[".$image_js."],'"
441                                             ._("Insert")."','"
442                                             ._("Close")."','tb-images')"));
443             return HTML("\n", $more_buttons);
444         }
445         return '';
446     }
447
448     // result is cached. Esp. the args are expensive
449     // FIXME!
450     function templatePulldown($query, $case_exact=false, $regex='auto') {
451         global $request;
452         require_once('lib/TextSearchQuery.php');
453         $dbi =& $request->_dbi;
454         $page_iter = $dbi->titleSearch(new TextSearchQuery($query, $case_exact, $regex));
455         $count = 0;
456         if ($page_iter->count()) {
457             global $WikiTheme;
458             $pages_js = '';
459             while ($p = $page_iter->next()) {
460                 $rev = $p->getCurrentRevision();
461                 $toinsert = str_replace(array("\n",'"'), array('_nl','_quot'), $rev->_get_content());
462                 //$toinsert = str_replace("\n",'\n',addslashes($rev->_get_content()));
463                 $pages_js .= ",['".$p->getName()."','_nl$toinsert']";
464             }
465             $pages_js = substr($pages_js, 1);
466             if (!empty($pages_js))
467                 return HTML("\n", HTML::img
468                             (array('class'=>"toolbar",
469                                    'id' => 'tb-templates',
470                                    'src'  => $WikiTheme->getImageURL("ed_template.png"),
471                                    'title'=>_("AddTemplate"),
472                                    'alt'=>_("AddTemplate"),
473                                    'onclick'=>"showPulldown('".
474                                    _("Insert Template")
475                                    ."',[".$pages_js."],'"
476                                    ._("Insert")."','"
477                                    ._("Close")."','tb-templates')")));
478         }
479         return '';
480     }
481
482 }
483
484 // Local Variables:
485 // mode: php
486 // tab-width: 8
487 // c-basic-offset: 4
488 // c-hanging-comment-ender-p: nil
489 // indent-tabs-mode: nil
490 // End:
491 ?>