2 rcs_id('$Id: editpage.php,v 1.104 2005-10-31 17:20:40 rurban Exp $');
4 require_once('lib/Template.php');
8 function PageEditor (&$request) {
9 $this->request = &$request;
11 $this->user = $request->getUser();
12 $this->page = $request->getPage();
14 $this->current = $this->page->getCurrentRevision(false);
16 // HACKish short circuit to browse on action=create
17 if ($request->getArg('action') == 'create') {
18 if (! $this->current->hasDefaultContents())
19 $request->redirect(WikiURL($this->page->getName())); // noreturn
23 $this->meta = array('author' => $this->user->getId(),
24 'author_id' => $this->user->getAuthenticatedId(),
27 $this->tokens = array();
30 $backend = WYSIWYG_BACKEND;
31 // TODO: error message
32 require_once("lib/WysiwygEdit/$backend.php");
33 $class = "WysiwygEdit_$backend";
34 $this->WysiwygEdit = new $class();
37 require_once('lib/Captcha.php');
38 $this->Captcha = new Captcha($this->meta);
41 $version = $request->getArg('version');
42 if ($version !== false) {
43 $this->selected = $this->page->getRevision($version);
44 $this->version = $version;
47 $this->version = $this->current->getVersion();
48 $this->selected = $this->page->getRevision($this->version);
51 if ($this->_restoreState()) {
52 $this->_initialEdit = false;
55 $this->_initializeState();
56 $this->_initialEdit = true;
58 // The edit request has specified some initial content from a template
59 if ( ($template = $request->getArg('template'))
60 and $request->_dbi->isWikiPage($template)) {
61 $page = $request->_dbi->getPage($template);
62 $current = $page->getCurrentRevision();
63 $this->_content = $current->getPackedContent();
64 } elseif ($initial_content = $request->getArg('initial_content')) {
65 $this->_content = $initial_content;
66 $this->_redirect_to = $request->getArg('save_and_redirect_to');
70 header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
73 function editPage () {
76 $tokens = &$this->tokens;
77 $tokens['PAGE_LOCKED_MESSAGE'] = '';
78 $tokens['CONCURRENT_UPDATE_MESSAGE'] = '';
80 if (isset($this->request->args['pref']['editWidth'])
81 and ($this->request->getPref('editWidth') != $this->request->args['pref']['editWidth'])) {
82 $this->request->_prefs->set('editWidth', $this->request->args['pref']['editWidth']);
84 if (isset($this->request->args['pref']['editHeight'])
85 and ($this->request->getPref('editHeight') != $this->request->args['pref']['editHeight'])) {
86 $this->request->_prefs->set('editHeight', $this->request->args['pref']['editHeight']);
89 if (! $this->canEdit()) {
90 if ($this->isInitialEdit())
91 return $this->viewSource();
92 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
94 elseif ($this->request->getArg('save_and_redirect_to') != "") {
95 if (ENABLE_CAPTCHA && $this->Captcha->Failed()) {
96 $this->tokens['PAGE_LOCKED_MESSAGE'] =
97 HTML::p(HTML::h1($this->Captcha->failed_msg));
99 elseif ( $this->savePage()) {
101 $this->request->redirect(WikiURL($this->request->getArg('save_and_redirect_to')));
102 return true; // Page saved.
106 elseif ($this->editaction == 'save') {
107 if (ENABLE_CAPTCHA && $this->Captcha->Failed()) {
108 $this->tokens['PAGE_LOCKED_MESSAGE'] =
109 HTML::p(HTML::h1($this->Captcha->failed_msg));
111 elseif ($this->savePage()) {
112 return true; // Page saved.
119 if ($saveFailed and $this->isConcurrentUpdate())
121 // Get the text of the original page, and the two conflicting edits
122 // The diff3 class takes arrays as input. So retrieve content as
123 // an array, or convert it as necesary.
124 $orig = $this->page->getRevision($this->_currentVersion);
125 // FIXME: what if _currentVersion has be deleted?
126 $orig_content = $orig->getContent();
127 $this_content = explode("\n", $this->_content);
128 $other_content = $this->current->getContent();
129 include_once("lib/diff3.php");
130 $diff = new diff3($orig_content, $this_content, $other_content);
131 $output = $diff->merged_output(_("Your version"), _("Other version"));
132 // Set the content of the textarea to the merged diff
133 // output, and update the version
134 $this->_content = implode ("\n", $output);
135 $this->_currentVersion = $this->current->getVersion();
136 $this->version = $this->_currentVersion;
137 $unresolved = $diff->ConflictingBlocks;
138 $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage($unresolved);
139 } elseif ($saveFailed && !$this->_isSpam) {
140 $tokens['CONCURRENT_UPDATE_MESSAGE'] =
141 HTML(HTML::h2(_("Some internal editing error")),
142 HTML::p(_("Your are probably trying to edit/create an invalid version of this page.")),
143 HTML::p(HTML::em(_("&version=-1 might help."))));
146 if ($this->editaction == 'edit_convert')
147 $tokens['PREVIEW_CONTENT'] = $this->getConvertedPreview();
148 if ($this->editaction == 'preview')
149 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
151 // FIXME: NOT_CURRENT_MESSAGE?
152 $tokens = array_merge($tokens, $this->getFormElements());
154 if (ENABLE_EDIT_TOOLBAR and !ENABLE_WYSIWYG) {
155 include_once("lib/EditToolbar.php");
156 $toolbar = new EditToolbar();
157 $tokens = array_merge($tokens, $toolbar->getTokens());
160 return $this->output('editpage', _("Edit: %s"));
163 function output ($template, $title_fs) {
165 $selected = &$this->selected;
166 $current = &$this->current;
168 if ($selected && $selected->getVersion() != $current->getVersion()) {
170 $pagelink = WikiLink($selected);
174 $pagelink = WikiLink($this->page);
177 $title = new FormattedText ($title_fs, $pagelink);
178 // not for dumphtml or viewsource
179 if (ENABLE_WYSIWYG and $template == 'editpage') {
180 $WikiTheme->addMoreHeaders($this->WysiwygEdit->Head());
181 //$tokens['PAGE_SOURCE'] = $this->WysiwygEdit->ConvertBefore($this->_content);
183 $template = Template($template, $this->tokens);
184 GeneratePage($template, $title, $rev);
189 function viewSource () {
190 assert($this->isInitialEdit());
191 assert($this->selected);
193 $this->tokens['PAGE_SOURCE'] = $this->_content;
194 $this->tokens['HIDDEN_INPUTS'] = HiddenInputs($this->request->getArgs());
195 return $this->output('viewsource', _("View Source: %s"));
198 function updateLock() {
199 if ((bool)$this->page->get('locked') == (bool)$this->locked)
200 return false; // Not changed.
202 if (!$this->user->isAdmin()) {
203 // FIXME: some sort of message
204 return false; // not allowed.
207 $this->page->set('locked', (bool)$this->locked);
208 $this->tokens['LOCK_CHANGED_MSG']
209 = $this->locked ? _("Page now locked.") : _("Page now unlocked.");
211 return true; // lock changed.
214 function savePage () {
215 $request = &$this->request;
217 if ($this->isUnchanged()) {
218 // Allow admin lock/unlock even if
219 // no text changes were made.
220 if ($this->updateLock()) {
221 $dbi = $request->getDbh();
224 // Save failed. No changes made.
225 $this->_redirectToBrowsePage();
226 // user will probably not see the rest of this...
227 include_once('lib/display.php');
228 // force browse of current version:
229 $request->setArg('version', false);
230 displayPage($request, 'nochanges');
234 if ($this->isSpam()) {
235 $this->_isSpam = true;
238 // Save failed. No changes made.
239 $this->_redirectToBrowsePage();
240 // user will probably not see the rest of this...
241 include_once('lib/display.php');
242 // force browse of current version:
243 $request->setArg('version', false);
244 displayPage($request, 'nochanges');
249 $page = &$this->page;
251 // Include any meta-data from original page version which
252 // has not been explicitly updated.
253 // (Except don't propagate pgsrc_version --- moot for now,
254 // because at present it never gets into the db...)
255 $meta = $this->selected->getMetaData();
256 unset($meta['pgsrc_version']);
257 $meta = array_merge($meta, $this->meta);
260 $this->_content = $this->getContent();
261 $newrevision = $page->save($this->_content,
264 : $this->_currentVersion + 1,
267 if (!isa($newrevision, 'WikiDB_PageRevision')) {
268 // Save failed. (Concurrent updates).
272 // New contents successfully saved...
275 // Clean out archived versions of this page.
276 include_once('lib/ArchiveCleaner.php');
277 $cleaner = new ArchiveCleaner($GLOBALS['ExpireParams']);
278 $cleaner->cleanPageRevisions($page);
280 /* generate notification emails done in WikiDB::save to catch all direct calls
283 // look at the errorstack
284 $errors = $GLOBALS['ErrorManager']->_postponed_errors;
285 $warnings = $GLOBALS['ErrorManager']->getPostponedErrorsAsHTML();
286 $GLOBALS['ErrorManager']->_postponed_errors = $errors;
288 $dbi = $request->getDbh();
292 if (empty($warnings->_content) && ! $WikiTheme->getImageURL('signature')) {
293 // Do redirect to browse page if no signature has
294 // been defined. In this case, the user will most
295 // likely not see the rest of the HTML we generate
297 $this->_redirectToBrowsePage();
300 // Force browse of current page version.
301 $request->setArg('version', false);
302 //$request->setArg('action', false);
304 $template = Template('savepage', $this->tokens);
305 $template->replace('CONTENT', $newrevision->getTransformedContent());
306 if (!empty($warnings->_content))
307 $template->replace('WARNINGS', $warnings);
309 $pagelink = WikiLink($page);
311 GeneratePage($template, fmt("Saved: %s", $pagelink), $newrevision);
315 function isConcurrentUpdate () {
316 assert($this->current->getVersion() >= $this->_currentVersion);
317 return $this->current->getVersion() != $this->_currentVersion;
320 function canEdit () {
321 return !$this->page->get('locked') || $this->user->isAdmin();
324 function isInitialEdit () {
325 return $this->_initialEdit;
328 function isUnchanged () {
329 $current = &$this->current;
331 if ($this->meta['markup'] != $current->get('markup'))
334 return $this->_content == $current->getPackedContent();
338 * Handle AntiSpam here. How? http://wikiblacklist.blogspot.com/
339 * Need to check dynamically some blacklist wikipage settings
340 * (plugin WikiAccessRestrictions) and some static blacklist.
342 * Always: More then 20 new external links
343 * ENABLE_SPAMASSASSIN: content patterns by babycart (only php >= 4.3 for now)
344 * ENABLE_SPAMBLOCKLIST: content domain blacklist
347 $current = &$this->current;
348 $request = &$this->request;
350 $oldtext = $current->getPackedContent();
351 $newtext =& $this->_content;
353 // FIXME: in longer texts the NUM_SPAM_LINKS number should be increased.
354 // better use a certain text : link ratio.
356 // 1. Not more then 20 new external links
357 if ($this->numLinks($newtext) - $this->numLinks($oldtext) >= NUM_SPAM_LINKS) {
358 // TODO: mail the admin?
359 $this->tokens['PAGE_LOCKED_MESSAGE'] =
360 HTML($this->getSpamMessage(),
361 HTML::p(HTML::strong(_("Too many external links."))));
364 // 2. external babycart (SpamAssassin) check
365 // This will probably prevent from discussing sex or viagra related topics. So beware.
366 if (ENABLE_SPAMASSASSIN) {
367 $user = $request->getUser();
368 include_once("lib/spam_babycart.php");
369 if ($babycart = check_babycart($newtext, $request->get("REMOTE_ADDR"),
371 // TODO: mail the admin
372 if (is_array($babycart))
373 $this->tokens['PAGE_LOCKED_MESSAGE'] =
374 HTML($this->getSpamMessage(),
375 HTML::p(HTML::em(_("SpamAssassin reports: ",
376 join("\n", $babycart)))));
380 // 3. extract (new) links and check surbl for blocked domains
381 if (ENABLE_SPAMBLOCKLIST and $this->numLinks($newtext)) {
382 include_once("lib/SpamBlocklist.php");
383 include_once("lib/InlineParser.php");
384 $parsed = TransformLinks($newtext);
385 foreach ($parsed->_content as $link) {
386 if (isa($link, 'Cached_ExternalLink')) {
387 $uri = $link->_getURL($this->page->getName());
388 if ($res = IsBlackListed($uri)) {
389 // TODO: mail the admin
390 $this->tokens['PAGE_LOCKED_MESSAGE'] =
391 HTML($this->getSpamMessage(),
392 HTML::p(HTML::strong(_("External links contain blocked domains:")),
393 HTML::ul(HTML::li(sprintf(_("%s is listed at %s"),
394 $res[2], $res[0])))));
404 /** Number of external links in the wikitext
406 function numLinks(&$text) {
407 return substr_count($text, "http://") + substr_count($text, "https://");
410 /** Header of the Anti Spam message
412 function getSpamMessage () {
414 HTML(HTML::h2(_("Spam Prevention")),
415 HTML::p(_("This page edit seems to contain spam and was therefore not saved."),
417 _("Sorry for the inconvenience.")),
421 function getPreview () {
422 include_once('lib/PageType.php');
423 $this->_content = $this->getContent();
424 return new TransformedText($this->page, $this->_content, $this->meta);
427 function getConvertedPreview () {
428 include_once('lib/PageType.php');
429 $this->_content = $this->getContent();
430 $this->meta['markup'] = 2.0;
431 $this->_content = ConvertOldMarkup($this->_content);
432 return new TransformedText($this->page, $this->_content, $this->meta);
435 // possibly convert HTMLAREA content back to Wiki markup
436 function getContent () {
437 if (ENABLE_WYSIWYG) {
438 // don't store everything as html
439 if (!WYSIWYG_DEFAULT_PAGETYPE_HTML) {
440 $xml_output = $this->WysiwygEdit->ConvertAfter($this->_content);
441 $this->_content = join("", $xml_output->_content);
443 $this->meta['pagetype'] = 'html';
445 return $this->_content;
447 return $this->_content;
451 function getLockedMessage () {
453 HTML(HTML::h2(_("Page Locked")),
454 HTML::p(_("This page has been locked by the administrator so your changes can not be saved.")),
455 HTML::p(_("(Copy your changes to the clipboard. You can try editing a different page or save your text in a text editor.)")),
456 HTML::p(_("Sorry for the inconvenience.")));
459 function getConflictMessage ($unresolved = false) {
461 xgettext only knows about c/c++ line-continuation strings
462 it does not know about php's dot operator.
463 We want to translate this entire paragraph as one string, of course.
466 //$re_edit_link = Button('edit', _("Edit the new version"), $this->page);
469 $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.",
470 "<<<<<<< ". _("Your version"),
471 ">>>>>>> ". _("Other version")));
473 $message = HTML::p(_("Please check it through before saving."));
477 /*$steps = HTML::ol(HTML::li(_("Copy your changes to the clipboard or to another temporary place (e.g. text editor).")),
478 HTML::li(fmt("%s of the page. You should now see the most current version of the page. Your changes are no longer there.",
480 HTML::li(_("Make changes to the file again. Paste your additions from the clipboard (or text editor).")),
481 HTML::li(_("Save your updated changes.")));
484 HTML(HTML::h2(_("Conflicting Edits!")),
485 HTML::p(_("In the time since you started editing this page, another user has saved a new version of it.")),
486 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.")),
491 function getTextArea () {
492 $request = &$this->request;
494 $readonly = ! $this->canEdit(); // || $this->isConcurrentUpdate();
496 // WYSIWYG will need two pagetypes: raw wikitest and converted html
497 if (ENABLE_WYSIWYG) {
498 $this->_wikicontent = $this->_content;
499 $this->_content = $this->WysiwygEdit->ConvertBefore($this->_content);
500 // $this->getPreview();
501 //$this->_htmlcontent = $this->_content->asXML();
504 $textarea = HTML::textarea(array('class'=> 'wikiedit',
505 'name' => 'edit[content]',
506 'id' => 'edit:content',
507 'rows' => $request->getPref('editHeight'),
508 'cols' => $request->getPref('editWidth'),
509 'readonly' => (bool) $readonly),
511 /** <textarea wrap="virtual"> is not valid XHTML but Netscape 4 requires it
512 * to wrap long lines.
515 $textarea->setAttr('wrap', 'virtual');
516 if (ENABLE_WYSIWYG) {
517 return $this->WysiwygEdit->Textarea($textarea, $this->_wikicontent,
518 $textarea->getAttr('name'));
523 function getFormElements () {
525 $request = &$this->request;
526 $page = &$this->page;
528 $h = array('action' => 'edit',
529 'pagename' => $page->getName(),
530 'version' => $this->version,
531 'edit[pagetype]' => $this->meta['pagetype'],
532 'edit[current_version]' => $this->_currentVersion);
534 $el['HIDDEN_INPUTS'] = HiddenInputs($h);
535 $el['EDIT_TEXTAREA'] = $this->getTextArea();
536 if ( ENABLE_CAPTCHA ) {
537 $el = array_merge($el, $this->Captcha->getFormElements());
540 = HTML::input(array('type' => 'text',
541 'class' => 'wikitext',
542 'id' => 'edit:summary',
543 'name' => 'edit[summary]',
546 'value' => $this->meta['summary']));
548 = HTML::input(array('type' => 'checkbox',
549 'name' => 'edit[minor_edit]',
550 'id' => 'edit:minor_edit',
551 'checked' => (bool) $this->meta['is_minor_edit']));
553 = HTML::input(array('type' => 'checkbox',
554 'name' => 'edit[markup]',
556 'checked' => $this->meta['markup'] < 2.0,
557 'id' => 'useOldMarkup',
558 'onclick' => 'showOldMarkupRules(this.checked)'));
559 $el['OLD_MARKUP_CONVERT'] = ($this->meta['markup'] < 2.0)
560 ? Button('submit:edit[edit_convert]', _("Convert"), 'wikiaction') : '';
562 = HTML::input(array('type' => 'checkbox',
563 'name' => 'edit[locked]',
564 'id' => 'edit:locked',
565 'disabled' => (bool) !$this->user->isadmin(),
566 'checked' => (bool) $this->locked));
568 $el['PREVIEW_B'] = Button('submit:edit[preview]', _("Preview"),
571 //if (!$this->isConcurrentUpdate() && $this->canEdit())
572 $el['SAVE_B'] = Button('submit:edit[save]', _("Save"), 'wikiaction');
574 $el['IS_CURRENT'] = $this->version == $this->current->getVersion();
577 = HTML::input(array('type' => 'text',
580 'class' => "numeric",
581 'name' => 'pref[editWidth]',
582 'id' => 'pref:editWidth',
583 'value' => $request->getPref('editWidth'),
584 'onchange' => 'this.form.submit();'));
586 = HTML::input(array('type' => 'text',
589 'class' => "numeric",
590 'name' => 'pref[editHeight]',
591 'id' => 'pref:editHeight',
592 'value' => $request->getPref('editHeight'),
593 'onchange' => 'this.form.submit();'));
594 $el['SEP'] = $WikiTheme->getButtonSeparator();
595 $el['AUTHOR_MESSAGE'] = fmt("Author will be logged as %s.",
596 HTML::em($this->user->getId()));
601 function _redirectToBrowsePage() {
602 $this->request->redirect(WikiURL($this->page, false, 'absolute_url'));
605 function _restoreState () {
606 $request = &$this->request;
608 $posted = $request->getArg('edit');
609 $request->setArg('edit', false);
611 if (!$posted || !$request->isPost()
612 || $request->getArg('action') != 'edit')
615 if (!isset($posted['content']) || !is_string($posted['content']))
617 $this->_content = preg_replace('/[ \t\r]+\n/', "\n",
618 rtrim($posted['content']));
619 $this->_content = $this->getContent();
621 $this->_currentVersion = (int) $posted['current_version'];
623 if ($this->_currentVersion < 0)
625 if ($this->_currentVersion > $this->current->getVersion())
626 return false; // FIXME: some kind of warning?
628 $is_old_markup = !empty($posted['markup']) && $posted['markup'] == 'old';
629 $meta['markup'] = $is_old_markup ? false : 2.0;
630 $meta['summary'] = trim(substr($posted['summary'], 0, 256));
631 $meta['is_minor_edit'] = !empty($posted['minor_edit']);
632 $meta['pagetype'] = !empty($posted['pagetype']) ? $posted['pagetype'] : false;
633 if ( ENABLE_CAPTCHA )
634 $meta['captcha_input'] = !empty($posted['captcha_input']) ?
635 $posted['captcha_input'] : '';
637 $this->meta = array_merge($this->meta, $meta);
638 $this->locked = !empty($posted['locked']);
640 if (!empty($posted['preview']))
641 $this->editaction = 'preview';
642 elseif (!empty($posted['save']))
643 $this->editaction = 'save';
644 elseif (!empty($posted['edit_convert']))
645 $this->editaction = 'edit_convert';
647 $this->editaction = 'edit';
652 function _initializeState () {
653 $request = &$this->request;
654 $current = &$this->current;
655 $selected = &$this->selected;
656 $user = &$this->user;
659 NoSuchRevision($request, $this->page, $this->version); // noreturn
661 $this->_currentVersion = $current->getVersion();
662 $this->_content = $selected->getPackedContent();
664 $this->locked = $this->page->get('locked');
666 // If author same as previous author, default minor_edit to on.
667 $age = $this->meta['mtime'] - $current->get('mtime');
668 $this->meta['is_minor_edit'] = ( $age < MINOR_EDIT_TIMEOUT
669 && $current->get('author') == $user->getId()
672 // Default for new pages is new-style markup.
673 if ($selected->hasDefaultContents())
674 $is_new_markup = true;
676 $is_new_markup = $selected->get('markup') >= 2.0;
678 $this->meta['markup'] = $is_new_markup ? 2.0: false;
679 $this->meta['pagetype'] = $selected->get('pagetype');
680 if ($this->meta['pagetype'] == 'wikiblog')
681 $this->meta['summary'] = $selected->get('summary'); // keep blog title
683 $this->meta['summary'] = '';
684 $this->editaction = 'edit';
688 class LoadFileConflictPageEditor
691 function editPage ($saveFailed = true) {
692 $tokens = &$this->tokens;
694 if (!$this->canEdit()) {
695 if ($this->isInitialEdit())
696 return $this->viewSource();
697 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
699 elseif ($this->editaction == 'save') {
700 if ($this->savePage())
701 return true; // Page saved.
705 if ($saveFailed || $this->isConcurrentUpdate())
707 // Get the text of the original page, and the two conflicting edits
708 // The diff class takes arrays as input. So retrieve content as
709 // an array, or convert it as necesary.
710 $orig = $this->page->getRevision($this->_currentVersion);
711 $this_content = explode("\n", $this->_content);
712 $other_content = $this->current->getContent();
713 include_once("lib/diff.php");
714 $diff2 = new Diff($other_content, $this_content);
715 $context_lines = max(4, count($other_content) + 1,
716 count($this_content) + 1);
717 $fmt = new BlockDiffFormatter($context_lines);
719 $this->_content = $fmt->format($diff2);
720 // FIXME: integrate this into class BlockDiffFormatter
721 $this->_content = str_replace(">>>>>>>\n<<<<<<<\n", "=======\n",
723 $this->_content = str_replace("<<<<<<<\n>>>>>>>\n", "=======\n",
726 $this->_currentVersion = $this->current->getVersion();
727 $this->version = $this->_currentVersion;
728 $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage();
731 if ($this->editaction == 'edit_convert')
732 $tokens['PREVIEW_CONTENT'] = $this->getConvertedPreview();
733 if ($this->editaction == 'preview')
734 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
736 // FIXME: NOT_CURRENT_MESSAGE?
737 $tokens = array_merge($tokens, $this->getFormElements());
739 return $this->output('editpage', _("Merge and Edit: %s"));
740 // FIXME: this doesn't display
743 function output ($template, $title_fs) {
744 $selected = &$this->selected;
745 $current = &$this->current;
747 if ($selected && $selected->getVersion() != $current->getVersion()) {
749 $pagelink = WikiLink($selected);
753 $pagelink = WikiLink($this->page);
756 //$title = new FormattedText ($title_fs, $pagelink);
757 $template = Template($template, $this->tokens);
759 //GeneratePage($template, $title, $rev);
764 function getConflictMessage () {
765 $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.",
768 HTML::p(_("Please check it through before saving."))));
774 $Log: not supported by cvs2svn $
775 Revision 1.103 2005/10/31 17:09:13 rurban
776 use better constant WYSIWYG_DEFAULT_PAGETYPE_HTML
778 Revision 1.102 2005/10/31 16:47:14 rurban
779 enable wysiwyg html converters
781 Revision 1.101 2005/10/30 16:12:28 rurban
782 simplify viewsource tokens
784 Revision 1.100 2005/10/30 14:20:42 rurban
785 move Captcha specific vars and methods into a Captcha object
786 randomize Captcha chars positions and angles (smoothly)
788 Revision 1.99 2005/10/29 08:21:58 rurban
789 ENABLE_SPAMBLOCKLIST:
790 Check for links to blocked external tld domains in new edits, against
791 multi.surbl.org and bl.spamcop.net.
793 Revision 1.98 2005/10/10 19:37:04 rurban
794 change USE_HTMLAREA to ENABLE WYSIWYG, add NUM_SPAM_LINKS=20
796 Revision 1.97 2005/09/26 06:32:22 rurban
797 [] is forbidden in id tags. Renamed to use :
799 Revision 1.96 2005/05/06 17:54:22 rurban
800 silence Preview warnings for PAGE_LOCKED_MESSAGE, CONCURRENT_UPDATE_MESSAGE (thanks to schorni)
802 Revision 1.95 2005/04/25 20:17:14 rurban
803 captcha feature by Benjamin Drieu. Patch #1110699
805 Revision 1.94 2005/02/28 20:23:31 rurban
808 Revision 1.93 2005/02/27 19:31:52 rurban
809 hack: display errorstack without sideeffects (save and restore)
811 Revision 1.92 2005/01/29 20:37:21 rurban
812 no edit toolbar at all if ENABLE_EDITTOOLBAR = false
814 Revision 1.91 2005/01/25 07:05:49 rurban
815 extract toolbar code, support new tags to get rid of php inside templates
817 Revision 1.90 2005/01/22 12:46:15 rurban
818 fix oldmakrup button label
819 update pref[edit*] settings
821 Revision 1.89 2005/01/21 14:07:49 rurban
824 Revision 1.88 2004/12/17 16:39:03 rurban
827 Revision 1.87 2004/12/16 18:28:05 rurban
828 keep wikiblog summary = page title
830 Revision 1.86 2004/12/11 14:50:15 rurban
831 new edit_convert button, to get rid of old markup eventually
833 Revision 1.85 2004/12/06 19:49:56 rurban
834 enable action=remove which is undoable and seeable in RecentChanges: ADODB ony for now.
835 renamed delete_page to purge_page.
836 enable action=edit&version=-1 to force creation of a new version.
837 added BABYCART_PATH config
838 fixed magiqc in adodb.inc.php
841 Revision 1.84 2004/12/04 12:58:26 rurban
842 enable babycart Blog::SpamAssassin module on ENABLE_SPAMASSASSIN=true
843 (currently only for php >= 4.3.0)
845 Revision 1.83 2004/12/04 11:55:39 rurban
846 First simple AntiSpam prevention:
847 No more than 20 new http:// links allowed
849 Revision 1.82 2004/11/30 22:21:56 rurban
850 changed gif to optimized (pngout) png
852 Revision 1.81 2004/11/29 17:57:27 rurban
853 translated pulldown buttons
855 Revision 1.80 2004/11/25 17:20:51 rurban
856 and again a couple of more native db args: backlinks
858 Revision 1.79 2004/11/21 11:59:20 rurban
859 remove final \n to be ob_cache independent
861 Revision 1.78 2004/11/16 17:57:45 rurban
862 fix search&replace button
863 use new addTagButton machinery
864 new showPulldown for categories, TODO: in a seperate request
866 Revision 1.77 2004/11/15 15:52:35 rurban
869 Revision 1.76 2004/11/15 15:37:34 rurban
871 don't use document.write for replace, otherwise self.opener is not defined.
873 Revision 1.75 2004/09/16 08:00:52 rurban
876 Revision 1.74 2004/07/03 07:36:28 rurban
877 do not get unneccessary content
879 Revision 1.73 2004/06/16 21:23:44 rurban
880 fixed non-object fatal #215
882 Revision 1.72 2004/06/14 11:31:37 rurban
883 renamed global $Theme to $WikiTheme (gforge nameclash)
884 inherit PageList default options from PageList
885 default sortby=pagename
886 use options in PageList_Selectable (limit, sortby, ...)
887 added action revert, with button at action=diff
888 added option regex to WikiAdminSearchReplace
890 Revision 1.71 2004/06/03 18:06:29 rurban
891 fix file locking issues (only needed on write)
892 fixed immediate LANG and THEME in-session updates if not stored in prefs
893 advanced editpage toolbars (search & replace broken)
895 Revision 1.70 2004/06/02 20:47:47 rurban
896 dont use the wikiaction class
898 Revision 1.69 2004/06/02 10:17:56 rurban
899 integrated search/replace into toolbar
900 added save+preview buttons
902 Revision 1.68 2004/06/01 15:28:00 rurban
903 AdminUser only ADMIN_USER not member of Administrators
904 some RateIt improvements by dfrankow
907 Revision _1.6 2004/05/26 15:48:00 syilek
908 fixed problem with creating page with slashes from one true page
910 Revision _1.5 2004/05/25 16:51:53 syilek
911 added ability to create a page from the category page and not have to edit it
913 Revision 1.67 2004/05/27 17:49:06 rurban
914 renamed DB_Session to DbSession (in CVS also)
915 added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
916 remove leading slash in error message
917 added force_unlock parameter to File_Passwd (no return on stale locks)
918 fixed adodb session AffectedRows
919 added FileFinder helpers to unify local filenames and DATA_PATH names
920 editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
922 Revision 1.66 2004/04/29 23:25:12 rurban
923 re-ordered locale init (as in 1.3.9)
924 fixed loadfile with subpages, and merge/restore anyway
927 Revision 1.65 2004/04/18 01:11:52 rurban
928 more numeric pagename fixes.
929 fixed action=upload with merge conflict warnings.
930 charset changed from constant to global (dynamic utf-8 switching)
932 Revision 1.64 2004/04/06 19:48:56 rurban
933 temp workaround for action=edit AddComment form
935 Revision 1.63 2004/03/24 19:39:02 rurban
936 php5 workaround code (plus some interim debugging code in XmlElement)
937 php5 doesn't work yet with the current XmlElement class constructors,
938 WikiUserNew does work better than php4.
939 rewrote WikiUserNew user upgrading to ease php5 update
940 fixed pref handling in WikiUserNew
941 added Email Notification
942 added simple Email verification
943 removed emailVerify userpref subclass: just a email property
944 changed pref binary storage layout: numarray => hash of non default values
945 print optimize message only if really done.
946 forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
947 prefs should be stored in db or homepage, besides the current session.
949 Revision 1.62 2004/03/17 18:41:05 rurban
950 initial_content and template support for CreatePage
952 Revision 1.61 2004/03/12 20:59:17 rurban
953 important cookie fix by Konstantin Zadorozhny
954 new editpage feature: JS_SEARCHREPLACE
956 Revision 1.60 2004/02/15 21:34:37 rurban
957 PageList enhanced and improved.
958 fixed new WikiAdmin... plugins
959 editpage, Theme with exp. htmlarea framework
960 (htmlarea yet committed, this is really questionable)
961 WikiUser... code with better session handling for prefs
962 enhanced UserPreferences (again)
963 RecentChanges for show_deleted: how should pages be deleted then?
965 Revision 1.59 2003/12/07 20:35:26 carstenklapp
966 Bugfix: Concurrent updates broken since after 1.3.4 release: Fatal
967 error: Call to undefined function: gettransformedcontent() in
968 /home/groups/p/ph/phpwiki/htdocs/phpwiki2/lib/editpage.php on line
971 Revision 1.58 2003/03/10 18:25:22 dairiki
972 Bug/typo fix. If you use the edit page to un/lock a page, it
973 failed with: Fatal error: Call to a member function on a
974 non-object in editpage.php on line 136
976 Revision 1.57 2003/02/26 03:40:22 dairiki
977 New action=create. Essentially the same as action=edit, except that if the
978 page already exists, it falls back to action=browse.
980 This is for use in the "question mark" links for unknown wiki words
981 to avoid problems and confusion when following links from stale pages.
982 (If the "unknown page" has been created in the interim, the user probably
983 wants to view the page before editing it.)
985 Revision 1.56 2003/02/21 18:07:14 dairiki
986 Minor, nitpicky, currently inconsequential changes.
988 Revision 1.55 2003/02/21 04:10:58 dairiki
989 Fixes for new cached markup.
990 Some minor code cleanups.
992 Revision 1.54 2003/02/16 19:47:16 dairiki
993 Update WikiDB timestamp when editing or deleting pages.
995 Revision 1.53 2003/02/15 23:20:27 dairiki
996 Redirect back to browse current version of page upon save,
997 even when no changes were made.
999 Revision 1.52 2003/01/03 22:22:00 carstenklapp
1000 Minor adjustments to diff block markers ("<<<<<<<"). Source reformatting.
1002 Revision 1.51 2003/01/03 02:43:26 carstenklapp
1003 New class LoadFileConflictPageEditor, for merging / comparing a loaded
1004 pgsrc file with an existing page.
1011 // c-basic-offset: 4
1012 // c-hanging-comment-ender-p: nil
1013 // indent-tabs-mode: nil