2 rcs_id('$Id: editpage.php,v 1.109 2007-01-02 13:21:39 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
22 $this->meta = array('author' => $this->user->getId(),
23 'author_id' => $this->user->getAuthenticatedId(),
26 $this->tokens = array();
29 $backend = WYSIWYG_BACKEND;
30 // TODO: error message
31 require_once("lib/WysiwygEdit/$backend.php");
32 $class = "WysiwygEdit_$backend";
33 $this->WysiwygEdit = new $class();
36 require_once('lib/Captcha.php');
37 $this->Captcha = new Captcha($this->meta);
40 $version = $request->getArg('version');
41 if ($version !== false) {
42 $this->selected = $this->page->getRevision($version);
43 $this->version = $version;
46 $this->version = $this->current->getVersion();
47 $this->selected = $this->page->getRevision($this->version);
50 if ($this->_restoreState()) {
51 $this->_initialEdit = false;
54 $this->_initializeState();
55 $this->_initialEdit = true;
57 // The edit request has specified some initial content from a template
58 if ( ($template = $request->getArg('template'))
59 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'] = '';
81 if (isset($r->args['pref']['editWidth'])
82 and ($r->getPref('editWidth') != $r->args['pref']['editWidth'])) {
83 $r->_prefs->set('editWidth', $r->args['pref']['editWidth']);
85 if (isset($r->args['pref']['editHeight'])
86 and ($r->getPref('editHeight') != $r->args['pref']['editHeight'])) {
87 $r->_prefs->set('editHeight', $r->args['pref']['editHeight']);
90 if (! $this->canEdit()) {
91 if ($this->isInitialEdit())
92 return $this->viewSource();
93 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
95 elseif ($r->getArg('save_and_redirect_to') != "") {
96 if (ENABLE_CAPTCHA && $this->Captcha->Failed()) {
97 $this->tokens['PAGE_LOCKED_MESSAGE'] =
98 HTML::p(HTML::h1($this->Captcha->failed_msg));
100 elseif ( $this->savePage()) {
102 $r->redirect(WikiURL($r->getArg('save_and_redirect_to')));
103 return true; // Page saved.
107 elseif ($this->editaction == 'save') {
108 if (ENABLE_CAPTCHA && $this->Captcha->Failed()) {
109 $this->tokens['PAGE_LOCKED_MESSAGE'] =
110 HTML::p(HTML::h1($this->Captcha->failed_msg));
112 elseif ($this->savePage()) {
113 return true; // Page saved.
119 // coming from loadfile conflicts
120 elseif ($this->editaction == 'keep_old') {
121 // keep old page and do nothing
122 $this->_redirectToBrowsePage();
123 //$r->redirect(WikiURL($r->getArg('save_and_redirect_to')));
126 elseif ($this->editaction == 'overwrite') {
127 // take the new content without diff
128 $source = $this->request->getArg('loadfile');
129 include_once('lib/loadsave.php');
130 $this->request->setArg('loadfile', 1);
131 $this->request->setArg('overwrite', 1);
132 $this->request->setArg('merge', 0);
133 LoadFileOrDir($this->request);
134 $this->_redirectToBrowsePage();
135 //$r->redirect(WikiURL($r->getArg('save_and_redirect_to')));
139 if ($saveFailed and $this->isConcurrentUpdate())
141 // Get the text of the original page, and the two conflicting edits
142 // The diff3 class takes arrays as input. So retrieve content as
143 // an array, or convert it as necesary.
144 $orig = $this->page->getRevision($this->_currentVersion);
145 // FIXME: what if _currentVersion has be deleted?
146 $orig_content = $orig->getContent();
147 $this_content = explode("\n", $this->_content);
148 $other_content = $this->current->getContent();
149 include_once("lib/diff3.php");
150 $diff = new diff3($orig_content, $this_content, $other_content);
151 $output = $diff->merged_output(_("Your version"), _("Other version"));
152 // Set the content of the textarea to the merged diff
153 // output, and update the version
154 $this->_content = implode ("\n", $output);
155 $this->_currentVersion = $this->current->getVersion();
156 $this->version = $this->_currentVersion;
157 $unresolved = $diff->ConflictingBlocks;
158 $tokens['CONCURRENT_UPDATE_MESSAGE']
159 = $this->getConflictMessage($unresolved);
160 } elseif ($saveFailed && !$this->_isSpam) {
161 $tokens['CONCURRENT_UPDATE_MESSAGE'] =
162 HTML(HTML::h2(_("Some internal editing error")),
163 HTML::p(_("Your are probably trying to edit/create an invalid version of this page.")),
164 HTML::p(HTML::em(_("&version=-1 might help."))));
167 if ($this->editaction == 'edit_convert')
168 $tokens['PREVIEW_CONTENT'] = $this->getConvertedPreview();
169 if ($this->editaction == 'preview')
170 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
172 // FIXME: NOT_CURRENT_MESSAGE?
173 $tokens = array_merge($tokens, $this->getFormElements());
175 if (ENABLE_EDIT_TOOLBAR and !ENABLE_WYSIWYG) {
176 include_once("lib/EditToolbar.php");
177 $toolbar = new EditToolbar();
178 $tokens = array_merge($tokens, $toolbar->getTokens());
181 return $this->output('editpage', _("Edit: %s"));
184 function output ($template, $title_fs) {
186 $selected = &$this->selected;
187 $current = &$this->current;
189 if ($selected && $selected->getVersion() != $current->getVersion()) {
191 $pagelink = WikiLink($selected);
195 $pagelink = WikiLink($this->page);
198 $title = new FormattedText ($title_fs, $pagelink);
199 // not for dumphtml or viewsource
200 if (ENABLE_WYSIWYG and $template == 'editpage') {
201 $WikiTheme->addMoreHeaders($this->WysiwygEdit->Head());
202 //$tokens['PAGE_SOURCE'] = $this->WysiwygEdit->ConvertBefore($this->_content);
204 $template = Template($template, $this->tokens);
205 GeneratePage($template, $title, $rev);
210 function viewSource () {
211 assert($this->isInitialEdit());
212 assert($this->selected);
214 $this->tokens['PAGE_SOURCE'] = $this->_content;
215 $this->tokens['HIDDEN_INPUTS'] = HiddenInputs($this->request->getArgs());
216 return $this->output('viewsource', _("View Source: %s"));
219 function updateLock() {
220 if ((bool)$this->page->get('locked') == (bool)$this->locked)
221 return false; // Not changed.
223 if (!$this->user->isAdmin()) {
224 // FIXME: some sort of message
225 return false; // not allowed.
228 $this->page->set('locked', (bool)$this->locked);
229 $this->tokens['LOCK_CHANGED_MSG']
230 = $this->locked ? _("Page now locked.") : _("Page now unlocked.");
232 return true; // lock changed.
235 function savePage () {
236 $request = &$this->request;
238 if ($this->isUnchanged()) {
239 // Allow admin lock/unlock even if
240 // no text changes were made.
241 if ($this->updateLock()) {
242 $dbi = $request->getDbh();
245 // Save failed. No changes made.
246 $this->_redirectToBrowsePage();
247 // user will probably not see the rest of this...
248 include_once('lib/display.php');
249 // force browse of current version:
250 $request->setArg('version', false);
251 displayPage($request, 'nochanges');
255 if (!$this->user->isAdmin() and $this->isSpam()) {
256 $this->_isSpam = true;
259 // Save failed. No changes made.
260 $this->_redirectToBrowsePage();
261 // user will probably not see the rest of this...
262 include_once('lib/display.php');
263 // force browse of current version:
264 $request->setArg('version', false);
265 displayPage($request, 'nochanges');
270 $page = &$this->page;
272 // Include any meta-data from original page version which
273 // has not been explicitly updated.
274 // (Except don't propagate pgsrc_version --- moot for now,
275 // because at present it never gets into the db...)
276 $meta = $this->selected->getMetaData();
277 unset($meta['pgsrc_version']);
278 $meta = array_merge($meta, $this->meta);
281 $this->_content = $this->getContent();
282 $newrevision = $page->save($this->_content,
285 : $this->_currentVersion + 1,
288 if (!isa($newrevision, 'WikiDB_PageRevision')) {
289 // Save failed. (Concurrent updates).
293 // New contents successfully saved...
296 // Clean out archived versions of this page.
297 include_once('lib/ArchiveCleaner.php');
298 $cleaner = new ArchiveCleaner($GLOBALS['ExpireParams']);
299 $cleaner->cleanPageRevisions($page);
301 /* generate notification emails done in WikiDB::save to catch
302 all direct calls (admin plugins) */
304 // look at the errorstack
305 $errors = $GLOBALS['ErrorManager']->_postponed_errors;
306 $warnings = $GLOBALS['ErrorManager']->getPostponedErrorsAsHTML();
307 $GLOBALS['ErrorManager']->_postponed_errors = $errors;
309 $dbi = $request->getDbh();
313 if (empty($warnings->_content) && ! $WikiTheme->getImageURL('signature')) {
314 // Do redirect to browse page if no signature has
315 // been defined. In this case, the user will most
316 // likely not see the rest of the HTML we generate
318 $this->_redirectToBrowsePage();
321 // Force browse of current page version.
322 $request->setArg('version', false);
323 $request->setArg('action', "browse");
325 $template = Template('savepage', $this->tokens);
326 $template->replace('CONTENT', $newrevision->getTransformedContent());
327 if (!empty($warnings->_content)) {
328 $template->replace('WARNINGS', $warnings);
329 unset($GLOBALS['ErrorManager']->_postponed_errors);
332 $pagelink = WikiLink($page);
334 GeneratePage($template, fmt("Saved: %s", $pagelink), $newrevision);
338 function isConcurrentUpdate () {
339 assert($this->current->getVersion() >= $this->_currentVersion);
340 return $this->current->getVersion() != $this->_currentVersion;
343 function canEdit () {
344 return !$this->page->get('locked') || $this->user->isAdmin();
347 function isInitialEdit () {
348 return $this->_initialEdit;
351 function isUnchanged () {
352 $current = &$this->current;
354 if ($this->meta['markup'] != $current->get('markup'))
357 return $this->_content == $current->getPackedContent();
361 * Handle AntiSpam here. How? http://wikiblacklist.blogspot.com/
362 * Need to check dynamically some blacklist wikipage settings
363 * (plugin WikiAccessRestrictions) and some static blacklist.
365 * Always: More then 20 new external links
366 * ENABLE_SPAMASSASSIN: content patterns by babycart (only php >= 4.3 for now)
367 * ENABLE_SPAMBLOCKLIST: content domain blacklist
370 $current = &$this->current;
371 $request = &$this->request;
373 $oldtext = $current->getPackedContent();
374 $newtext =& $this->_content;
376 // FIXME: in longer texts the NUM_SPAM_LINKS number should be increased.
377 // better use a certain text : link ratio.
379 // 1. Not more then 20 new external links
380 if ($this->numLinks($newtext) - $this->numLinks($oldtext) >= NUM_SPAM_LINKS)
382 // Allow strictly authenticated users?
383 // TODO: mail the admin?
384 $this->tokens['PAGE_LOCKED_MESSAGE'] =
385 HTML($this->getSpamMessage(),
386 HTML::p(HTML::strong(_("Too many external links."))));
389 // 2. external babycart (SpamAssassin) check
390 // This will probably prevent from discussing sex or viagra related topics. So beware.
391 if (ENABLE_SPAMASSASSIN) {
392 include_once("lib/spam_babycart.php");
393 if ($babycart = check_babycart($newtext, $request->get("REMOTE_ADDR"),
394 $this->user->getId())) {
395 // TODO: mail the admin
396 if (is_array($babycart))
397 $this->tokens['PAGE_LOCKED_MESSAGE'] =
398 HTML($this->getSpamMessage(),
399 HTML::p(HTML::em(_("SpamAssassin reports: "),
400 join("\n", $babycart))));
404 // 3. extract (new) links and check surbl for blocked domains
405 if (ENABLE_SPAMBLOCKLIST and $this->numLinks($newtext)) {
406 include_once("lib/SpamBlocklist.php");
407 include_once("lib/InlineParser.php");
408 $parsed = TransformLinks($newtext);
409 foreach ($parsed->_content as $link) {
410 if (isa($link, 'Cached_ExternalLink')) {
411 $uri = $link->_getURL($this->page->getName());
412 if ($res = IsBlackListed($uri)) {
413 // TODO: mail the admin
414 $this->tokens['PAGE_LOCKED_MESSAGE'] =
415 HTML($this->getSpamMessage(),
416 HTML::p(HTML::strong(_("External links contain blocked domains:")),
417 HTML::ul(HTML::li(sprintf(_("%s is listed at %s"),
418 $res[2], $res[0])))));
428 /** Number of external links in the wikitext
430 function numLinks(&$text) {
431 return substr_count($text, "http://") + substr_count($text, "https://");
434 /** Header of the Anti Spam message
436 function getSpamMessage () {
438 HTML(HTML::h2(_("Spam Prevention")),
439 HTML::p(_("This page edit seems to contain spam and was therefore not saved."),
441 _("Sorry for the inconvenience.")),
445 function getPreview () {
446 include_once('lib/PageType.php');
447 $this->_content = $this->getContent();
448 return new TransformedText($this->page, $this->_content, $this->meta);
451 function getConvertedPreview () {
452 include_once('lib/PageType.php');
453 $this->_content = $this->getContent();
454 $this->meta['markup'] = 2.0;
455 $this->_content = ConvertOldMarkup($this->_content);
456 return new TransformedText($this->page, $this->_content, $this->meta);
459 // possibly convert HTMLAREA content back to Wiki markup
460 function getContent () {
461 if (ENABLE_WYSIWYG) {
462 // don't store everything as html
463 if (!WYSIWYG_DEFAULT_PAGETYPE_HTML) {
464 // Wikiwyg shortcut to avoid the InlineTransformer:
465 if (WYSIWYG_BACKEND == "Wikiwyg") return $this->_content;
466 $xml_output = $this->WysiwygEdit->ConvertAfter($this->_content);
467 $this->_content = join("", $xml_output->_content);
469 $this->meta['pagetype'] = 'html';
471 return $this->_content;
473 return $this->_content;
477 function getLockedMessage () {
479 HTML(HTML::h2(_("Page Locked")),
480 HTML::p(_("This page has been locked by the administrator so your changes can not be saved.")),
481 HTML::p(_("(Copy your changes to the clipboard. You can try editing a different page or save your text in a text editor.)")),
482 HTML::p(_("Sorry for the inconvenience.")));
485 function getConflictMessage ($unresolved = false) {
487 xgettext only knows about c/c++ line-continuation strings
488 it does not know about php's dot operator.
489 We want to translate this entire paragraph as one string, of course.
492 //$re_edit_link = Button('edit', _("Edit the new version"), $this->page);
495 $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.",
496 "<<<<<<< ". _("Your version"),
497 ">>>>>>> ". _("Other version")));
499 $message = HTML::p(_("Please check it through before saving."));
503 /*$steps = HTML::ol(HTML::li(_("Copy your changes to the clipboard or to another temporary place (e.g. text editor).")),
504 HTML::li(fmt("%s of the page. You should now see the most current version of the page. Your changes are no longer there.",
506 HTML::li(_("Make changes to the file again. Paste your additions from the clipboard (or text editor).")),
507 HTML::li(_("Save your updated changes.")));
510 HTML(HTML::h2(_("Conflicting Edits!")),
511 HTML::p(_("In the time since you started editing this page, another user has saved a new version of it.")),
512 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.")),
517 function getTextArea () {
518 $request = &$this->request;
520 $readonly = ! $this->canEdit(); // || $this->isConcurrentUpdate();
522 // WYSIWYG will need two pagetypes: raw wikitest and converted html
523 if (ENABLE_WYSIWYG) {
524 $this->_wikicontent = $this->_content;
525 $this->_content = $this->WysiwygEdit->ConvertBefore($this->_content);
526 // $this->getPreview();
527 //$this->_htmlcontent = $this->_content->asXML();
530 $textarea = HTML::textarea(array('class'=> 'wikiedit',
531 'name' => 'edit[content]',
532 'id' => 'edit:content',
533 'rows' => $request->getPref('editHeight'),
534 'cols' => $request->getPref('editWidth'),
535 'readonly' => (bool) $readonly),
537 /** <textarea wrap="virtual"> is not valid XHTML but Netscape 4 requires it
538 * to wrap long lines.
541 $textarea->setAttr('wrap', 'virtual');
542 if (ENABLE_WYSIWYG) {
543 return $this->WysiwygEdit->Textarea($textarea, $this->_wikicontent,
544 $textarea->getAttr('name'));
549 function getFormElements () {
551 $request = &$this->request;
552 $page = &$this->page;
554 $h = array('action' => 'edit',
555 'pagename' => $page->getName(),
556 'version' => $this->version,
557 'edit[pagetype]' => $this->meta['pagetype'],
558 'edit[current_version]' => $this->_currentVersion);
560 $el['HIDDEN_INPUTS'] = HiddenInputs($h);
561 $el['EDIT_TEXTAREA'] = $this->getTextArea();
562 if ( ENABLE_CAPTCHA ) {
563 $el = array_merge($el, $this->Captcha->getFormElements());
566 = HTML::input(array('type' => 'text',
567 'class' => 'wikitext',
568 'id' => 'edit:summary',
569 'name' => 'edit[summary]',
572 'value' => $this->meta['summary']));
574 = HTML::input(array('type' => 'checkbox',
575 'name' => 'edit[minor_edit]',
576 'id' => 'edit:minor_edit',
577 'checked' => (bool) $this->meta['is_minor_edit']));
579 = HTML::input(array('type' => 'checkbox',
580 'name' => 'edit[markup]',
582 'checked' => $this->meta['markup'] < 2.0,
583 'id' => 'useOldMarkup',
584 'onclick' => 'showOldMarkupRules(this.checked)'));
585 $el['OLD_MARKUP_CONVERT'] = ($this->meta['markup'] < 2.0)
586 ? Button('submit:edit[edit_convert]', _("Convert"), 'wikiaction') : '';
588 = HTML::input(array('type' => 'checkbox',
589 'name' => 'edit[locked]',
590 'id' => 'edit:locked',
591 'disabled' => (bool) !$this->user->isadmin(),
592 'checked' => (bool) $this->locked));
594 $el['PREVIEW_B'] = Button('submit:edit[preview]', _("Preview"),
596 array('accesskey'=> 'p'));
598 //if (!$this->isConcurrentUpdate() && $this->canEdit())
599 $el['SAVE_B'] = Button('submit:edit[save]',
600 _("Save"), 'wikiaction',
601 array('accesskey'=> 's'));
602 $el['IS_CURRENT'] = $this->version == $this->current->getVersion();
605 = HTML::input(array('type' => 'text',
608 'class' => "numeric",
609 'name' => 'pref[editWidth]',
610 'id' => 'pref:editWidth',
611 'value' => $request->getPref('editWidth'),
612 'onchange' => 'this.form.submit();'));
614 = HTML::input(array('type' => 'text',
617 'class' => "numeric",
618 'name' => 'pref[editHeight]',
619 'id' => 'pref:editHeight',
620 'value' => $request->getPref('editHeight'),
621 'onchange' => 'this.form.submit();'));
622 $el['SEP'] = $WikiTheme->getButtonSeparator();
623 $el['AUTHOR_MESSAGE'] = fmt("Author will be logged as %s.",
624 HTML::em($this->user->getId()));
629 function _redirectToBrowsePage() {
630 $this->request->redirect(WikiURL($this->page, false, 'absolute_url'));
633 function _restoreState () {
634 $request = &$this->request;
636 $posted = $request->getArg('edit');
637 $request->setArg('edit', false);
640 || !$request->isPost()
641 || !in_array($request->getArg('action'),array('edit','loadfile')))
644 if (!isset($posted['content']) || !is_string($posted['content']))
646 $this->_content = preg_replace('/[ \t\r]+\n/', "\n",
647 rtrim($posted['content']));
648 $this->_content = $this->getContent();
650 $this->_currentVersion = (int) $posted['current_version'];
652 if ($this->_currentVersion < 0)
654 if ($this->_currentVersion > $this->current->getVersion())
655 return false; // FIXME: some kind of warning?
657 $is_old_markup = !empty($posted['markup']) && $posted['markup'] == 'old';
658 $meta['markup'] = $is_old_markup ? false : 2.0;
659 $meta['summary'] = trim(substr($posted['summary'], 0, 256));
660 $meta['is_minor_edit'] = !empty($posted['minor_edit']);
661 $meta['pagetype'] = !empty($posted['pagetype']) ? $posted['pagetype'] : false;
662 if ( ENABLE_CAPTCHA )
663 $meta['captcha_input'] = !empty($posted['captcha_input']) ?
664 $posted['captcha_input'] : '';
666 $this->meta = array_merge($this->meta, $meta);
667 $this->locked = !empty($posted['locked']);
669 foreach (array('preview','save','edit_convert',
670 'keep_old','overwrite') as $o)
672 if (!empty($posted[$o]))
673 $this->editaction = $o;
675 if (empty($this->editaction))
676 $this->editaction = 'edit';
681 function _initializeState () {
682 $request = &$this->request;
683 $current = &$this->current;
684 $selected = &$this->selected;
685 $user = &$this->user;
688 NoSuchRevision($request, $this->page, $this->version); // noreturn
690 $this->_currentVersion = $current->getVersion();
691 $this->_content = $selected->getPackedContent();
693 $this->locked = $this->page->get('locked');
695 // If author same as previous author, default minor_edit to on.
696 $age = $this->meta['mtime'] - $current->get('mtime');
697 $this->meta['is_minor_edit'] = ( $age < MINOR_EDIT_TIMEOUT
698 && $current->get('author') == $user->getId()
701 // Default for new pages is new-style markup.
702 if ($selected->hasDefaultContents())
703 $is_new_markup = true;
705 $is_new_markup = $selected->get('markup') >= 2.0;
707 $this->meta['markup'] = $is_new_markup ? 2.0: false;
708 $this->meta['pagetype'] = $selected->get('pagetype');
709 if ($this->meta['pagetype'] == 'wikiblog')
710 $this->meta['summary'] = $selected->get('summary'); // keep blog title
712 $this->meta['summary'] = '';
713 $this->editaction = 'edit';
717 class LoadFileConflictPageEditor
720 function editPage ($saveFailed = true) {
721 $tokens = &$this->tokens;
723 if (!$this->canEdit()) {
724 if ($this->isInitialEdit()) {
725 return $this->viewSource();
727 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
729 elseif ($this->editaction == 'save') {
730 if ($this->savePage()) {
731 return true; // Page saved.
736 if ($saveFailed || $this->isConcurrentUpdate())
738 // Get the text of the original page, and the two conflicting edits
739 // The diff class takes arrays as input. So retrieve content as
740 // an array, or convert it as necesary.
741 $orig = $this->page->getRevision($this->_currentVersion);
742 $this_content = explode("\n", $this->_content);
743 $other_content = $this->current->getContent();
744 include_once("lib/diff.php");
745 $diff2 = new Diff($other_content, $this_content);
746 $context_lines = max(4, count($other_content) + 1,
747 count($this_content) + 1);
748 $fmt = new BlockDiffFormatter($context_lines);
750 $this->_content = $fmt->format($diff2);
751 // FIXME: integrate this into class BlockDiffFormatter
752 $this->_content = str_replace(">>>>>>>\n<<<<<<<\n", "=======\n",
754 $this->_content = str_replace("<<<<<<<\n>>>>>>>\n", "=======\n",
757 $this->_currentVersion = $this->current->getVersion();
758 $this->version = $this->_currentVersion;
759 $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage();
762 if ($this->editaction == 'edit_convert')
763 $tokens['PREVIEW_CONTENT'] = $this->getConvertedPreview();
764 if ($this->editaction == 'preview')
765 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
767 // FIXME: NOT_CURRENT_MESSAGE?
768 $tokens = array_merge($tokens, $this->getFormElements());
769 // we need all GET params for loadfile overwrite
770 if ($this->request->getArg('action') == 'loadfile') {
772 $this->tokens['HIDDEN_INPUTS'] =
774 (array('source' => $this->request->getArg('source'),
776 $this->tokens['HIDDEN_INPUTS']);
777 // add two conflict resolution buttons before preview and save.
778 $tokens['PREVIEW_B'] = HTML(
779 Button('submit:edit[keep_old]',
780 _("Keep old"), 'wikiaction'),
782 Button('submit:edit[overwrite]',
783 _("Overwrite with new"), 'wikiaction'),
785 $tokens['PREVIEW_B']);
787 if (ENABLE_EDIT_TOOLBAR and !ENABLE_WYSIWYG) {
788 include_once("lib/EditToolbar.php");
789 $toolbar = new EditToolbar();
790 $tokens = array_merge($tokens, $toolbar->getTokens());
793 return $this->output('editpage', _("Merge and Edit: %s"));
796 function output ($template, $title_fs) {
797 $selected = &$this->selected;
798 $current = &$this->current;
800 if ($selected && $selected->getVersion() != $current->getVersion()) {
802 $pagelink = WikiLink($selected);
806 $pagelink = WikiLink($this->page);
809 $title = new FormattedText ($title_fs, $pagelink);
810 $this->tokens['HEADER'] = $title;
811 //hack! there's no TITLE in editpage, but in the previous top template
812 if (empty($this->tokens['PAGE_LOCKED_MESSAGE']))
813 $this->tokens['PAGE_LOCKED_MESSAGE'] = HTML::h3($title);
815 $this->tokens['PAGE_LOCKED_MESSAGE'] = HTML(HTML::h3($title),
816 $this->tokens['PAGE_LOCKED_MESSAGE']);
817 $template = Template($template, $this->tokens);
819 //GeneratePage($template, $title, $rev);
824 function getConflictMessage () {
825 $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.",
828 HTML::p(_("Please check it through before saving."))));
834 $Log: not supported by cvs2svn $
835 Revision 1.108 2006/12/22 17:47:34 rurban
836 Display Warnings only once.
837 Add button accesskeys
839 Revision 1.107 2006/05/13 19:59:54 rurban
840 added wysiwyg_editor-1.3a feature by Jean-Nicolas GEREONE <jean-nicolas.gereone@st.com>
841 converted wysiwyg_editor-1.3a js to WysiwygEdit framework
842 changed default ENABLE_WYSIWYG = true and added WYSIWYG_BACKEND = Wikiwyg
844 Revision 1.106 2005/11/21 22:03:08 rurban
845 fix syntax error inside ENABLE_SPAMBLOCKLIST
847 Revision 1.105 2005/11/21 20:53:59 rurban
848 beautify request pref lines, no antispam if admin (netznetz request), user is a member anyway
850 Revision 1.104 2005/10/31 17:20:40 rurban
853 Revision 1.103 2005/10/31 17:09:13 rurban
854 use better constant WYSIWYG_DEFAULT_PAGETYPE_HTML
856 Revision 1.102 2005/10/31 16:47:14 rurban
857 enable wysiwyg html converters
859 Revision 1.101 2005/10/30 16:12:28 rurban
860 simplify viewsource tokens
862 Revision 1.100 2005/10/30 14:20:42 rurban
863 move Captcha specific vars and methods into a Captcha object
864 randomize Captcha chars positions and angles (smoothly)
866 Revision 1.99 2005/10/29 08:21:58 rurban
867 ENABLE_SPAMBLOCKLIST:
868 Check for links to blocked external tld domains in new edits, against
869 multi.surbl.org and bl.spamcop.net.
871 Revision 1.98 2005/10/10 19:37:04 rurban
872 change USE_HTMLAREA to ENABLE WYSIWYG, add NUM_SPAM_LINKS=20
874 Revision 1.97 2005/09/26 06:32:22 rurban
875 [] is forbidden in id tags. Renamed to use :
877 Revision 1.96 2005/05/06 17:54:22 rurban
878 silence Preview warnings for PAGE_LOCKED_MESSAGE, CONCURRENT_UPDATE_MESSAGE (thanks to schorni)
880 Revision 1.95 2005/04/25 20:17:14 rurban
881 captcha feature by Benjamin Drieu. Patch #1110699
883 Revision 1.94 2005/02/28 20:23:31 rurban
886 Revision 1.93 2005/02/27 19:31:52 rurban
887 hack: display errorstack without sideeffects (save and restore)
889 Revision 1.92 2005/01/29 20:37:21 rurban
890 no edit toolbar at all if ENABLE_EDITTOOLBAR = false
892 Revision 1.91 2005/01/25 07:05:49 rurban
893 extract toolbar code, support new tags to get rid of php inside templates
895 Revision 1.90 2005/01/22 12:46:15 rurban
896 fix oldmakrup button label
897 update pref[edit*] settings
899 Revision 1.89 2005/01/21 14:07:49 rurban
902 Revision 1.88 2004/12/17 16:39:03 rurban
905 Revision 1.87 2004/12/16 18:28:05 rurban
906 keep wikiblog summary = page title
908 Revision 1.86 2004/12/11 14:50:15 rurban
909 new edit_convert button, to get rid of old markup eventually
911 Revision 1.85 2004/12/06 19:49:56 rurban
912 enable action=remove which is undoable and seeable in RecentChanges: ADODB ony for now.
913 renamed delete_page to purge_page.
914 enable action=edit&version=-1 to force creation of a new version.
915 added BABYCART_PATH config
916 fixed magiqc in adodb.inc.php
919 Revision 1.84 2004/12/04 12:58:26 rurban
920 enable babycart Blog::SpamAssassin module on ENABLE_SPAMASSASSIN=true
921 (currently only for php >= 4.3.0)
923 Revision 1.83 2004/12/04 11:55:39 rurban
924 First simple AntiSpam prevention:
925 No more than 20 new http:// links allowed
927 Revision 1.82 2004/11/30 22:21:56 rurban
928 changed gif to optimized (pngout) png
930 Revision 1.81 2004/11/29 17:57:27 rurban
931 translated pulldown buttons
933 Revision 1.80 2004/11/25 17:20:51 rurban
934 and again a couple of more native db args: backlinks
936 Revision 1.79 2004/11/21 11:59:20 rurban
937 remove final \n to be ob_cache independent
939 Revision 1.78 2004/11/16 17:57:45 rurban
940 fix search&replace button
941 use new addTagButton machinery
942 new showPulldown for categories, TODO: in a seperate request
944 Revision 1.77 2004/11/15 15:52:35 rurban
947 Revision 1.76 2004/11/15 15:37:34 rurban
949 don't use document.write for replace, otherwise self.opener is not defined.
951 Revision 1.75 2004/09/16 08:00:52 rurban
954 Revision 1.74 2004/07/03 07:36:28 rurban
955 do not get unneccessary content
957 Revision 1.73 2004/06/16 21:23:44 rurban
958 fixed non-object fatal #215
960 Revision 1.72 2004/06/14 11:31:37 rurban
961 renamed global $Theme to $WikiTheme (gforge nameclash)
962 inherit PageList default options from PageList
963 default sortby=pagename
964 use options in PageList_Selectable (limit, sortby, ...)
965 added action revert, with button at action=diff
966 added option regex to WikiAdminSearchReplace
968 Revision 1.71 2004/06/03 18:06:29 rurban
969 fix file locking issues (only needed on write)
970 fixed immediate LANG and THEME in-session updates if not stored in prefs
971 advanced editpage toolbars (search & replace broken)
973 Revision 1.70 2004/06/02 20:47:47 rurban
974 dont use the wikiaction class
976 Revision 1.69 2004/06/02 10:17:56 rurban
977 integrated search/replace into toolbar
978 added save+preview buttons
980 Revision 1.68 2004/06/01 15:28:00 rurban
981 AdminUser only ADMIN_USER not member of Administrators
982 some RateIt improvements by dfrankow
985 Revision _1.6 2004/05/26 15:48:00 syilek
986 fixed problem with creating page with slashes from one true page
988 Revision _1.5 2004/05/25 16:51:53 syilek
989 added ability to create a page from the category page and not have to edit it
991 Revision 1.67 2004/05/27 17:49:06 rurban
992 renamed DB_Session to DbSession (in CVS also)
993 added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
994 remove leading slash in error message
995 added force_unlock parameter to File_Passwd (no return on stale locks)
996 fixed adodb session AffectedRows
997 added FileFinder helpers to unify local filenames and DATA_PATH names
998 editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
1000 Revision 1.66 2004/04/29 23:25:12 rurban
1001 re-ordered locale init (as in 1.3.9)
1002 fixed loadfile with subpages, and merge/restore anyway
1003 (sf.net bug #844188)
1005 Revision 1.65 2004/04/18 01:11:52 rurban
1006 more numeric pagename fixes.
1007 fixed action=upload with merge conflict warnings.
1008 charset changed from constant to global (dynamic utf-8 switching)
1010 Revision 1.64 2004/04/06 19:48:56 rurban
1011 temp workaround for action=edit AddComment form
1013 Revision 1.63 2004/03/24 19:39:02 rurban
1014 php5 workaround code (plus some interim debugging code in XmlElement)
1015 php5 doesn't work yet with the current XmlElement class constructors,
1016 WikiUserNew does work better than php4.
1017 rewrote WikiUserNew user upgrading to ease php5 update
1018 fixed pref handling in WikiUserNew
1019 added Email Notification
1020 added simple Email verification
1021 removed emailVerify userpref subclass: just a email property
1022 changed pref binary storage layout: numarray => hash of non default values
1023 print optimize message only if really done.
1024 forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
1025 prefs should be stored in db or homepage, besides the current session.
1027 Revision 1.62 2004/03/17 18:41:05 rurban
1028 initial_content and template support for CreatePage
1030 Revision 1.61 2004/03/12 20:59:17 rurban
1031 important cookie fix by Konstantin Zadorozhny
1032 new editpage feature: JS_SEARCHREPLACE
1034 Revision 1.60 2004/02/15 21:34:37 rurban
1035 PageList enhanced and improved.
1036 fixed new WikiAdmin... plugins
1037 editpage, Theme with exp. htmlarea framework
1038 (htmlarea yet committed, this is really questionable)
1039 WikiUser... code with better session handling for prefs
1040 enhanced UserPreferences (again)
1041 RecentChanges for show_deleted: how should pages be deleted then?
1043 Revision 1.59 2003/12/07 20:35:26 carstenklapp
1044 Bugfix: Concurrent updates broken since after 1.3.4 release: Fatal
1045 error: Call to undefined function: gettransformedcontent() in
1046 /home/groups/p/ph/phpwiki/htdocs/phpwiki2/lib/editpage.php on line
1049 Revision 1.58 2003/03/10 18:25:22 dairiki
1050 Bug/typo fix. If you use the edit page to un/lock a page, it
1051 failed with: Fatal error: Call to a member function on a
1052 non-object in editpage.php on line 136
1054 Revision 1.57 2003/02/26 03:40:22 dairiki
1055 New action=create. Essentially the same as action=edit, except that if the
1056 page already exists, it falls back to action=browse.
1058 This is for use in the "question mark" links for unknown wiki words
1059 to avoid problems and confusion when following links from stale pages.
1060 (If the "unknown page" has been created in the interim, the user probably
1061 wants to view the page before editing it.)
1063 Revision 1.56 2003/02/21 18:07:14 dairiki
1064 Minor, nitpicky, currently inconsequential changes.
1066 Revision 1.55 2003/02/21 04:10:58 dairiki
1067 Fixes for new cached markup.
1068 Some minor code cleanups.
1070 Revision 1.54 2003/02/16 19:47:16 dairiki
1071 Update WikiDB timestamp when editing or deleting pages.
1073 Revision 1.53 2003/02/15 23:20:27 dairiki
1074 Redirect back to browse current version of page upon save,
1075 even when no changes were made.
1077 Revision 1.52 2003/01/03 22:22:00 carstenklapp
1078 Minor adjustments to diff block markers ("<<<<<<<"). Source reformatting.
1080 Revision 1.51 2003/01/03 02:43:26 carstenklapp
1081 New class LoadFileConflictPageEditor, for merging / comparing a loaded
1082 pgsrc file with an existing page.
1089 // c-basic-offset: 4
1090 // c-hanging-comment-ender-p: nil
1091 // indent-tabs-mode: nil