2 rcs_id('$Id: editpage.php,v 1.80 2004-11-25 17:20:51 rurban Exp $');
4 require_once('lib/Template.php');
6 // USE_HTMLAREA - Support for some WYSIWYG HTML Editor
7 // Not yet enabled, since we cannot convert HTML to Wiki Markup yet.
8 // (See HtmlParser.php for the ongoing efforts)
9 // We might use a HTML PageType, which is contra wiki, but some people might prefer HTML markup.
10 // TODO: Change from constant to user preference variable (checkbox setting),
11 // when HtmlParser is finished.
12 if (!defined('USE_HTMLAREA')) define('USE_HTMLAREA',false);
13 if (USE_HTMLAREA) require_once('lib/htmlarea.php');
17 function PageEditor (&$request) {
18 $this->request = &$request;
20 $this->user = $request->getUser();
21 $this->page = $request->getPage();
23 $this->current = $this->page->getCurrentRevision(false);
25 // HACKish short circuit to browse on action=create
26 if ($request->getArg('action') == 'create') {
27 if (! $this->current->hasDefaultContents())
28 $request->redirect(WikiURL($this->page->getName())); // noreturn
32 $this->meta = array('author' => $this->user->getId(),
33 'author_id' => $this->user->getAuthenticatedId(),
36 $this->tokens = array();
38 $version = $request->getArg('version');
39 if ($version !== false) {
40 $this->selected = $this->page->getRevision($version);
41 $this->version = $version;
44 $this->version = $this->current->getVersion();
45 $this->selected = $this->page->getRevision($this->version);
48 if ($this->_restoreState()) {
49 $this->_initialEdit = false;
52 $this->_initializeState();
53 $this->_initialEdit = true;
55 // The edit request has specified some initial content from a template
56 if ( ($template = $request->getArg('template')) and
57 $request->_dbi->isWikiPage($template)) {
58 $page = $request->_dbi->getPage($template);
59 $current = $page->getCurrentRevision();
60 $this->_content = $current->getPackedContent();
61 } elseif ($initial_content = $request->getArg('initial_content')) {
62 $this->_content = $initial_content;
63 $this->_redirect_to = $request->getArg('save_and_redirect_to');
67 header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
70 function editPage () {
73 $tokens = &$this->tokens;
75 if (! $this->canEdit()) {
76 if ($this->isInitialEdit())
77 return $this->viewSource();
78 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
80 elseif ($this->request->getArg('save_and_redirect_to') != "") {
81 if ($this->savePage()) {
83 $this->request->redirect(WikiURL($this->request->getArg('save_and_redirect_to')));
84 return true; // Page saved.
88 elseif ($this->editaction == 'save') {
89 if ($this->savePage()) {
90 return true; // Page saved.
95 if ($saveFailed || $this->isConcurrentUpdate())
97 // Get the text of the original page, and the two conflicting edits
98 // The diff3 class takes arrays as input. So retrieve content as
99 // an array, or convert it as necesary.
100 $orig = $this->page->getRevision($this->_currentVersion);
101 // FIXME: what if _currentVersion has be deleted?
102 $orig_content = $orig->getContent();
103 $this_content = explode("\n", $this->_content);
104 $other_content = $this->current->getContent();
105 include_once("lib/diff3.php");
106 $diff = new diff3($orig_content, $this_content, $other_content);
107 $output = $diff->merged_output(_("Your version"), _("Other version"));
108 // Set the content of the textarea to the merged diff
109 // output, and update the version
110 $this->_content = implode ("\n", $output);
111 $this->_currentVersion = $this->current->getVersion();
112 $this->version = $this->_currentVersion;
113 $unresolved = $diff->ConflictingBlocks;
114 $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage($unresolved);
117 if ($this->editaction == 'preview')
118 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
120 // FIXME: NOT_CURRENT_MESSAGE?
121 $tokens = array_merge($tokens, $this->getFormElements());
123 //FIXME: enable Undo button for all other buttons also, not only the search/replace button
124 if (defined('JS_SEARCHREPLACE') and JS_SEARCHREPLACE) {
125 $tokens['JS_SEARCHREPLACE'] = 1;
126 $undo_btn = $WikiTheme->getImageURL("ed_undo.gif");
127 $undo_d_btn = $WikiTheme->getImageURL("ed_undo_d.gif");
128 // JS_SEARCHREPLACE from walterzorn.de
129 $WikiTheme->addMoreHeaders(Javascript("
130 var f, sr_undo, replacewin, undo_buffer=new Array(), undo_buffer_index=0;
132 function define_f() {
133 f=document.getElementById('editpage');
134 f.editarea=document.getElementById('edit[content]');
135 sr_undo=document.getElementById('sr_undo');
139 function undo_enable(bool) {
141 sr_undo.src='".$undo_btn."';
145 sr_undo.disabled = false;
147 sr_undo.src='".$undo_d_btn."';
151 sr_undo.disabled = true;
152 if(sr_undo.blur) sr_undo.blur();
156 replacewin = window.open('','','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes,copyhistory=no,height=90,width=450');
157 replacewin.window.document.write('<html><head><title>"
158 ._("Search & Replace")
159 ."</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\">'+'"
161 .":</td><td align=\"left\"><input type=\"text\" name=\"ein\" size=\"45\" maxlength=\"500\"></td></tr><tr><td align=\"right\">'+' "
163 .":</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=\" "
165 ." \" onclick=\"if(self.opener)self.opener.do_replace(); return false;\"> <input type=\"button\" value=\""
167 ."\" onclick=\"self.close(); return false;\"></td></tr></table></center></form></body></html>');
168 replacewin.window.document.close();
171 function do_replace() {
172 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;
173 if (ein==''||ein==null) {
174 if (replacewin) replacewin.window.document.forms[0].ein.focus();
177 var z_repl=txt.match(ein)? txt.match(ein).length : 0;
178 txt=txt.replace(ein,aus);
179 ein=ein.toString().substring(1,ein.toString().length-2);
180 result(z_repl, 'Substring \"'+ein+'\" found '+z_repl+' times. Replace with \"'+aus+'\"?', txt, 'String \"'+ein+'\" not found.');
181 replacewin.window.focus();
182 replacewin.window.document.forms[0].ein.focus();
185 function result(zahl,frage,txt,alert_txt) {
187 if(window.confirm(frage)==true) {
188 f.editarea.value=txt;
192 } else alert(alert_txt);
195 if(undo_buffer_index==0) return;
196 else if(undo_buffer_index>0) {
197 f.editarea.value=undo_buffer[undo_buffer_index-1];
198 undo_buffer[undo_buffer_index]=null;
200 if(undo_buffer_index==0) {
202 _("Operation undone")
208 //save a snapshot in the undo buffer (unused)
209 function undo_save() {
210 undo_buffer[undo_buffer_index]=f.editarea.value;
215 $WikiTheme->addMoreAttr('body'," onload='define_f()'");
217 $WikiTheme->addMoreAttr('body',"document.getElementById('edit[content]').editarea.focus()");
219 if (defined('ENABLE_EDIT_TOOLBAR') and ENABLE_EDIT_TOOLBAR) {
220 $WikiTheme->addMoreHeaders(JavaScript('',array('src' => $WikiTheme->_findData("toolbar.js"))));
221 $tokens['EDIT_TOOLBAR'] = $this->toolbar();
223 $tokens['EDIT_TOOLBAR'] = '';
226 return $this->output('editpage', _("Edit: %s"));
229 function toolbar () {
233 "image"=>"ed_format_bold.gif",
236 "sample"=>_("Bold text"),
237 "tip"=>_("Bold text")),
238 array("image"=>"ed_format_italic.gif",
241 "sample"=>_("Italic text"),
242 "tip"=>_("Italic text")),
243 array("image"=>"ed_pagelink.gif",
246 "sample"=>_("optional label | PageName"),
247 "tip"=>_("Link to page")),
248 array("image"=>"ed_link.gif",
251 "sample"=>_("optional label | http://www.example.com"),
252 "tip"=>_("External link (remember http:// prefix)")),
253 array("image"=>"ed_headline.gif",
256 "sample"=>_("Headline text"),
257 "tip"=>_("Level 1 headline")),
258 array("image"=>"ed_image.gif",
261 "sample"=>_("Example.jpg"),
262 "tip"=>_("Embedded image")),
263 array("image"=>"ed_nowiki.gif",
264 "open"=>"\\n\\<verbatim\\>\\n",
265 "close"=>"\\n\\</verbatim\\>\\n",
266 "sample"=>_("Insert non-formatted text here"),
267 "tip"=>_("Ignore wiki formatting")),
268 array("image"=>"ed_sig.gif",
269 "open" => " --" . $GLOBALS['request']->_user->UserName(),
272 "tip"=>_("Your signature")),
273 array("image"=>"ed_hr.gif",
274 "open"=>"\\n----\\n",
277 "tip"=>_("Horizontal line"))
279 $toolbar = "document.writeln(\"<div class=\\\"edit-toolbar\\\" id=\\\"toolbar\\\">\");\n";
281 $btn = new SubmitImageButton(_("Save"), "edit[save]", 'toolbar', $WikiTheme->getImageURL("ed_save.gif"));
282 $btn->addTooltip(_("Save"));
283 $toolbar.='document.writeln("'.addslashes($btn->asXml()).'");'."\n";
284 $btn = new SubmitImageButton(_("Preview"), "edit[preview]", 'toolbar', $WikiTheme->getImageURL("ed_preview.gif"));
285 $btn->addTooltip(_("Preview"));
286 $toolbar.='document.writeln("'.addslashes($btn->asXml()).'");'."\n";
288 foreach ($toolarray as $tool) {
289 $image = $WikiTheme->getImageURL($tool["image"]);
290 $open = $tool["open"];
291 $close = $tool["close"];
292 $sample = addslashes( $tool["sample"] );
293 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
294 // Older browsers show a "speedtip" type message only for ALT.
295 // Ideally these should be different, realistically they
296 // probably don't need to be.
297 $tip = addslashes( $tool["tip"] );
298 $toolbar.="addTagButton('$image','$tip','$open','$close','$sample');\n";
300 $toolbar.="addInfobox('" . addslashes( _("Click a button to get an example text") ) . "');\n";
302 if (JS_SEARCHREPLACE) {
303 $undo_d_btn = $WikiTheme->getImageURL("ed_undo_d.gif");
304 //$redo_btn = $WikiTheme->getImageURL("ed_redo.gif");
305 $sr_btn = $WikiTheme->getImageURL("ed_replace.gif");
306 $sr_html = HTML(HTML::img(array('class'=>"toolbar",
309 'title'=>_("Undo Search & Replace"),
310 'alt' =>_("Undo Search & Replace"),
311 'disabled'=>"disabled",
313 'onfocus' =>"if(this.blur && undo_buffer_index==0) this.blur()",
314 'onclick' =>"do_undo()")),
315 HTML::img(array('class'=>"toolbar",
317 'alt' =>_("Search & Replace"),
318 'title'=>_("Search & Replace"),
319 'onclick'=>"replace()")));
324 // Button to generate pagenames, display in extra window as pulldown and insert
325 // Button to generate plugins, display in extra window as pulldown and insert
326 // Button to generate categories, display in extra window as pulldown and insert
327 if (DEBUG and JS_SEARCHREPLACE) {
328 //TODO: delegate this calculation to a seperate pulldown action request
329 require_once('lib/TextSearchQuery.php');
330 $dbi =& $GLOBALS['request']->_dbi;
331 $pages = $dbi->titleSearch(new TextSearchQuery(''.
332 _("Category").' OR '.
334 if ($pages->count()) {
335 $categories = array();
336 while ($p = $pages->next()){
337 $categories[] = $p->getName();
339 $more_buttons = HTML::img(array('class'=>"toolbar",
340 'src' => $WikiTheme->getImageURL("ed_category.gif"),
341 'title'=>_("AddCategory"),
342 'onclick'=>"showPulldown('".
343 _("Insert Categories double-click")
344 ."',['".join("','",$categories)."'])"));
345 if ($sr_html) $sr_html = HTML($sr_html, $more_buttons);
346 else $sr_html = $more_buttons;
349 $toolbar_end = "document.writeln(\"</div>\");";
350 // don't use document.write for replace, otherwise self.opener is not defined.
352 return HTML(Javascript($toolbar),
354 Javascript($toolbar_end));
356 return HTML(Javascript($toolbar . $toolbar_end));
359 function output ($template, $title_fs) {
361 $selected = &$this->selected;
362 $current = &$this->current;
364 if ($selected && $selected->getVersion() != $current->getVersion()) {
366 $pagelink = WikiLink($selected);
370 $pagelink = WikiLink($this->page);
374 $title = new FormattedText ($title_fs, $pagelink);
375 if (USE_HTMLAREA and $template == 'editpage') {
376 $WikiTheme->addMoreHeaders(Edit_HtmlArea_Head());
377 //$tokens['PAGE_SOURCE'] = Edit_HtmlArea_ConvertBefore($this->_content);
379 $template = Template($template, $this->tokens);
380 GeneratePage($template, $title, $rev);
385 function viewSource () {
386 assert($this->isInitialEdit());
387 assert($this->selected);
389 $this->tokens['PAGE_SOURCE'] = $this->_content;
390 return $this->output('viewsource', _("View Source: %s"));
393 function updateLock() {
394 if ((bool)$this->page->get('locked') == (bool)$this->locked)
395 return false; // Not changed.
397 if (!$this->user->isAdmin()) {
398 // FIXME: some sort of message
399 return false; // not allowed.
402 $this->page->set('locked', (bool)$this->locked);
403 $this->tokens['LOCK_CHANGED_MSG']
404 = $this->locked ? _("Page now locked.") : _("Page now unlocked.");
406 return true; // lock changed.
409 function savePage () {
410 $request = &$this->request;
412 if ($this->isUnchanged()) {
413 // Allow admin lock/unlock even if
414 // no text changes were made.
415 if ($this->updateLock()) {
416 $dbi = $request->getDbh();
419 // Save failed. No changes made.
420 $this->_redirectToBrowsePage();
421 // user will probably not see the rest of this...
422 include_once('lib/display.php');
423 // force browse of current version:
424 $request->setArg('version', false);
425 displayPage($request, 'nochanges');
429 $page = &$this->page;
431 // Include any meta-data from original page version which
432 // has not been explicitly updated.
433 // (Except don't propagate pgsrc_version --- moot for now,
434 // because at present it never gets into the db...)
435 $meta = $this->selected->getMetaData();
436 unset($meta['pgsrc_version']);
437 $meta = array_merge($meta, $this->meta);
440 $this->_content = $this->getContent();
441 $newrevision = $page->save($this->_content, $this->_currentVersion + 1, $meta);
442 if (!isa($newrevision, 'wikidb_pagerevision')) {
443 // Save failed. (Concurrent updates).
447 // New contents successfully saved...
450 // Clean out archived versions of this page.
451 include_once('lib/ArchiveCleaner.php');
452 $cleaner = new ArchiveCleaner($GLOBALS['ExpireParams']);
453 $cleaner->cleanPageRevisions($page);
455 /* generate notification emails done in WikiDB::save to catch all direct calls
458 $dbi = $request->getDbh();
459 $warnings = $dbi->GenericWarnings();
463 if (empty($warnings) && ! $WikiTheme->getImageURL('signature')) {
464 // Do redirect to browse page if no signature has
465 // been defined. In this case, the user will most
466 // likely not see the rest of the HTML we generate
468 $this->_redirectToBrowsePage();
471 // Force browse of current page version.
472 $request->setArg('version', false);
473 //$request->setArg('action', false);
475 $template = Template('savepage', $this->tokens);
476 $template->replace('CONTENT', $newrevision->getTransformedContent());
477 if (!empty($warnings))
478 $template->replace('WARNINGS', $warnings);
480 $pagelink = WikiLink($page);
482 GeneratePage($template, fmt("Saved: %s", $pagelink), $newrevision);
486 function isConcurrentUpdate () {
487 assert($this->current->getVersion() >= $this->_currentVersion);
488 return $this->current->getVersion() != $this->_currentVersion;
491 function canEdit () {
492 return !$this->page->get('locked') || $this->user->isAdmin();
495 function isInitialEdit () {
496 return $this->_initialEdit;
499 function isUnchanged () {
500 $current = &$this->current;
502 if ($this->meta['markup'] != $current->get('markup'))
505 return $this->_content == $current->getPackedContent();
508 function getPreview () {
509 include_once('lib/PageType.php');
510 $this->_content = $this->getContent();
511 return new TransformedText($this->page, $this->_content, $this->meta);
514 // possibly convert HTMLAREA content back to Wiki markup
515 function getContent () {
517 $xml_output = Edit_HtmlArea_ConvertAfter($this->_content);
518 $this->_content = join("",$xml_output->_content);
519 return $this->_content;
521 return $this->_content;
525 function getLockedMessage () {
527 HTML(HTML::h2(_("Page Locked")),
528 HTML::p(_("This page has been locked by the administrator so your changes can not be saved.")),
529 HTML::p(_("(Copy your changes to the clipboard. You can try editing a different page or save your text in a text editor.)")),
530 HTML::p(_("Sorry for the inconvenience.")));
533 function getConflictMessage ($unresolved = false) {
535 xgettext only knows about c/c++ line-continuation strings
536 it does not know about php's dot operator.
537 We want to translate this entire paragraph as one string, of course.
540 //$re_edit_link = Button('edit', _("Edit the new version"), $this->page);
543 $message = HTML::p(fmt("Some of the changes could not automatically be combined. Please look for sections beginning with '%s', and ending with '%s'. You will need to edit those sections by hand before you click Save.",
544 "<<<<<<< ". _("Your version"),
545 ">>>>>>> ". _("Other version")));
547 $message = HTML::p(_("Please check it through before saving."));
551 /*$steps = HTML::ol(HTML::li(_("Copy your changes to the clipboard or to another temporary place (e.g. text editor).")),
552 HTML::li(fmt("%s of the page. You should now see the most current version of the page. Your changes are no longer there.",
554 HTML::li(_("Make changes to the file again. Paste your additions from the clipboard (or text editor).")),
555 HTML::li(_("Save your updated changes.")));
558 HTML(HTML::h2(_("Conflicting Edits!")),
559 HTML::p(_("In the time since you started editing this page, another user has saved a new version of it.")),
560 HTML::p(_("Your changes can not be saved as they are, since doing so would overwrite the other author's changes. So, your changes and those of the other author have been combined. The result is shown below.")),
565 function getTextArea () {
566 $request = &$this->request;
568 // wrap=virtual is not HTML4, but without it NS4 doesn't wrap
570 $readonly = ! $this->canEdit(); // || $this->isConcurrentUpdate();
572 $html = $this->getPreview();
573 $this->_wikicontent = $this->_content;
574 $this->_content = $html->asXML();
577 /** <textarea wrap="virtual"> is not valid xhtml but Netscape 4 requires it
578 * to wrap long lines.
580 $textarea = HTML::textarea(array('class' => 'wikiedit',
581 'name' => 'edit[content]',
582 'id' => 'edit[content]',
583 'rows' => $request->getPref('editHeight'),
584 'cols' => $request->getPref('editWidth'),
585 'readonly' => (bool) $readonly),
588 $textarea->setAttr('wrap','virtual');
590 return Edit_HtmlArea_Textarea($textarea,$this->_wikicontent,'edit[content]');
595 function getFormElements () {
596 $request = &$this->request;
597 $page = &$this->page;
600 $h = array('action' => 'edit',
601 'pagename' => $page->getName(),
602 'version' => $this->version,
603 'edit[pagetype]' => $this->meta['pagetype'],
604 'edit[current_version]' => $this->_currentVersion);
606 $el['HIDDEN_INPUTS'] = HiddenInputs($h);
607 $el['EDIT_TEXTAREA'] = $this->getTextArea();
609 = HTML::input(array('type' => 'text',
610 'class' => 'wikitext',
611 'name' => 'edit[summary]',
614 'value' => $this->meta['summary']));
616 = HTML::input(array('type' => 'checkbox',
617 'name' => 'edit[minor_edit]',
618 'checked' => (bool) $this->meta['is_minor_edit']));
620 = HTML::input(array('type' => 'checkbox',
621 'name' => 'edit[markup]',
623 'checked' => $this->meta['markup'] < 2.0,
624 'id' => 'useOldMarkup',
625 'onclick' => 'showOldMarkupRules(this.checked)'));
628 = HTML::input(array('type' => 'checkbox',
629 'name' => 'edit[locked]',
630 'disabled' => (bool) !$this->user->isadmin(),
631 'checked' => (bool) $this->locked));
633 $el['PREVIEW_B'] = Button('submit:edit[preview]', _("Preview"),
636 //if (!$this->isConcurrentUpdate() && $this->canEdit())
637 $el['SAVE_B'] = Button('submit:edit[save]', _("Save"), 'wikiaction');
639 $el['IS_CURRENT'] = $this->version == $this->current->getVersion();
644 function _redirectToBrowsePage() {
645 $this->request->redirect(WikiURL($this->page, false, 'absolute_url'));
649 function _restoreState () {
650 $request = &$this->request;
652 $posted = $request->getArg('edit');
653 $request->setArg('edit', false);
655 if (!$posted || !$request->isPost()
656 || $request->getArg('action') != 'edit')
659 if (!isset($posted['content']) || !is_string($posted['content']))
661 $this->_content = preg_replace('/[ \t\r]+\n/', "\n",
662 rtrim($posted['content']));
663 $this->_content = $this->getContent();
665 $this->_currentVersion = (int) $posted['current_version'];
667 if ($this->_currentVersion < 0)
669 if ($this->_currentVersion > $this->current->getVersion())
670 return false; // FIXME: some kind of warning?
672 $is_old_markup = !empty($posted['markup']) && $posted['markup'] == 'old';
673 $meta['markup'] = $is_old_markup ? false : 2.0;
674 $meta['summary'] = trim(substr($posted['summary'], 0, 256));
675 $meta['is_minor_edit'] = !empty($posted['minor_edit']);
676 $meta['pagetype'] = !empty($posted['pagetype']) ? $posted['pagetype'] : false;
677 $this->meta = array_merge($this->meta, $meta);
678 $this->locked = !empty($posted['locked']);
680 if (!empty($posted['preview']))
681 $this->editaction = 'preview';
682 elseif (!empty($posted['save']))
683 $this->editaction = 'save';
685 $this->editaction = 'edit';
690 function _initializeState () {
691 $request = &$this->request;
692 $current = &$this->current;
693 $selected = &$this->selected;
694 $user = &$this->user;
697 NoSuchRevision($request, $this->page, $this->version); // noreturn
699 $this->_currentVersion = $current->getVersion();
700 $this->_content = $selected->getPackedContent();
702 $this->meta['summary'] = '';
703 $this->locked = $this->page->get('locked');
705 // If author same as previous author, default minor_edit to on.
706 $age = $this->meta['mtime'] - $current->get('mtime');
707 $this->meta['is_minor_edit'] = ( $age < MINOR_EDIT_TIMEOUT
708 && $current->get('author') == $user->getId()
711 // Default for new pages is new-style markup.
712 if ($selected->hasDefaultContents())
713 $is_new_markup = true;
715 $is_new_markup = $selected->get('markup') >= 2.0;
717 $this->meta['markup'] = $is_new_markup ? 2.0: false;
718 $this->meta['pagetype'] = $selected->get('pagetype');
719 $this->editaction = 'edit';
723 class LoadFileConflictPageEditor
726 function editPage ($saveFailed = true) {
727 $tokens = &$this->tokens;
729 if (!$this->canEdit()) {
730 if ($this->isInitialEdit())
731 return $this->viewSource();
732 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
734 elseif ($this->editaction == 'save') {
735 if ($this->savePage())
736 return true; // Page saved.
740 if ($saveFailed || $this->isConcurrentUpdate())
742 // Get the text of the original page, and the two conflicting edits
743 // The diff class takes arrays as input. So retrieve content as
744 // an array, or convert it as necesary.
745 $orig = $this->page->getRevision($this->_currentVersion);
746 $this_content = explode("\n", $this->_content);
747 $other_content = $this->current->getContent();
748 include_once("lib/diff.php");
749 $diff2 = new Diff($other_content, $this_content);
750 $context_lines = max(4, count($other_content) + 1,
751 count($this_content) + 1);
752 $fmt = new BlockDiffFormatter($context_lines);
754 $this->_content = $fmt->format($diff2);
755 // FIXME: integrate this into class BlockDiffFormatter
756 $this->_content = str_replace(">>>>>>>\n<<<<<<<\n", "=======\n",
758 $this->_content = str_replace("<<<<<<<\n>>>>>>>\n", "=======\n",
761 $this->_currentVersion = $this->current->getVersion();
762 $this->version = $this->_currentVersion;
763 $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage();
766 if ($this->editaction == 'preview')
767 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
769 // FIXME: NOT_CURRENT_MESSAGE?
771 $tokens = array_merge($tokens, $this->getFormElements());
773 return $this->output('editpage', _("Merge and Edit: %s"));
774 // FIXME: this doesn't display
777 function output ($template, $title_fs) {
778 $selected = &$this->selected;
779 $current = &$this->current;
781 if ($selected && $selected->getVersion() != $current->getVersion()) {
783 $pagelink = WikiLink($selected);
787 $pagelink = WikiLink($this->page);
790 $title = new FormattedText ($title_fs, $pagelink);
791 $template = Template($template, $this->tokens);
793 //GeneratePage($template, $title, $rev);
797 function getConflictMessage () {
798 $message = HTML(HTML::p(fmt("Some of the changes could not automatically be combined. Please look for sections beginning with '%s', and ending with '%s'. You will need to edit those sections by hand before you click Save.",
801 HTML::p(_("Please check it through before saving."))));
807 $Log: not supported by cvs2svn $
808 Revision 1.79 2004/11/21 11:59:20 rurban
809 remove final \n to be ob_cache independent
811 Revision 1.78 2004/11/16 17:57:45 rurban
812 fix search&replace button
813 use new addTagButton machinery
814 new showPulldown for categories, TODO: in a seperate request
816 Revision 1.77 2004/11/15 15:52:35 rurban
819 Revision 1.76 2004/11/15 15:37:34 rurban
821 don't use document.write for replace, otherwise self.opener is not defined.
823 Revision 1.75 2004/09/16 08:00:52 rurban
826 Revision 1.74 2004/07/03 07:36:28 rurban
827 do not get unneccessary content
829 Revision 1.73 2004/06/16 21:23:44 rurban
830 fixed non-object fatal #215
832 Revision 1.72 2004/06/14 11:31:37 rurban
833 renamed global $Theme to $WikiTheme (gforge nameclash)
834 inherit PageList default options from PageList
835 default sortby=pagename
836 use options in PageList_Selectable (limit, sortby, ...)
837 added action revert, with button at action=diff
838 added option regex to WikiAdminSearchReplace
840 Revision 1.71 2004/06/03 18:06:29 rurban
841 fix file locking issues (only needed on write)
842 fixed immediate LANG and THEME in-session updates if not stored in prefs
843 advanced editpage toolbars (search & replace broken)
845 Revision 1.70 2004/06/02 20:47:47 rurban
846 dont use the wikiaction class
848 Revision 1.69 2004/06/02 10:17:56 rurban
849 integrated search/replace into toolbar
850 added save+preview buttons
852 Revision 1.68 2004/06/01 15:28:00 rurban
853 AdminUser only ADMIN_USER not member of Administrators
854 some RateIt improvements by dfrankow
857 Revision _1.6 2004/05/26 15:48:00 syilek
858 fixed problem with creating page with slashes from one true page
860 Revision _1.5 2004/05/25 16:51:53 syilek
861 added ability to create a page from the category page and not have to edit it
863 Revision 1.67 2004/05/27 17:49:06 rurban
864 renamed DB_Session to DbSession (in CVS also)
865 added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
866 remove leading slash in error message
867 added force_unlock parameter to File_Passwd (no return on stale locks)
868 fixed adodb session AffectedRows
869 added FileFinder helpers to unify local filenames and DATA_PATH names
870 editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
872 Revision 1.66 2004/04/29 23:25:12 rurban
873 re-ordered locale init (as in 1.3.9)
874 fixed loadfile with subpages, and merge/restore anyway
877 Revision 1.65 2004/04/18 01:11:52 rurban
878 more numeric pagename fixes.
879 fixed action=upload with merge conflict warnings.
880 charset changed from constant to global (dynamic utf-8 switching)
882 Revision 1.64 2004/04/06 19:48:56 rurban
883 temp workaround for action=edit AddComment form
885 Revision 1.63 2004/03/24 19:39:02 rurban
886 php5 workaround code (plus some interim debugging code in XmlElement)
887 php5 doesn't work yet with the current XmlElement class constructors,
888 WikiUserNew does work better than php4.
889 rewrote WikiUserNew user upgrading to ease php5 update
890 fixed pref handling in WikiUserNew
891 added Email Notification
892 added simple Email verification
893 removed emailVerify userpref subclass: just a email property
894 changed pref binary storage layout: numarray => hash of non default values
895 print optimize message only if really done.
896 forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
897 prefs should be stored in db or homepage, besides the current session.
899 Revision 1.62 2004/03/17 18:41:05 rurban
900 initial_content and template support for CreatePage
902 Revision 1.61 2004/03/12 20:59:17 rurban
903 important cookie fix by Konstantin Zadorozhny
904 new editpage feature: JS_SEARCHREPLACE
906 Revision 1.60 2004/02/15 21:34:37 rurban
907 PageList enhanced and improved.
908 fixed new WikiAdmin... plugins
909 editpage, Theme with exp. htmlarea framework
910 (htmlarea yet committed, this is really questionable)
911 WikiUser... code with better session handling for prefs
912 enhanced UserPreferences (again)
913 RecentChanges for show_deleted: how should pages be deleted then?
915 Revision 1.59 2003/12/07 20:35:26 carstenklapp
916 Bugfix: Concurrent updates broken since after 1.3.4 release: Fatal
917 error: Call to undefined function: gettransformedcontent() in
918 /home/groups/p/ph/phpwiki/htdocs/phpwiki2/lib/editpage.php on line
921 Revision 1.58 2003/03/10 18:25:22 dairiki
922 Bug/typo fix. If you use the edit page to un/lock a page, it
923 failed with: Fatal error: Call to a member function on a
924 non-object in editpage.php on line 136
926 Revision 1.57 2003/02/26 03:40:22 dairiki
927 New action=create. Essentially the same as action=edit, except that if the
928 page already exists, it falls back to action=browse.
930 This is for use in the "question mark" links for unknown wiki words
931 to avoid problems and confusion when following links from stale pages.
932 (If the "unknown page" has been created in the interim, the user probably
933 wants to view the page before editing it.)
935 Revision 1.56 2003/02/21 18:07:14 dairiki
936 Minor, nitpicky, currently inconsequential changes.
938 Revision 1.55 2003/02/21 04:10:58 dairiki
939 Fixes for new cached markup.
940 Some minor code cleanups.
942 Revision 1.54 2003/02/16 19:47:16 dairiki
943 Update WikiDB timestamp when editing or deleting pages.
945 Revision 1.53 2003/02/15 23:20:27 dairiki
946 Redirect back to browse current version of page upon save,
947 even when no changes were made.
949 Revision 1.52 2003/01/03 22:22:00 carstenklapp
950 Minor adjustments to diff block markers ("<<<<<<<"). Source reformatting.
952 Revision 1.51 2003/01/03 02:43:26 carstenklapp
953 New class LoadFileConflictPageEditor, for merging / comparing a loaded
954 pgsrc file with an existing page.
962 // c-hanging-comment-ender-p: nil
963 // indent-tabs-mode: nil