2 rcs_id('$Id: editpage.php,v 1.99 2005-10-29 08:21:58 rurban Exp $');
4 require_once('lib/Template.php');
6 // ENABLE_WYSIWYG - Support for some WYSIWYG HTML Editor (tinymce or htmlarea3)
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
10 // might prefer HTML markup.
11 // TODO: Change from constant to user preference variable
12 // (checkbox setting or edit click as in gmail),
13 // when HtmlParser is finished.
15 if (!defined('USE_HTMLAREA')) define('USE_HTMLAREA', false);
16 if (USE_TINYMCE) require_once('lib/tinymce.php');
17 else if (USE_HTMLAREA) require_once('lib/htmlarea.php');
19 if (ENABLE_CAPTCHA) require_once('lib/Captcha.php');
23 function PageEditor (&$request) {
24 $this->request = &$request;
26 $this->user = $request->getUser();
27 $this->page = $request->getPage();
29 $this->current = $this->page->getCurrentRevision(false);
31 // HACKish short circuit to browse on action=create
32 if ($request->getArg('action') == 'create') {
33 if (! $this->current->hasDefaultContents())
34 $request->redirect(WikiURL($this->page->getName())); // noreturn
38 $this->meta = array('author' => $this->user->getId(),
39 'author_id' => $this->user->getAuthenticatedId(),
42 $this->tokens = array();
44 $version = $request->getArg('version');
45 if ($version !== false) {
46 $this->selected = $this->page->getRevision($version);
47 $this->version = $version;
50 $this->version = $this->current->getVersion();
51 $this->selected = $this->page->getRevision($this->version);
54 if ($this->_restoreState()) {
55 $this->_initialEdit = false;
58 $this->_initializeState();
59 $this->_initialEdit = true;
61 // The edit request has specified some initial content from a template
62 if ( ($template = $request->getArg('template'))
63 and $request->_dbi->isWikiPage($template)) {
64 $page = $request->_dbi->getPage($template);
65 $current = $page->getCurrentRevision();
66 $this->_content = $current->getPackedContent();
67 } elseif ($initial_content = $request->getArg('initial_content')) {
68 $this->_content = $initial_content;
69 $this->_redirect_to = $request->getArg('save_and_redirect_to');
73 header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
76 function editPage () {
79 $tokens = &$this->tokens;
80 $tokens['PAGE_LOCKED_MESSAGE'] = '';
81 $tokens['CONCURRENT_UPDATE_MESSAGE'] = '';
83 if (isset($this->request->args['pref']['editWidth'])
84 and ($this->request->getPref('editWidth') != $this->request->args['pref']['editWidth'])) {
85 $this->request->_prefs->set('editWidth', $this->request->args['pref']['editWidth']);
87 if (isset($this->request->args['pref']['editHeight'])
88 and ($this->request->getPref('editHeight') != $this->request->args['pref']['editHeight'])) {
89 $this->request->_prefs->set('editHeight', $this->request->args['pref']['editHeight']);
92 if (! $this->canEdit()) {
93 if ($this->isInitialEdit())
94 return $this->viewSource();
95 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
97 elseif ($this->request->getArg('save_and_redirect_to') != "") {
98 if (ENABLE_CAPTCHA && $this->captchaFailed()) {
99 $this->tokens['PAGE_LOCKED_MESSAGE'] =
100 HTML::p(HTML::h1(_("Typed in verification word mismatch ... are you a bot?")));
102 elseif ( $this->savePage()) {
104 $this->request->redirect(WikiURL($this->request->getArg('save_and_redirect_to')));
105 return true; // Page saved.
109 elseif ($this->editaction == 'save') {
110 if (ENABLE_CAPTCHA && $this->captchaFailed()) {
111 $this->tokens['PAGE_LOCKED_MESSAGE'] =
112 HTML::p(HTML::h1(_("Typed in verification word mismatch ... are you a bot?")));
114 elseif ($this->savePage()) {
115 return true; // Page saved.
122 if ($saveFailed and $this->isConcurrentUpdate())
124 // Get the text of the original page, and the two conflicting edits
125 // The diff3 class takes arrays as input. So retrieve content as
126 // an array, or convert it as necesary.
127 $orig = $this->page->getRevision($this->_currentVersion);
128 // FIXME: what if _currentVersion has be deleted?
129 $orig_content = $orig->getContent();
130 $this_content = explode("\n", $this->_content);
131 $other_content = $this->current->getContent();
132 include_once("lib/diff3.php");
133 $diff = new diff3($orig_content, $this_content, $other_content);
134 $output = $diff->merged_output(_("Your version"), _("Other version"));
135 // Set the content of the textarea to the merged diff
136 // output, and update the version
137 $this->_content = implode ("\n", $output);
138 $this->_currentVersion = $this->current->getVersion();
139 $this->version = $this->_currentVersion;
140 $unresolved = $diff->ConflictingBlocks;
141 $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage($unresolved);
142 } elseif ($saveFailed && !$this->_isSpam) {
143 $tokens['CONCURRENT_UPDATE_MESSAGE'] =
144 HTML(HTML::h2(_("Some internal editing error")),
145 HTML::p(_("Your are probably trying to edit/create an invalid version of this page.")),
146 HTML::p(HTML::em(_("&version=-1 might help."))));
149 if ($this->editaction == 'edit_convert')
150 $tokens['PREVIEW_CONTENT'] = $this->getConvertedPreview();
151 if ($this->editaction == 'preview')
152 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
154 // FIXME: NOT_CURRENT_MESSAGE?
155 $tokens = array_merge($tokens, $this->getFormElements());
157 if (ENABLE_EDIT_TOOLBAR and !ENABLE_WYSIWYG) {
158 include_once("lib/EditToolbar.php");
159 $toolbar = new EditToolbar();
160 $tokens = array_merge($tokens, $toolbar->getTokens());
163 return $this->output('editpage', _("Edit: %s"));
166 function output ($template, $title_fs) {
168 $selected = &$this->selected;
169 $current = &$this->current;
171 if ($selected && $selected->getVersion() != $current->getVersion()) {
173 $pagelink = WikiLink($selected);
177 $pagelink = WikiLink($this->page);
180 $title = new FormattedText ($title_fs, $pagelink);
181 // not for dumphtml or viewsource
182 if (ENABLE_WYSIWYG and $template == 'editpage') {
183 $WikiTheme->addMoreHeaders(Edit_WYSIWYG_Head());
184 //$tokens['PAGE_SOURCE'] = Edit_WYSIWYG_ConvertBefore($this->_content);
186 $template = Template($template, $this->tokens);
187 GeneratePage($template, $title, $rev);
192 function viewSource () {
193 assert($this->isInitialEdit());
194 assert($this->selected);
196 $this->tokens['PAGE_SOURCE'] = $this->_content;
197 return $this->output('viewsource', _("View Source: %s"));
200 function updateLock() {
201 if ((bool)$this->page->get('locked') == (bool)$this->locked)
202 return false; // Not changed.
204 if (!$this->user->isAdmin()) {
205 // FIXME: some sort of message
206 return false; // not allowed.
209 $this->page->set('locked', (bool)$this->locked);
210 $this->tokens['LOCK_CHANGED_MSG']
211 = $this->locked ? _("Page now locked.") : _("Page now unlocked.");
213 return true; // lock changed.
216 function savePage () {
217 $request = &$this->request;
219 if ($this->isUnchanged()) {
220 // Allow admin lock/unlock even if
221 // no text changes were made.
222 if ($this->updateLock()) {
223 $dbi = $request->getDbh();
226 // Save failed. No changes made.
227 $this->_redirectToBrowsePage();
228 // user will probably not see the rest of this...
229 include_once('lib/display.php');
230 // force browse of current version:
231 $request->setArg('version', false);
232 displayPage($request, 'nochanges');
236 if ($this->isSpam()) {
237 $this->_isSpam = true;
240 // Save failed. No changes made.
241 $this->_redirectToBrowsePage();
242 // user will probably not see the rest of this...
243 include_once('lib/display.php');
244 // force browse of current version:
245 $request->setArg('version', false);
246 displayPage($request, 'nochanges');
251 $page = &$this->page;
253 // Include any meta-data from original page version which
254 // has not been explicitly updated.
255 // (Except don't propagate pgsrc_version --- moot for now,
256 // because at present it never gets into the db...)
257 $meta = $this->selected->getMetaData();
258 unset($meta['pgsrc_version']);
259 $meta = array_merge($meta, $this->meta);
262 $this->_content = $this->getContent();
263 $newrevision = $page->save($this->_content,
266 : $this->_currentVersion + 1,
269 if (!isa($newrevision, 'WikiDB_PageRevision')) {
270 // Save failed. (Concurrent updates).
274 // New contents successfully saved...
277 // Clean out archived versions of this page.
278 include_once('lib/ArchiveCleaner.php');
279 $cleaner = new ArchiveCleaner($GLOBALS['ExpireParams']);
280 $cleaner->cleanPageRevisions($page);
282 /* generate notification emails done in WikiDB::save to catch all direct calls
285 // look at the errorstack
286 $errors = $GLOBALS['ErrorManager']->_postponed_errors;
287 $warnings = $GLOBALS['ErrorManager']->getPostponedErrorsAsHTML();
288 $GLOBALS['ErrorManager']->_postponed_errors = $errors;
290 $dbi = $request->getDbh();
294 if (empty($warnings->_content) && ! $WikiTheme->getImageURL('signature')) {
295 // Do redirect to browse page if no signature has
296 // been defined. In this case, the user will most
297 // likely not see the rest of the HTML we generate
299 $this->_redirectToBrowsePage();
302 // Force browse of current page version.
303 $request->setArg('version', false);
304 //$request->setArg('action', false);
306 $template = Template('savepage', $this->tokens);
307 $template->replace('CONTENT', $newrevision->getTransformedContent());
308 if (!empty($warnings->_content))
309 $template->replace('WARNINGS', $warnings);
311 $pagelink = WikiLink($page);
313 GeneratePage($template, fmt("Saved: %s", $pagelink), $newrevision);
317 function captchaFailed () {
318 if ($this->request->getSessionVar('captcha_ok') == true)
321 if ( ! array_key_exists ( 'captcha_input', $this->meta )
322 or ($this->request->getSessionVar('captchaword')
323 and ($this->request->getSessionVar('captchaword') != $this->meta['captcha_input'])))
326 $this->request->setSessionVar('captcha_ok', true);
330 function isConcurrentUpdate () {
331 assert($this->current->getVersion() >= $this->_currentVersion);
332 return $this->current->getVersion() != $this->_currentVersion;
335 function canEdit () {
336 return !$this->page->get('locked') || $this->user->isAdmin();
339 function isInitialEdit () {
340 return $this->_initialEdit;
343 function isUnchanged () {
344 $current = &$this->current;
346 if ($this->meta['markup'] != $current->get('markup'))
349 return $this->_content == $current->getPackedContent();
353 * Handle AntiSpam here. How? http://wikiblacklist.blogspot.com/
354 * Need to check dynamically some blacklist wikipage settings
355 * (plugin WikiAccessRestrictions) and some static blacklist.
357 * Always: More then 20 new external links
358 * ENABLE_SPAMASSASSIN: content patterns by babycart (only php >= 4.3 for now)
359 * ENABLE_SPAMBLOCKLIST: IP blacklist, domain blacklist, url patterns
362 $current = &$this->current;
363 $request = &$this->request;
365 $oldtext = $current->getPackedContent();
366 $newtext =& $this->_content;
368 // FIXME: in longer texts the NUM_SPAM_LINKS number should be increased.
369 // better use a certain text : link ratio.
371 // 1. Not more then 20 new external links
372 if ($this->numLinks($newtext) - $this->numLinks($oldtext) >= NUM_SPAM_LINKS) {
373 // TODO: mail the admin?
374 $this->tokens['PAGE_LOCKED_MESSAGE'] =
375 HTML($this->getSpamMessage(),
376 HTML::p(HTML::strong(_("Too many external links."))));
379 // 2. external babycart (SpamAssassin) check
380 // This will probably prevent from discussing sex or viagra related topics. So beware.
381 if (ENABLE_SPAMASSASSIN) {
382 $user = $request->getUser();
383 include_once("lib/spam_babycart.php");
384 if ($babycart = check_babycart($newtext, $request->get("REMOTE_ADDR"),
386 // TODO: mail the admin
387 if (is_array($babycart))
388 $this->tokens['PAGE_LOCKED_MESSAGE'] =
389 HTML($this->getSpamMessage(),
390 HTML::p(HTML::em(_("SpamAssassin reports: ",
391 join("\n", $babycart)))));
395 // 3. extract (new) links and check surbl for blocked domains
396 if (ENABLE_SPAMBLOCKLIST and $this->numLinks($newtext)) {
397 include_once("lib/SpamBlocklist.php");
398 include_once("lib/InlineParser.php");
399 $parsed = TransformLinks($newtext);
400 foreach ($parsed->_content as $link) {
401 if (isa($link, 'Cached_ExternalLink')) {
402 $uri = $link->_getURL($this->page->getName());
403 if ($res = IsBlackListed($uri)) {
404 // TODO: mail the admin
405 $this->tokens['PAGE_LOCKED_MESSAGE'] =
406 HTML($this->getSpamMessage(),
407 HTML::p(HTML::strong(_("External links contain blocked domains:")),
408 HTML::ul(HTML::li(sprintf(_("%s is listed at %s"),
409 $res[2], $res[0])))));
419 /** Number of external links in the wikitext
421 function numLinks(&$text) {
422 return substr_count($text, "http://") + substr_count($text, "https://");
425 /** Header of the Anti Spam message
427 function getSpamMessage () {
429 HTML(HTML::h2(_("Spam Prevention")),
430 HTML::p(_("This page edit seems to contain spam and was therefore not saved."),
432 _("Sorry for the inconvenience.")),
436 function getPreview () {
437 include_once('lib/PageType.php');
438 $this->_content = $this->getContent();
439 return new TransformedText($this->page, $this->_content, $this->meta);
442 function getConvertedPreview () {
443 include_once('lib/PageType.php');
444 $this->_content = $this->getContent();
445 $this->meta['markup'] = 2.0;
446 $this->_content = ConvertOldMarkup($this->_content);
447 return new TransformedText($this->page, $this->_content, $this->meta);
450 // possibly convert HTMLAREA content back to Wiki markup
451 function getContent () {
452 if (ENABLE_WYSIWYG) {
453 $xml_output = Edit_WYSIWYG_ConvertAfter($this->_content);
454 //$this->_content = join("", $xml_output->_content);
455 return $this->_content;
457 return $this->_content;
461 function getLockedMessage () {
463 HTML(HTML::h2(_("Page Locked")),
464 HTML::p(_("This page has been locked by the administrator so your changes can not be saved.")),
465 HTML::p(_("(Copy your changes to the clipboard. You can try editing a different page or save your text in a text editor.)")),
466 HTML::p(_("Sorry for the inconvenience.")));
469 function getConflictMessage ($unresolved = false) {
471 xgettext only knows about c/c++ line-continuation strings
472 it does not know about php's dot operator.
473 We want to translate this entire paragraph as one string, of course.
476 //$re_edit_link = Button('edit', _("Edit the new version"), $this->page);
479 $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.",
480 "<<<<<<< ". _("Your version"),
481 ">>>>>>> ". _("Other version")));
483 $message = HTML::p(_("Please check it through before saving."));
487 /*$steps = HTML::ol(HTML::li(_("Copy your changes to the clipboard or to another temporary place (e.g. text editor).")),
488 HTML::li(fmt("%s of the page. You should now see the most current version of the page. Your changes are no longer there.",
490 HTML::li(_("Make changes to the file again. Paste your additions from the clipboard (or text editor).")),
491 HTML::li(_("Save your updated changes.")));
494 HTML(HTML::h2(_("Conflicting Edits!")),
495 HTML::p(_("In the time since you started editing this page, another user has saved a new version of it.")),
496 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.")),
501 function getTextArea () {
502 $request = &$this->request;
504 $readonly = ! $this->canEdit(); // || $this->isConcurrentUpdate();
506 // WYSIWYG will need two pagetypes: raw wikitest and converted html
507 if (ENABLE_WYSIWYG) {
508 $this->_wikicontent = $this->_content;
509 $this->_content = $this->getPreview();
510 // $html = $this->getPreview();
511 // $this->_content = $html->asXML();
514 $textarea = HTML::textarea(array('class'=> 'wikiedit',
515 'name' => 'edit[content]',
516 'id' => 'edit:content',
517 'rows' => $request->getPref('editHeight'),
518 'cols' => $request->getPref('editWidth'),
519 'readonly' => (bool) $readonly),
521 /** <textarea wrap="virtual"> is not valid xhtml but Netscape 4 requires it
522 * to wrap long lines.
525 $textarea->setAttr('wrap', 'virtual');
527 return Edit_WYSIWYG_Textarea($textarea, $this->_wikicontent, $textarea->getAttr('name'));
532 function getFormElements () {
534 $request = &$this->request;
535 $page = &$this->page;
537 $h = array('action' => 'edit',
538 'pagename' => $page->getName(),
539 'version' => $this->version,
540 'edit[pagetype]' => $this->meta['pagetype'],
541 'edit[current_version]' => $this->_currentVersion);
543 $el['HIDDEN_INPUTS'] = HiddenInputs($h);
544 $el['EDIT_TEXTAREA'] = $this->getTextArea();
545 if ( ENABLE_CAPTCHA && ! $request->getSessionVar('captchaword')) {
546 $request->setSessionVar('captchaword', get_captcha_word());
548 if ( ENABLE_CAPTCHA && ! $request->getSessionVar('captcha_ok')) {
550 = HTML::input(array('type' => 'text',
551 'class' => 'wikitext',
552 'id' => 'edit:captcha_input',
553 'name' => 'edit[captcha_input]',
555 'maxlength' => 256));
556 $el['CAPTCHA_IMAGE'] = '<img src="?action=captcha" alt="captcha" />';
557 $el['CAPTCHA_LABEL'] = '<label for="edit:captcha_input">'._("Type word above:").' </label>';
560 = HTML::input(array('type' => 'text',
561 'class' => 'wikitext',
562 'id' => 'edit:summary',
563 'name' => 'edit[summary]',
566 'value' => $this->meta['summary']));
568 = HTML::input(array('type' => 'checkbox',
569 'name' => 'edit[minor_edit]',
570 'id' => 'edit:minor_edit',
571 'checked' => (bool) $this->meta['is_minor_edit']));
573 = HTML::input(array('type' => 'checkbox',
574 'name' => 'edit[markup]',
576 'checked' => $this->meta['markup'] < 2.0,
577 'id' => 'useOldMarkup',
578 'onclick' => 'showOldMarkupRules(this.checked)'));
579 $el['OLD_MARKUP_CONVERT'] = ($this->meta['markup'] < 2.0)
580 ? Button('submit:edit[edit_convert]', _("Convert"), 'wikiaction') : '';
582 = HTML::input(array('type' => 'checkbox',
583 'name' => 'edit[locked]',
584 'id' => 'edit:locked',
585 'disabled' => (bool) !$this->user->isadmin(),
586 'checked' => (bool) $this->locked));
588 $el['PREVIEW_B'] = Button('submit:edit[preview]', _("Preview"),
591 //if (!$this->isConcurrentUpdate() && $this->canEdit())
592 $el['SAVE_B'] = Button('submit:edit[save]', _("Save"), 'wikiaction');
594 $el['IS_CURRENT'] = $this->version == $this->current->getVersion();
597 = HTML::input(array('type' => 'text',
600 'class' => "numeric",
601 'name' => 'pref[editWidth]',
602 'id' => 'pref:editWidth',
603 'value' => $request->getPref('editWidth'),
604 'onchange' => 'this.form.submit();'));
606 = HTML::input(array('type' => 'text',
609 'class' => "numeric",
610 'name' => 'pref[editHeight]',
611 'id' => 'pref:editHeight',
612 'value' => $request->getPref('editHeight'),
613 'onchange' => 'this.form.submit();'));
614 $el['SEP'] = $WikiTheme->getButtonSeparator();
615 $el['AUTHOR_MESSAGE'] = fmt("Author will be logged as %s.",
616 HTML::em($this->user->getId()));
621 function _redirectToBrowsePage() {
622 $this->request->redirect(WikiURL($this->page, false, 'absolute_url'));
625 function _restoreState () {
626 $request = &$this->request;
628 $posted = $request->getArg('edit');
629 $request->setArg('edit', false);
631 if (!$posted || !$request->isPost()
632 || $request->getArg('action') != 'edit')
635 if (!isset($posted['content']) || !is_string($posted['content']))
637 $this->_content = preg_replace('/[ \t\r]+\n/', "\n",
638 rtrim($posted['content']));
639 $this->_content = $this->getContent();
641 $this->_currentVersion = (int) $posted['current_version'];
643 if ($this->_currentVersion < 0)
645 if ($this->_currentVersion > $this->current->getVersion())
646 return false; // FIXME: some kind of warning?
648 $is_old_markup = !empty($posted['markup']) && $posted['markup'] == 'old';
649 $meta['markup'] = $is_old_markup ? false : 2.0;
650 $meta['summary'] = trim(substr($posted['summary'], 0, 256));
651 $meta['is_minor_edit'] = !empty($posted['minor_edit']);
652 $meta['pagetype'] = !empty($posted['pagetype']) ? $posted['pagetype'] : false;
653 if ( ENABLE_CAPTCHA )
654 $meta['captcha_input'] = !empty($posted['captcha_input']) ?
655 $posted['captcha_input'] : '';
657 $this->meta = array_merge($this->meta, $meta);
658 $this->locked = !empty($posted['locked']);
660 if (!empty($posted['preview']))
661 $this->editaction = 'preview';
662 elseif (!empty($posted['save']))
663 $this->editaction = 'save';
664 elseif (!empty($posted['edit_convert']))
665 $this->editaction = 'edit_convert';
667 $this->editaction = 'edit';
672 function _initializeState () {
673 $request = &$this->request;
674 $current = &$this->current;
675 $selected = &$this->selected;
676 $user = &$this->user;
679 NoSuchRevision($request, $this->page, $this->version); // noreturn
681 $this->_currentVersion = $current->getVersion();
682 $this->_content = $selected->getPackedContent();
684 $this->locked = $this->page->get('locked');
686 // If author same as previous author, default minor_edit to on.
687 $age = $this->meta['mtime'] - $current->get('mtime');
688 $this->meta['is_minor_edit'] = ( $age < MINOR_EDIT_TIMEOUT
689 && $current->get('author') == $user->getId()
692 // Default for new pages is new-style markup.
693 if ($selected->hasDefaultContents())
694 $is_new_markup = true;
696 $is_new_markup = $selected->get('markup') >= 2.0;
698 $this->meta['markup'] = $is_new_markup ? 2.0: false;
699 $this->meta['pagetype'] = $selected->get('pagetype');
700 if ($this->meta['pagetype'] == 'wikiblog')
701 $this->meta['summary'] = $selected->get('summary'); // keep blog title
703 $this->meta['summary'] = '';
704 $this->editaction = 'edit';
708 class LoadFileConflictPageEditor
711 function editPage ($saveFailed = true) {
712 $tokens = &$this->tokens;
714 if (!$this->canEdit()) {
715 if ($this->isInitialEdit())
716 return $this->viewSource();
717 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
719 elseif ($this->editaction == 'save') {
720 if ($this->savePage())
721 return true; // Page saved.
725 if ($saveFailed || $this->isConcurrentUpdate())
727 // Get the text of the original page, and the two conflicting edits
728 // The diff class takes arrays as input. So retrieve content as
729 // an array, or convert it as necesary.
730 $orig = $this->page->getRevision($this->_currentVersion);
731 $this_content = explode("\n", $this->_content);
732 $other_content = $this->current->getContent();
733 include_once("lib/diff.php");
734 $diff2 = new Diff($other_content, $this_content);
735 $context_lines = max(4, count($other_content) + 1,
736 count($this_content) + 1);
737 $fmt = new BlockDiffFormatter($context_lines);
739 $this->_content = $fmt->format($diff2);
740 // FIXME: integrate this into class BlockDiffFormatter
741 $this->_content = str_replace(">>>>>>>\n<<<<<<<\n", "=======\n",
743 $this->_content = str_replace("<<<<<<<\n>>>>>>>\n", "=======\n",
746 $this->_currentVersion = $this->current->getVersion();
747 $this->version = $this->_currentVersion;
748 $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage();
751 if ($this->editaction == 'edit_convert')
752 $tokens['PREVIEW_CONTENT'] = $this->getConvertedPreview();
753 if ($this->editaction == 'preview')
754 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
756 // FIXME: NOT_CURRENT_MESSAGE?
757 $tokens = array_merge($tokens, $this->getFormElements());
759 return $this->output('editpage', _("Merge and Edit: %s"));
760 // FIXME: this doesn't display
763 function output ($template, $title_fs) {
764 $selected = &$this->selected;
765 $current = &$this->current;
767 if ($selected && $selected->getVersion() != $current->getVersion()) {
769 $pagelink = WikiLink($selected);
773 $pagelink = WikiLink($this->page);
776 $title = new FormattedText ($title_fs, $pagelink);
777 $template = Template($template, $this->tokens);
779 //GeneratePage($template, $title, $rev);
783 function getConflictMessage () {
784 $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.",
787 HTML::p(_("Please check it through before saving."))));
793 $Log: not supported by cvs2svn $
794 Revision 1.98 2005/10/10 19:37:04 rurban
795 change USE_HTMLAREA to ENABLE WYSIWYG, add NUM_SPAM_LINKS=20
797 Revision 1.97 2005/09/26 06:32:22 rurban
798 [] is forbidden in id tags. Renamed to use :
800 Revision 1.96 2005/05/06 17:54:22 rurban
801 silence Preview warnings for PAGE_LOCKED_MESSAGE, CONCURRENT_UPDATE_MESSAGE (thanks to schorni)
803 Revision 1.95 2005/04/25 20:17:14 rurban
804 captcha feature by Benjamin Drieu. Patch #1110699
806 Revision 1.94 2005/02/28 20:23:31 rurban
809 Revision 1.93 2005/02/27 19:31:52 rurban
810 hack: display errorstack without sideeffects (save and restore)
812 Revision 1.92 2005/01/29 20:37:21 rurban
813 no edit toolbar at all if ENABLE_EDITTOOLBAR = false
815 Revision 1.91 2005/01/25 07:05:49 rurban
816 extract toolbar code, support new tags to get rid of php inside templates
818 Revision 1.90 2005/01/22 12:46:15 rurban
819 fix oldmakrup button label
820 update pref[edit*] settings
822 Revision 1.89 2005/01/21 14:07:49 rurban
825 Revision 1.88 2004/12/17 16:39:03 rurban
828 Revision 1.87 2004/12/16 18:28:05 rurban
829 keep wikiblog summary = page title
831 Revision 1.86 2004/12/11 14:50:15 rurban
832 new edit_convert button, to get rid of old markup eventually
834 Revision 1.85 2004/12/06 19:49:56 rurban
835 enable action=remove which is undoable and seeable in RecentChanges: ADODB ony for now.
836 renamed delete_page to purge_page.
837 enable action=edit&version=-1 to force creation of a new version.
838 added BABYCART_PATH config
839 fixed magiqc in adodb.inc.php
842 Revision 1.84 2004/12/04 12:58:26 rurban
843 enable babycart Blog::SpamAssassin module on ENABLE_SPAMASSASSIN=true
844 (currently only for php >= 4.3.0)
846 Revision 1.83 2004/12/04 11:55:39 rurban
847 First simple AntiSpam prevention:
848 No more than 20 new http:// links allowed
850 Revision 1.82 2004/11/30 22:21:56 rurban
851 changed gif to optimized (pngout) png
853 Revision 1.81 2004/11/29 17:57:27 rurban
854 translated pulldown buttons
856 Revision 1.80 2004/11/25 17:20:51 rurban
857 and again a couple of more native db args: backlinks
859 Revision 1.79 2004/11/21 11:59:20 rurban
860 remove final \n to be ob_cache independent
862 Revision 1.78 2004/11/16 17:57:45 rurban
863 fix search&replace button
864 use new addTagButton machinery
865 new showPulldown for categories, TODO: in a seperate request
867 Revision 1.77 2004/11/15 15:52:35 rurban
870 Revision 1.76 2004/11/15 15:37:34 rurban
872 don't use document.write for replace, otherwise self.opener is not defined.
874 Revision 1.75 2004/09/16 08:00:52 rurban
877 Revision 1.74 2004/07/03 07:36:28 rurban
878 do not get unneccessary content
880 Revision 1.73 2004/06/16 21:23:44 rurban
881 fixed non-object fatal #215
883 Revision 1.72 2004/06/14 11:31:37 rurban
884 renamed global $Theme to $WikiTheme (gforge nameclash)
885 inherit PageList default options from PageList
886 default sortby=pagename
887 use options in PageList_Selectable (limit, sortby, ...)
888 added action revert, with button at action=diff
889 added option regex to WikiAdminSearchReplace
891 Revision 1.71 2004/06/03 18:06:29 rurban
892 fix file locking issues (only needed on write)
893 fixed immediate LANG and THEME in-session updates if not stored in prefs
894 advanced editpage toolbars (search & replace broken)
896 Revision 1.70 2004/06/02 20:47:47 rurban
897 dont use the wikiaction class
899 Revision 1.69 2004/06/02 10:17:56 rurban
900 integrated search/replace into toolbar
901 added save+preview buttons
903 Revision 1.68 2004/06/01 15:28:00 rurban
904 AdminUser only ADMIN_USER not member of Administrators
905 some RateIt improvements by dfrankow
908 Revision _1.6 2004/05/26 15:48:00 syilek
909 fixed problem with creating page with slashes from one true page
911 Revision _1.5 2004/05/25 16:51:53 syilek
912 added ability to create a page from the category page and not have to edit it
914 Revision 1.67 2004/05/27 17:49:06 rurban
915 renamed DB_Session to DbSession (in CVS also)
916 added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
917 remove leading slash in error message
918 added force_unlock parameter to File_Passwd (no return on stale locks)
919 fixed adodb session AffectedRows
920 added FileFinder helpers to unify local filenames and DATA_PATH names
921 editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
923 Revision 1.66 2004/04/29 23:25:12 rurban
924 re-ordered locale init (as in 1.3.9)
925 fixed loadfile with subpages, and merge/restore anyway
928 Revision 1.65 2004/04/18 01:11:52 rurban
929 more numeric pagename fixes.
930 fixed action=upload with merge conflict warnings.
931 charset changed from constant to global (dynamic utf-8 switching)
933 Revision 1.64 2004/04/06 19:48:56 rurban
934 temp workaround for action=edit AddComment form
936 Revision 1.63 2004/03/24 19:39:02 rurban
937 php5 workaround code (plus some interim debugging code in XmlElement)
938 php5 doesn't work yet with the current XmlElement class constructors,
939 WikiUserNew does work better than php4.
940 rewrote WikiUserNew user upgrading to ease php5 update
941 fixed pref handling in WikiUserNew
942 added Email Notification
943 added simple Email verification
944 removed emailVerify userpref subclass: just a email property
945 changed pref binary storage layout: numarray => hash of non default values
946 print optimize message only if really done.
947 forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
948 prefs should be stored in db or homepage, besides the current session.
950 Revision 1.62 2004/03/17 18:41:05 rurban
951 initial_content and template support for CreatePage
953 Revision 1.61 2004/03/12 20:59:17 rurban
954 important cookie fix by Konstantin Zadorozhny
955 new editpage feature: JS_SEARCHREPLACE
957 Revision 1.60 2004/02/15 21:34:37 rurban
958 PageList enhanced and improved.
959 fixed new WikiAdmin... plugins
960 editpage, Theme with exp. htmlarea framework
961 (htmlarea yet committed, this is really questionable)
962 WikiUser... code with better session handling for prefs
963 enhanced UserPreferences (again)
964 RecentChanges for show_deleted: how should pages be deleted then?
966 Revision 1.59 2003/12/07 20:35:26 carstenklapp
967 Bugfix: Concurrent updates broken since after 1.3.4 release: Fatal
968 error: Call to undefined function: gettransformedcontent() in
969 /home/groups/p/ph/phpwiki/htdocs/phpwiki2/lib/editpage.php on line
972 Revision 1.58 2003/03/10 18:25:22 dairiki
973 Bug/typo fix. If you use the edit page to un/lock a page, it
974 failed with: Fatal error: Call to a member function on a
975 non-object in editpage.php on line 136
977 Revision 1.57 2003/02/26 03:40:22 dairiki
978 New action=create. Essentially the same as action=edit, except that if the
979 page already exists, it falls back to action=browse.
981 This is for use in the "question mark" links for unknown wiki words
982 to avoid problems and confusion when following links from stale pages.
983 (If the "unknown page" has been created in the interim, the user probably
984 wants to view the page before editing it.)
986 Revision 1.56 2003/02/21 18:07:14 dairiki
987 Minor, nitpicky, currently inconsequential changes.
989 Revision 1.55 2003/02/21 04:10:58 dairiki
990 Fixes for new cached markup.
991 Some minor code cleanups.
993 Revision 1.54 2003/02/16 19:47:16 dairiki
994 Update WikiDB timestamp when editing or deleting pages.
996 Revision 1.53 2003/02/15 23:20:27 dairiki
997 Redirect back to browse current version of page upon save,
998 even when no changes were made.
1000 Revision 1.52 2003/01/03 22:22:00 carstenklapp
1001 Minor adjustments to diff block markers ("<<<<<<<"). Source reformatting.
1003 Revision 1.51 2003/01/03 02:43:26 carstenklapp
1004 New class LoadFileConflictPageEditor, for merging / comparing a loaded
1005 pgsrc file with an existing page.
1012 // c-basic-offset: 4
1013 // c-hanging-comment-ender-p: nil
1014 // indent-tabs-mode: nil