]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/EditToolbar.php
make TextSearchQuery->_stoplist localizable and overridable within config.ini
[SourceForge/phpwiki.git] / lib / EditToolbar.php
1 <?php
2 rcs_id('$Id: EditToolbar.php,v 1.5 2005-10-29 14:16:17 rurban Exp $');
3
4 /**
5  * EDIT Toolbar Initialization.
6  * The default/themes/toolbar.js is from mediawiki, this php is written from scratch.
7  *
8  * Features: 
9  * - save-preview and formatting buttons from mediawiki
10  * - Search&Replace from walterzorn.de
11  * - pageinsert popup by Reini Urban (TODO: should be a pulldown, use acdropdown))
12  *
13  */
14
15 class EditToolbar {
16
17     function EditToolbar() {
18         global $WikiTheme;
19
20         $this->tokens = array();
21
22         //FIXME: enable Undo button for all other buttons also, not only the search/replace button
23         if (JS_SEARCHREPLACE) {
24             $this->tokens['JS_SEARCHREPLACE'] = 1;
25             $undo_btn = $WikiTheme->getImageURL("ed_undo.png"); 
26             $undo_d_btn = $WikiTheme->getImageURL("ed_undo_d.png"); 
27             // JS_SEARCHREPLACE from walterzorn.de
28             $WikiTheme->addMoreHeaders(Javascript("
29 var f, sr_undo, replacewin, undo_buffer=new Array(), undo_buffer_index=0;
30
31 function define_f() {
32    f=document.getElementById('editpage');
33    f.editarea=document.getElementById('edit[content]');
34    sr_undo=document.getElementById('sr_undo');
35    undo_enable(false);
36    f.editarea.focus();
37 }
38 function undo_enable(bool) {
39    if (bool) {
40      sr_undo.src='".$undo_btn."';
41      sr_undo.alt='"
42 ._("Undo")
43 ."';
44      sr_undo.disabled = false;
45    } else {
46      sr_undo.src='".$undo_d_btn."';
47      sr_undo.alt='"
48 ._("Undo disabled")
49 ."';
50      sr_undo.disabled = true;
51      if(sr_undo.blur) sr_undo.blur();
52   }
53 }
54 function replace() {
55    replacewin = window.open('','','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes,copyhistory=no,height=90,width=450');
56    replacewin.window.document.write('<html><head><title>"
57 ._("Search & Replace")
58 ."</title><style type=\"text/css\"><'+'!'+'-- body, input {font-family:Tahoma,Arial,Helvetica,sans-serif;font-size:10pt;font-weight:bold;} td {font-size:9pt}  --'+'></style></head><body bgcolor=\"#dddddd\" onload=\"if(document.forms[0].ein.focus) document.forms[0].ein.focus(); return false;\"><form><center><table><tr><td align=\"right\">'+'"
59 ._("Search")
60 .":</td><td align=\"left\"><input type=\"text\" name=\"ein\" size=\"45\" maxlength=\"500\"></td></tr><tr><td align=\"right\">'+' "
61 ._("Replace with")
62 .":</td><td align=\"left\"><input type=\"text\" name=\"aus\" size=\"45\" maxlength=\"500\"></td></tr><tr><td colspan=\"2\" align=\"center\"><input type=\"button\" value=\" "
63 ._("OK")
64 ." \" onclick=\"if(self.opener)self.opener.do_replace(); return false;\">&nbsp;&nbsp;&nbsp;<input type=\"button\" value=\""
65 ._("Close")
66 ."\" onclick=\"self.close(); return false;\"></td></tr></table></center></form></body></html>');
67    replacewin.window.document.close();
68    return false;
69 }
70 function do_replace() {
71    var txt=undo_buffer[undo_buffer_index]=f.editarea.value, ein=new RegExp(replacewin.document.forms[0].ein.value,'g'), aus=replacewin.document.forms[0].aus.value;
72    if (ein==''||ein==null) {
73       if (replacewin) replacewin.window.document.forms[0].ein.focus();
74       return;
75    }
76    var z_repl=txt.match(ein)? txt.match(ein).length : 0;
77    txt=txt.replace(ein,aus);
78    ein=ein.toString().substring(1,ein.toString().length-2);
79    result(z_repl, '"
80 .sprintf(_("Substring \"%s\" found %s times. Replace with \"%s\"?"), "'+ein+'", "'+z_repl+'", "'+aus+'")
81 ."', txt, '"
82 .sprintf(_("String \"%s\" not found."), "'+ein+'")
83 ."');
84    replacewin.window.focus();
85    replacewin.window.document.forms[0].ein.focus();
86    return false;
87 }
88 function result(zahl,frage,txt,alert_txt) {
89    if (zahl>0) {
90       if(window.confirm(frage)==true) {
91          f.editarea.value=txt;
92          undo_save();
93          undo_enable(true);
94       }
95    } else alert(alert_txt);
96 }
97 function do_undo() {
98    if(undo_buffer_index==0) return;
99    else if(undo_buffer_index>0) {
100       f.editarea.value=undo_buffer[undo_buffer_index-1];
101       undo_buffer[undo_buffer_index]=null;
102       undo_buffer_index--;
103       if(undo_buffer_index==0) {
104          alert('".
105 _("Operation undone")
106 ."');
107          undo_enable(false);
108       }
109    }
110 }
111 //save a snapshot in the undo buffer
112 function undo_save() {
113    undo_buffer[undo_buffer_index]=f.editarea.value;
114    undo_buffer_index++;
115    undo_enable(true);
116 }
117 "));
118             $WikiTheme->addMoreAttr('body', "SearchReplace"," onload='define_f()'");
119         } else {
120             $WikiTheme->addMoreAttr('body', "editfocus", "document.getElementById('edit:content]').editarea.focus()");
121         }
122     
123         if (ENABLE_EDIT_TOOLBAR) {
124             $WikiTheme->addMoreHeaders(JavaScript('',array('src' => $WikiTheme->_findData("toolbar.js"))));
125         }
126
127         include_once("lib/WikiPluginCached.php");
128         $cache = WikiPluginCached::newCache();
129         $dbi = $GLOBALS['request']->getDbh();
130         // regenerate if number of pages changes (categories, pages, templates)
131         $key = $dbi->numPages();
132         $key .= '+categories+plugin';
133         if (TOOLBAR_PAGELINK_PULLDOWN) {
134             $key .= "+pages";
135         }
136         if (TOOLBAR_TEMPLATE_PULLDOWN) {
137             $key .= "+templates_" . $dbi->getTimestamp();
138         }
139         $id = $cache->generateId($key);
140         $content = $cache->get($id, 'toolbarcache');
141
142         if (!empty($content)) {
143             $this->tokens['EDIT_TOOLBAR'] =& $content;
144         } else {
145             $content = $this->_generate();
146             // regenerate buttons every 3600 seconds
147             $cache->save($id, $content, '+3600', 'toolbarcache'); 
148             $this->tokens['EDIT_TOOLBAR'] =& $content;
149         }
150     }
151
152     function getTokens () {
153         return $this->tokens;
154     }
155
156     function _generate () {
157         global $WikiTheme;
158
159         $toolbar = "document.writeln(\"<div class=\\\"edit-toolbar\\\" id=\\\"toolbar\\\">\");\n";
160
161         if (ENABLE_EDIT_TOOLBAR) {
162             $toolarray = array(
163                            array(
164                                  "image"=>"ed_format_bold.png",
165                                  "open"=>"*",
166                                  "close"=>"*",
167                                  "sample"=>_("Bold text"),
168                                  "tip"=>_("Bold text")),
169                            array("image"=>"ed_format_italic.png",
170                                  "open"=>"_",
171                                  "close"=>"_",
172                                  "sample"=>_("Italic text"),
173                                  "tip"=>_("Italic text")),
174                            array("image"=>"ed_pagelink.png",
175                                  "open"=>"[",
176                                  "close"=>"]",
177                                  "sample"=>_("optional label | PageName"),
178                                  "tip"=>_("Link to page")),
179                            array("image"=>"ed_link.png",
180                                  "open"=>"[",
181                                  "close"=>"]",
182                                  "sample"=>_("optional label | http://www.example.com"),
183                                  "tip"=>_("External link (remember http:// prefix)")),
184                            array("image"=>"ed_headline.png",
185                                  "open"=>"\\n!!! ",
186                                  "close"=>"\\n",
187                                  "sample"=>_("Headline text"),
188                                  "tip"=>_("Level 1 headline")),
189                            array("image"=>"ed_image.png",
190                                  "open"=>"[ ",
191                                  "close"=>" ]",
192                                  "sample"=>_("Example.jpg"),
193                                  "tip"=>_("Embedded image")),
194                            array("image"=>"ed_nowiki.png",
195                                  "open"=>"\\n\\<verbatim\\>\\n",
196                                  "close"=>"\\n\\</verbatim\\>\\n",
197                                  "sample"=>_("Insert non-formatted text here"),
198                                  "tip"=>_("Ignore wiki formatting")),
199                            array("image"=>"ed_sig.png",
200                                  "open" => " --" . $GLOBALS['request']->_user->UserName(),
201                                  "close" => "",
202                                  "sample"=>"",
203                                  "tip"=>_("Your signature")),
204                            array("image"=>"ed_hr.png",
205                                  "open"=>"\\n----\\n",
206                                  "close"=>"",
207                                  "sample"=>"",
208                                  "tip"=>_("Horizontal line"))
209                            );
210             $btn = new SubmitImageButton(_("Save"), "edit[save]", 'toolbar', 
211                                          $WikiTheme->getImageURL("ed_save.png"));
212             $btn->addTooltip(_("Save"));
213             $toolbar .= ('document.writeln("'.addslashes($btn->asXml()).'");'."\n");
214             $btn = new SubmitImageButton(_("Preview"), "edit[preview]", 'toolbar', 
215                                          $WikiTheme->getImageURL("ed_preview.png"));
216             $btn->addTooltip(_("Preview"));
217             $toolbar .= ('document.writeln("'.addslashes($btn->asXml()).'");'."\n");
218     
219             foreach ($toolarray as $tool) {
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 tip 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                 $tip = addslashes( $tool["tip"] );
229                 $toolbar .= ("addTagButton('$image','$tip','$open','$close','$sample');\n");
230             }
231             $toolbar .= ("addInfobox('" 
232                          . addslashes( _("Click a button to get an example text") ) 
233                          . "');\n");
234         }
235
236         if (JS_SEARCHREPLACE) {
237             $undo_d_btn = $WikiTheme->getImageURL("ed_undo_d.png"); 
238             //$redo_btn = $WikiTheme->getImageURL("ed_redo.png");
239             $sr_btn   = $WikiTheme->getImageURL("ed_replace.png");
240             //TODO: generalize the UNDO button and fix it for Search & Replace
241             $sr_html = HTML(HTML::img
242                             (array('class'=>"toolbar",
243                                    'id'   =>"sr_undo",
244                                    'src'  =>$undo_d_btn,
245                                    'title'=>_("Undo Search & Replace"),
246                                    'alt'  =>_("Undo Search & Replace"),
247                                    //'disabled'=>"disabled",   //non-XHTML conform
248                                    //'onfocus' =>"if(this.blur && undo_buffer_index==0) this.blur()",
249                                    'onclick' =>"do_undo()")),
250                             HTML::img
251                             (array('class'=>"toolbar",
252                                    'src'  => $sr_btn,
253                                    'alt'  =>_("Search & Replace"),
254                                    'title'=>_("Search & Replace"),
255                                    'onclick'=>"replace()")));
256         } else {
257             $sr_html = '';
258         }
259
260         //TODO: delegate these calculations to a seperate popup/pulldown action request
261         // using moacdropdown and xmlrpc:titleSearch
262         // action=pulldown or xmlrpc/soap (see google: WebServiceProxyFactory.createProxyAsync)
263
264         // Button to generate categories, display in extra window as popup and insert
265         $sr_html = HTML($sr_html, $this->categoriesPulldown());
266         // Button to generate plugins, display in extra window as popup and insert
267         $sr_html = HTML($sr_html, $this->pluginPulldown());
268
269         // Button to generate pagenames, display in extra window as popup and insert
270         if (TOOLBAR_PAGELINK_PULLDOWN)
271             $sr_html = HTML($sr_html, $this->pagesPulldown(TOOLBAR_PAGELINK_PULLDOWN));
272         // Button to insert from an template, display pagename in extra window as popup and insert
273         if (TOOLBAR_TEMPLATE_PULLDOWN)
274             $sr_html = HTML($sr_html, $this->templatePulldown(TOOLBAR_TEMPLATE_PULLDOWN));
275
276         // don't use document.write for replace, otherwise self.opener is not defined.
277         $toolbar_end = "document.writeln(\"</div>\");";
278         if ($sr_html)
279             return HTML(Javascript($toolbar),
280                         "\n", $sr_html, "\n",
281                         Javascript($toolbar_end));
282         else
283             return HTML(Javascript($toolbar . $toolbar_end));
284     }
285
286     //TODO: make the result cached
287     function categoriesPulldown() {
288         global $WikiTheme;
289
290         require_once('lib/TextSearchQuery.php');
291         $dbi =& $GLOBALS['request']->_dbi;
292         // KEYWORDS formerly known as $KeywordLinkRegexp
293         $pages = $dbi->titleSearch(new TextSearchQuery(KEYWORDS, true));
294         if ($pages) {
295             $categories = array();
296             while ($p = $pages->next()){
297                 $categories[] = $p->getName();
298             }
299             if (!$categories) return '';
300             $more_buttons = HTML::img(array('class'=>"toolbar",
301                                             'src'  => $WikiTheme->getImageURL("ed_category.png"),
302                                             'title'=>_("AddCategory"),
303                                             'alt'=>_("AddCategory"),
304                                             'onclick'=>"showPulldown('".
305                                             _("Insert Categories (double-click)")
306                                             ."',['".join("','",$categories)."'],'"
307                                             ._("Insert")."','"
308                                             ._("Close")."')"));
309             return HTML("\n", $more_buttons);
310         }
311         return '';
312     }
313
314     //TODO: Make the result cached. Esp. the args are expensive
315     function pluginPulldown() {
316         global $WikiTheme;
317
318         $plugin_dir = 'lib/plugin';
319         if (defined('PHPWIKI_DIR'))
320             $plugin_dir = PHPWIKI_DIR . "/$plugin_dir";
321         $pd = new fileSet($plugin_dir, '*.php');
322         $plugins = $pd->getFiles();
323         unset($pd);
324         sort($plugins);
325         if (!empty($plugins)) {
326             $plugin_js = '';
327             require_once("lib/WikiPlugin.php");
328             $w = new WikiPluginLoader;
329             foreach ($plugins as $plugin) {
330                 $pluginName = str_replace(".php", "", $plugin);
331                 $p = $w->getPlugin($pluginName, false); // second arg?
332                 // trap php files which aren't WikiPlugin~s
333                 if (strtolower(substr(get_parent_class($p), 0, 10)) == 'wikiplugin') {
334                     $plugin_args = '';
335                     $desc = $p->getArgumentsDescription();
336                     $src = array("\n",'"',"'",'|','[',']','\\');
337                     $replace = array('%0A','%22','%27','%7C','%5B','%5D','%5C');
338                     $desc = str_replace("<br />",' ',$desc->asXML());
339                     if ($desc)
340                         $plugin_args = '\n'.str_replace($src, $replace, $desc);
341                     $toinsert = "%0A<?plugin ".$pluginName.$plugin_args."?>"; // args?
342                     $plugin_js .= ",['$pluginName','$toinsert']";
343                 }
344             }
345             $plugin_js = substr($plugin_js, 1);
346             $more_buttons = HTML::img(array('class'=>"toolbar",
347                                             'src'  => $WikiTheme->getImageURL("ed_plugins.png"),
348                                             'title'=>_("AddPlugin"),
349                                             'alt'=>_("AddPlugin"),
350                                             'onclick'=>"showPulldown('".
351                                             _("Insert Plugin (double-click)")
352                                             ."',[".$plugin_js."],'"
353                                             ._("Insert")."','"
354                                             ._("Close")."')"));
355             return HTML("\n", $more_buttons);
356         }
357         return '';
358     }
359
360     function pagesPulldown($query, $case_exact=false, $regex='auto') {
361         require_once('lib/TextSearchQuery.php');
362         $dbi =& $GLOBALS['request']->_dbi;
363         $page_iter = $dbi->titleSearch(new TextSearchQuery($query, $case_exact, $regex));
364         if ($page_iter->count()) {
365             global $WikiTheme;
366             $pages = array();
367             while ($p = $page_iter->next()){
368                 $pages[] = $p->getName();
369             }
370             return HTML("\n", HTML::img(array('class'=>"toolbar",
371                                               'src'  => $WikiTheme->getImageURL("ed_pages.png"),
372                                               'title'=>_("AddPageLink"),
373                                               'alt'=>_("AddPageLink"),
374                                               'onclick'=>"showPulldown('".
375                                               _("Insert PageLink (double-click)")
376                                               ."',['".join("','",$pages)."'],'"
377                                               ._("Insert")."','"
378                                               ._("Close")."')")));
379         }
380         return '';
381     }
382
383     //TODO: make the result cached
384     function templatePulldown($query, $case_exact=false, $regex='auto') {
385         require_once('lib/TextSearchQuery.php');
386         $dbi =& $GLOBALS['request']->_dbi;
387         $page_iter = $dbi->titleSearch(new TextSearchQuery($query, $case_exact, $regex));
388         $count = 0;
389         if ($page_iter->count()) {
390             global $WikiTheme;
391             $pages_js = '';
392             while ($p = $page_iter->next()) {
393                 $rev = $p->getCurrentRevision();
394                 $src = array("\n",'"');
395                 $replace = array('_nl','_quot'); 
396                 $toinsert = str_replace($src, $replace, $rev->_get_content());
397                 //$toinsert = str_replace("\n",'\n',addslashes($rev->_get_content()));
398                 $pages_js .= ",['".$p->getName()."','_nl$toinsert']";
399             }
400             $pages_js = substr($pages_js, 1);
401             if (!empty($pages_js))
402                 return HTML("\n", HTML::img
403                             (array('class'=>"toolbar",
404                                    'src'  => $WikiTheme->getImageURL("ed_template.png"),
405                                    'title'=>_("AddTemplate"),
406                                    'alt'=>_("AddTemplate"),
407                                    'onclick'=>"showPulldown('".
408                                    _("Insert Template (double-click)")
409                                    ."',[".$pages_js."],'"
410                                    ._("Insert")."','"
411                                    ._("Close")."')")));
412         }
413         return '';
414     }
415
416 }
417
418 /*
419  $Log: not supported by cvs2svn $
420  Revision 1.4  2005/09/29 23:07:58  rurban
421  cache toolbar
422
423  Revision 1.3  2005/09/26 06:25:50  rurban
424  EditToolbar enhancements by Thomas Harding: add plugins args, properly quote control chars. added plugin method getArgumentsDescription to override the default description string
425
426  Revision 1.3  2005/09/22 13:40:00 tharding
427  add modules arguments
428  
429  Revision 1.2  2005/05/06 18:43:41  rurban
430  add AddTemplate EditToolbar icon
431
432  Revision 1.1  2005/01/25 15:19:09  rurban
433  extract Toolbar code from editpage.php
434
435
436 */
437
438 // Local Variables:
439 // mode: php
440 // tab-width: 8
441 // c-basic-offset: 4
442 // c-hanging-comment-ender-p: nil
443 // indent-tabs-mode: nil
444 // End:
445 ?>