]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/editpage.php
extract toolbar code, support new tags to get rid of php inside templates
[SourceForge/phpwiki.git] / lib / editpage.php
1 <?php
2 rcs_id('$Id: editpage.php,v 1.91 2005-01-25 07:05:49 rurban Exp $');
3
4 require_once('lib/Template.php');
5
6 // USE_HTMLAREA - Support for some WYSIWYG HTML Editor
7 // Not yet enabled, since we cannot convert HTML to Wiki Markup yet.
8 // (See HtmlParser.php for the ongoing efforts)
9 // We might use a HTML PageType, which is contra wiki, but some people might prefer HTML markup.
10 // TODO: Change from constant to user preference variable (checkbox setting),
11 //       when HtmlParser is finished.
12 if (!defined('USE_HTMLAREA')) define('USE_HTMLAREA', false);
13 if (USE_HTMLAREA) require_once('lib/htmlarea.php');
14
15 class PageEditor
16 {
17     function PageEditor (&$request) {
18         $this->request = &$request;
19
20         $this->user = $request->getUser();
21         $this->page = $request->getPage();
22
23         $this->current = $this->page->getCurrentRevision(false);
24
25         // HACKish short circuit to browse on action=create
26         if ($request->getArg('action') == 'create') {
27             if (! $this->current->hasDefaultContents()) 
28                 $request->redirect(WikiURL($this->page->getName())); // noreturn
29         }
30         
31         
32         $this->meta = array('author' => $this->user->getId(),
33                             'author_id' => $this->user->getAuthenticatedId(),
34                             'mtime' => time());
35         
36         $this->tokens = array();
37         
38         $version = $request->getArg('version');
39         if ($version !== false) {
40             $this->selected = $this->page->getRevision($version);
41             $this->version = $version;
42         }
43         else {
44             $this->version = $this->current->getVersion();
45             $this->selected = $this->page->getRevision($this->version);
46         }
47
48         if ($this->_restoreState()) {
49             $this->_initialEdit = false;
50         }
51         else {
52             $this->_initializeState();
53             $this->_initialEdit = true;
54
55             // The edit request has specified some initial content from a template 
56             if (  ($template = $request->getArg('template'))
57                    and $request->_dbi->isWikiPage($template)) {
58                 $page = $request->_dbi->getPage($template);
59                 $current = $page->getCurrentRevision();
60                 $this->_content = $current->getPackedContent();
61             } elseif ($initial_content = $request->getArg('initial_content')) {
62                 $this->_content = $initial_content;
63                 $this->_redirect_to = $request->getArg('save_and_redirect_to');
64             }
65         }
66         if (!headers_sent())
67             header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
68     }
69
70     function editPage () {
71         global $WikiTheme;
72         $saveFailed = false;
73         $tokens = &$this->tokens;
74         if (isset($this->request->args['pref']['editWidth'])
75             and ($this->request->getPref('editWidth') != $this->request->args['pref']['editWidth'])) {
76             $this->request->_prefs->set('editWidth', $this->request->args['pref']['editWidth']);
77         }
78         if (isset($this->request->args['pref']['editHeight'])
79             and ($this->request->getPref('editHeight') != $this->request->args['pref']['editHeight'])) {
80             $this->request->_prefs->set('editHeight', $this->request->args['pref']['editHeight']);
81         }
82
83         if (! $this->canEdit()) {
84             if ($this->isInitialEdit())
85                 return $this->viewSource();
86             $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
87         }
88         elseif ($this->request->getArg('save_and_redirect_to') != "") {
89             if ($this->savePage()) {
90                 // noreturn
91                 $this->request->redirect(WikiURL($this->request->getArg('save_and_redirect_to')));
92                 return true;    // Page saved.
93             }
94             $saveFailed = true;
95         }
96         elseif ($this->editaction == 'save') {
97             if ($this->savePage()) {
98                 return true;    // Page saved.
99             }
100             $saveFailed = true;
101         }
102
103         if ($saveFailed and $this->isConcurrentUpdate())
104         {
105             // Get the text of the original page, and the two conflicting edits
106             // The diff3 class takes arrays as input.  So retrieve content as
107             // an array, or convert it as necesary.
108             $orig = $this->page->getRevision($this->_currentVersion);
109             // FIXME: what if _currentVersion has be deleted?
110             $orig_content = $orig->getContent();
111             $this_content = explode("\n", $this->_content);
112             $other_content = $this->current->getContent();
113             include_once("lib/diff3.php");
114             $diff = new diff3($orig_content, $this_content, $other_content);
115             $output = $diff->merged_output(_("Your version"), _("Other version"));
116             // Set the content of the textarea to the merged diff
117             // output, and update the version
118             $this->_content = implode ("\n", $output);
119             $this->_currentVersion = $this->current->getVersion();
120             $this->version = $this->_currentVersion;
121             $unresolved = $diff->ConflictingBlocks;
122             $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage($unresolved);
123         } elseif ($saveFailed) {
124             $tokens['CONCURRENT_UPDATE_MESSAGE'] = 
125                 HTML(HTML::h2(_("Some internal editing error")),
126                      HTML::p(_("Your are probably trying to edit/create an invalid version of this page.")),
127                      HTML::p(HTML::em(_("&version=-1 might help."))));
128         }
129
130         if ($this->editaction == 'edit_convert')
131             $tokens['PREVIEW_CONTENT'] = $this->getConvertedPreview();
132         if ($this->editaction == 'preview')
133             $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
134
135         // FIXME: NOT_CURRENT_MESSAGE?
136         $tokens = array_merge($tokens, $this->getFormElements());
137
138         if (ENABLE_EDIT_TOOLBAR or JS_SEARCHREPLACE) {
139             include_once("lib/EditToolbar.php");
140             $toolbar = new EditToolbar();
141             $tokens = array_merge($tokens, $toolbar->getTokens());
142         }
143
144         return $this->output('editpage', _("Edit: %s"));
145     }
146
147     function output ($template, $title_fs) {
148         global $WikiTheme;
149         $selected = &$this->selected;
150         $current = &$this->current;
151
152         if ($selected && $selected->getVersion() != $current->getVersion()) {
153             $rev = $selected;
154             $pagelink = WikiLink($selected);
155         }
156         else {
157             $rev = $current;
158             $pagelink = WikiLink($this->page);
159         }
160
161
162         $title = new FormattedText ($title_fs, $pagelink);
163         if (USE_HTMLAREA and $template == 'editpage') {
164             $WikiTheme->addMoreHeaders(Edit_HtmlArea_Head());
165             //$tokens['PAGE_SOURCE'] = Edit_HtmlArea_ConvertBefore($this->_content);
166         }
167         $template = Template($template, $this->tokens);
168         GeneratePage($template, $title, $rev);
169         return true;
170     }
171
172
173     function viewSource () {
174         assert($this->isInitialEdit());
175         assert($this->selected);
176
177         $this->tokens['PAGE_SOURCE'] = $this->_content;
178         return $this->output('viewsource', _("View Source: %s"));
179     }
180
181     function updateLock() {
182         if ((bool)$this->page->get('locked') == (bool)$this->locked)
183             return false;       // Not changed.
184
185         if (!$this->user->isAdmin()) {
186             // FIXME: some sort of message
187             return false;         // not allowed.
188         }
189
190         $this->page->set('locked', (bool)$this->locked);
191         $this->tokens['LOCK_CHANGED_MSG']
192             = $this->locked ? _("Page now locked.") : _("Page now unlocked.");
193
194         return true;            // lock changed.
195     }
196
197     function savePage () {
198         $request = &$this->request;
199
200         if ($this->isUnchanged()) {
201             // Allow admin lock/unlock even if
202             // no text changes were made.
203             if ($this->updateLock()) {
204                 $dbi = $request->getDbh();
205                 $dbi->touch();
206             }
207             // Save failed. No changes made.
208             $this->_redirectToBrowsePage();
209             // user will probably not see the rest of this...
210             include_once('lib/display.php');
211             // force browse of current version:
212             $request->setArg('version', false);
213             displayPage($request, 'nochanges');
214             return true;
215         }
216
217         if ($this->isSpam()) {
218             return false;
219             /*
220             // Save failed. No changes made.
221             $this->_redirectToBrowsePage();
222             // user will probably not see the rest of this...
223             include_once('lib/display.php');
224             // force browse of current version:
225             $request->setArg('version', false);
226             displayPage($request, 'nochanges');
227             return true;
228             */
229         }
230
231         $page = &$this->page;
232
233         // Include any meta-data from original page version which
234         // has not been explicitly updated.
235         // (Except don't propagate pgsrc_version --- moot for now,
236         //  because at present it never gets into the db...)
237         $meta = $this->selected->getMetaData();
238         unset($meta['pgsrc_version']);
239         $meta = array_merge($meta, $this->meta);
240         
241         // Save new revision
242         $this->_content = $this->getContent();
243         $newrevision = $page->save($this->_content, 
244                                    $this->version == -1 
245                                      ? -1 
246                                      : $this->_currentVersion + 1, 
247                                    // force new?
248                                    $meta);
249         if (!isa($newrevision, 'WikiDB_PageRevision')) {
250             // Save failed.  (Concurrent updates).
251             return false;
252         }
253         
254         // New contents successfully saved...
255         $this->updateLock();
256
257         // Clean out archived versions of this page.
258         include_once('lib/ArchiveCleaner.php');
259         $cleaner = new ArchiveCleaner($GLOBALS['ExpireParams']);
260         $cleaner->cleanPageRevisions($page);
261
262         /* generate notification emails done in WikiDB::save to catch all direct calls 
263           (admin plugins) */
264
265         $dbi = $request->getDbh();
266         $warnings = $dbi->GenericWarnings();
267         $dbi->touch();
268         
269         global $WikiTheme;
270         if (empty($warnings) && ! $WikiTheme->getImageURL('signature')) {
271             // Do redirect to browse page if no signature has
272             // been defined.  In this case, the user will most
273             // likely not see the rest of the HTML we generate
274             // (below).
275             $this->_redirectToBrowsePage();
276         }
277
278         // Force browse of current page version.
279         $request->setArg('version', false);
280         //$request->setArg('action', false);
281
282         $template = Template('savepage', $this->tokens);
283         $template->replace('CONTENT', $newrevision->getTransformedContent());
284         if (!empty($warnings))
285             $template->replace('WARNINGS', $warnings);
286
287         $pagelink = WikiLink($page);
288
289         GeneratePage($template, fmt("Saved: %s", $pagelink), $newrevision);
290         return true;
291     }
292
293     function isConcurrentUpdate () {
294         assert($this->current->getVersion() >= $this->_currentVersion);
295         return $this->current->getVersion() != $this->_currentVersion;
296     }
297
298     function canEdit () {
299         return !$this->page->get('locked') || $this->user->isAdmin();
300     }
301
302     function isInitialEdit () {
303         return $this->_initialEdit;
304     }
305
306     function isUnchanged () {
307         $current = &$this->current;
308
309         if ($this->meta['markup'] !=  $current->get('markup'))
310             return false;
311
312         return $this->_content == $current->getPackedContent();
313     }
314
315     /** 
316      * Handle AntiSpam here. How? http://wikiblacklist.blogspot.com/
317      * Need to check dynamically some blacklist wikipage settings 
318      * (plugin WikiAccessRestrictions) and some static blacklist.
319      * DONE: 
320      *   More then 20 new external links
321      *   content patterns by babycart (only php >= 4.3 for now)
322      * TODO:
323      *   IP blacklist 
324      *   domain blacklist
325      *   url patterns
326      */
327     function isSpam () {
328         $current = &$this->current;
329         $request = &$this->request;
330
331         $oldtext = $current->getPackedContent();
332         $newtext =& $this->_content;
333         // 1. Not more then 20 new external links
334         if ($this->numLinks($newtext) - $this->numLinks($oldtext) >= 20) {
335             // mail the admin?
336             $this->tokens['PAGE_LOCKED_MESSAGE'] = 
337                 HTML($this->getSpamMessage(),
338                      HTML::p(HTML::em(_("Too many external links."))));
339             return true;
340         }
341         // 2. external babycart (SpamAssassin) check
342         // This will probably prevent from discussing sex or viagra related topics. So beware.
343         if (ENABLE_SPAMASSASSIN) {
344             $user = $request->getUser();
345             include_once("lib/spam_babycart.php");
346             if ($babycart = check_babycart($newtext, $request->get("REMOTE_ADDR"), 
347                                            $user->getId())) {
348                 // mail the admin?
349                 if (is_array($babycart))
350                     $this->tokens['PAGE_LOCKED_MESSAGE'] = 
351                         HTML($this->getSpamMessage(),
352                              HTML::p(HTML::em(_("SpamAssassin reports: ", 
353                                                 join("\n", $babycart)))));
354                 return true;
355             }
356         }
357         return false;
358     }
359
360     /** Number of external links in the wikitext
361      */
362     function numLinks(&$text) {
363         return substr_count($text, "http://");
364     }
365
366     /** Header of the Anti Spam message 
367      */
368     function getSpamMessage () {
369         return
370             HTML(HTML::h2(_("Spam Prevention")),
371                  HTML::p(_("This page edit seems to contain spam and was therefore not saved."),
372                          HTML::br(),
373                          _("Sorry for the inconvenience.")),
374                  HTML::p(""));
375     }
376
377     function getPreview () {
378         include_once('lib/PageType.php');
379         $this->_content = $this->getContent();
380         return new TransformedText($this->page, $this->_content, $this->meta);
381     }
382
383     function getConvertedPreview () {
384         include_once('lib/PageType.php');
385         $this->_content = $this->getContent();
386         $this->meta['markup'] = 2.0;
387         $this->_content = ConvertOldMarkup($this->_content);
388         return new TransformedText($this->page, $this->_content, $this->meta);
389     }
390
391     // possibly convert HTMLAREA content back to Wiki markup
392     function getContent () {
393         if (USE_HTMLAREA) {
394             $xml_output = Edit_HtmlArea_ConvertAfter($this->_content);
395             $this->_content = join("", $xml_output->_content);
396             return $this->_content;
397         } else {
398             return $this->_content;
399         }
400     }
401
402     function getLockedMessage () {
403         return
404             HTML(HTML::h2(_("Page Locked")),
405                  HTML::p(_("This page has been locked by the administrator so your changes can not be saved.")),
406                  HTML::p(_("(Copy your changes to the clipboard. You can try editing a different page or save your text in a text editor.)")),
407                  HTML::p(_("Sorry for the inconvenience.")));
408     }
409
410     function getConflictMessage ($unresolved = false) {
411         /*
412          xgettext only knows about c/c++ line-continuation strings
413          it does not know about php's dot operator.
414          We want to translate this entire paragraph as one string, of course.
415          */
416
417         //$re_edit_link = Button('edit', _("Edit the new version"), $this->page);
418
419         if ($unresolved)
420             $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.",
421                                 "<<<<<<< ". _("Your version"),
422                                 ">>>>>>> ". _("Other version")));
423         else
424             $message = HTML::p(_("Please check it through before saving."));
425
426
427
428         /*$steps = HTML::ol(HTML::li(_("Copy your changes to the clipboard or to another temporary place (e.g. text editor).")),
429           HTML::li(fmt("%s of the page. You should now see the most current version of the page. Your changes are no longer there.",
430                        $re_edit_link)),
431           HTML::li(_("Make changes to the file again. Paste your additions from the clipboard (or text editor).")),
432           HTML::li(_("Save your updated changes.")));
433         */
434         return
435             HTML(HTML::h2(_("Conflicting Edits!")),
436                  HTML::p(_("In the time since you started editing this page, another user has saved a new version of it.")),
437                  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.")),
438                  $message);
439     }
440
441
442     function getTextArea () {
443         $request = &$this->request;
444
445         // wrap=virtual is not HTML4, but without it NS4 doesn't wrap
446         // long lines
447         $readonly = ! $this->canEdit(); // || $this->isConcurrentUpdate();
448         if (USE_HTMLAREA) {
449             $html = $this->getPreview();
450             $this->_wikicontent = $this->_content;
451             $this->_content = $html->asXML();
452         }
453
454         /** <textarea wrap="virtual"> is not valid xhtml but Netscape 4 requires it
455          * to wrap long lines.
456          */
457         $textarea = HTML::textarea(array('class' => 'wikiedit',
458                                          'name' => 'edit[content]',
459                                          'id'   => 'edit[content]',
460                                          'rows' => $request->getPref('editHeight'),
461                                          'cols' => $request->getPref('editWidth'),
462                                          'readonly' => (bool) $readonly),
463                                    $this->_content);
464         if (isBrowserNS4())
465             $textarea->setAttr('wrap', 'virtual');
466         if (USE_HTMLAREA)
467             return Edit_HtmlArea_Textarea($textarea,$this->_wikicontent,'edit[content]');
468         else
469             return $textarea;
470     }
471
472     function getFormElements () {
473         global $WikiTheme;
474         $request = &$this->request;
475         $page = &$this->page;
476
477         $h = array('action'   => 'edit',
478                    'pagename' => $page->getName(),
479                    'version'  => $this->version,
480                    'edit[pagetype]' => $this->meta['pagetype'],
481                    'edit[current_version]' => $this->_currentVersion);
482
483         $el['HIDDEN_INPUTS'] = HiddenInputs($h);
484         $el['EDIT_TEXTAREA'] = $this->getTextArea();
485         $el['SUMMARY_INPUT']
486             = HTML::input(array('type'  => 'text',
487                                 'class' => 'wikitext',
488                                 'id' => 'edit[summary]',
489                                 'name'  => 'edit[summary]',
490                                 'size'  => 50,
491                                 'maxlength' => 256,
492                                 'value' => $this->meta['summary']));
493         $el['MINOR_EDIT_CB']
494             = HTML::input(array('type' => 'checkbox',
495                                 'name'  => 'edit[minor_edit]',
496                                 'id' => 'edit[minor_edit]',
497                                 'checked' => (bool) $this->meta['is_minor_edit']));
498         $el['OLD_MARKUP_CB']
499             = HTML::input(array('type' => 'checkbox',
500                                 'name' => 'edit[markup]',
501                                 'value' => 'old',
502                                 'checked' => $this->meta['markup'] < 2.0,
503                                 'id' => 'useOldMarkup',
504                                 'onclick' => 'showOldMarkupRules(this.checked)'));
505         $el['OLD_MARKUP_CONVERT'] = ($this->meta['markup'] < 2.0) 
506             ? Button('submit:edit[edit_convert]', _("Convert"), 'wikiaction') : '';
507         $el['LOCKED_CB']
508             = HTML::input(array('type' => 'checkbox',
509                                 'name' => 'edit[locked]',
510                                 'id'   => 'edit[locked]',
511                                 'disabled' => (bool) !$this->user->isadmin(),
512                                 'checked'  => (bool) $this->locked));
513
514         $el['PREVIEW_B'] = Button('submit:edit[preview]', _("Preview"),
515                                   'wikiaction');
516
517         //if (!$this->isConcurrentUpdate() && $this->canEdit())
518         $el['SAVE_B'] = Button('submit:edit[save]', _("Save"), 'wikiaction');
519
520         $el['IS_CURRENT'] = $this->version == $this->current->getVersion();
521
522         $el['WIDTH_PREF'] = HTML::input(array('type' => 'text',
523                                     'size' => 3,
524                                     'maxlength' => 4,
525                                     'class' => "numeric",
526                                     'name' => 'pref[editWidth]',
527                                     'id'   => 'pref[editWidth]',
528                                     'value' => $request->getPref('editWidth'),
529                                     'onchange' => 'this.form.submit();'));
530         $el['HEIGHT_PREF'] = HTML::input(array('type' => 'text',
531                                      'size' => 3,
532                                      'maxlength' => 4,
533                                      'class' => "numeric",
534                                      'name' => 'pref[editHeight]',
535                                      'id'   => 'pref[editHeight]',
536                                      'value' => $request->getPref('editHeight'),
537                                      'onchange' => 'this.form.submit();'));
538         $el['SEP'] = $WikiTheme->getButtonSeparator();
539         $el['AUTHOR_MESSAGE'] = fmt("Author will be logged as %s.", HTML::em($this->user->getId()));
540         
541         return $el;
542     }
543
544     function _redirectToBrowsePage() {
545         $this->request->redirect(WikiURL($this->page, false, 'absolute_url'));
546     }
547
548     function _restoreState () {
549         $request = &$this->request;
550
551         $posted = $request->getArg('edit');
552         $request->setArg('edit', false);
553
554         if (!$posted || !$request->isPost()
555             || $request->getArg('action') != 'edit')
556             return false;
557
558         if (!isset($posted['content']) || !is_string($posted['content']))
559             return false;
560         $this->_content = preg_replace('/[ \t\r]+\n/', "\n",
561                                         rtrim($posted['content']));
562         $this->_content = $this->getContent();
563
564         $this->_currentVersion = (int) $posted['current_version'];
565
566         if ($this->_currentVersion < 0)
567             return false;
568         if ($this->_currentVersion > $this->current->getVersion())
569             return false;       // FIXME: some kind of warning?
570
571         $is_old_markup = !empty($posted['markup']) && $posted['markup'] == 'old';
572         $meta['markup'] = $is_old_markup ? false : 2.0;
573         $meta['summary'] = trim(substr($posted['summary'], 0, 256));
574         $meta['is_minor_edit'] = !empty($posted['minor_edit']);
575         $meta['pagetype'] = !empty($posted['pagetype']) ? $posted['pagetype'] : false;
576         $this->meta = array_merge($this->meta, $meta);
577         $this->locked = !empty($posted['locked']);
578
579         if (!empty($posted['preview']))
580             $this->editaction = 'preview';
581         elseif (!empty($posted['save']))
582             $this->editaction = 'save';
583         elseif (!empty($posted['edit_convert']))
584             $this->editaction = 'edit_convert';
585         else
586             $this->editaction = 'edit';
587
588         return true;
589     }
590
591     function _initializeState () {
592         $request = &$this->request;
593         $current = &$this->current;
594         $selected = &$this->selected;
595         $user = &$this->user;
596
597         if (!$selected)
598             NoSuchRevision($request, $this->page, $this->version); // noreturn
599
600         $this->_currentVersion = $current->getVersion();
601         $this->_content = $selected->getPackedContent();
602
603         $this->locked = $this->page->get('locked');
604
605         // If author same as previous author, default minor_edit to on.
606         $age = $this->meta['mtime'] - $current->get('mtime');
607         $this->meta['is_minor_edit'] = ( $age < MINOR_EDIT_TIMEOUT
608                                          && $current->get('author') == $user->getId()
609                                          );
610
611         // Default for new pages is new-style markup.
612         if ($selected->hasDefaultContents())
613             $is_new_markup = true;
614         else
615             $is_new_markup = $selected->get('markup') >= 2.0;
616
617         $this->meta['markup'] = $is_new_markup ? 2.0: false;
618         $this->meta['pagetype'] = $selected->get('pagetype');
619         if ($this->meta['pagetype'] == 'wikiblog')
620             $this->meta['summary'] = $selected->get('summary'); // keep blog title
621         else
622             $this->meta['summary'] = '';
623         $this->editaction = 'edit';
624     }
625 }
626
627 class LoadFileConflictPageEditor
628 extends PageEditor
629 {
630     function editPage ($saveFailed = true) {
631         $tokens = &$this->tokens;
632
633         if (!$this->canEdit()) {
634             if ($this->isInitialEdit())
635                 return $this->viewSource();
636             $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
637         }
638         elseif ($this->editaction == 'save') {
639             if ($this->savePage())
640                 return true;    // Page saved.
641             $saveFailed = true;
642         }
643
644         if ($saveFailed || $this->isConcurrentUpdate())
645         {
646             // Get the text of the original page, and the two conflicting edits
647             // The diff class takes arrays as input.  So retrieve content as
648             // an array, or convert it as necesary.
649             $orig = $this->page->getRevision($this->_currentVersion);
650             $this_content = explode("\n", $this->_content);
651             $other_content = $this->current->getContent();
652             include_once("lib/diff.php");
653             $diff2 = new Diff($other_content, $this_content);
654             $context_lines = max(4, count($other_content) + 1,
655                                  count($this_content) + 1);
656             $fmt = new BlockDiffFormatter($context_lines);
657
658             $this->_content = $fmt->format($diff2);
659             // FIXME: integrate this into class BlockDiffFormatter
660             $this->_content = str_replace(">>>>>>>\n<<<<<<<\n", "=======\n",
661                                           $this->_content);
662             $this->_content = str_replace("<<<<<<<\n>>>>>>>\n", "=======\n",
663                                           $this->_content);
664
665             $this->_currentVersion = $this->current->getVersion();
666             $this->version = $this->_currentVersion;
667             $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage();
668         }
669
670         if ($this->editaction == 'edit_convert')
671             $tokens['PREVIEW_CONTENT'] = $this->getConvertedPreview();
672         if ($this->editaction == 'preview')
673             $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
674
675         // FIXME: NOT_CURRENT_MESSAGE?
676         $tokens = array_merge($tokens, $this->getFormElements());
677
678         return $this->output('editpage', _("Merge and Edit: %s"));
679         // FIXME: this doesn't display
680     }
681
682     function output ($template, $title_fs) {
683         $selected = &$this->selected;
684         $current = &$this->current;
685
686         if ($selected && $selected->getVersion() != $current->getVersion()) {
687             $rev = $selected;
688             $pagelink = WikiLink($selected);
689         }
690         else {
691             $rev = $current;
692             $pagelink = WikiLink($this->page);
693         }
694
695         $title = new FormattedText ($title_fs, $pagelink);
696         $template = Template($template, $this->tokens);
697
698         //GeneratePage($template, $title, $rev);
699         PrintXML($template);
700         return true;
701     }
702     function getConflictMessage () {
703         $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.",
704                                     "<<<<<<<",
705                                     "======="),
706                                 HTML::p(_("Please check it through before saving."))));
707         return $message;
708     }
709 }
710
711 /**
712  $Log: not supported by cvs2svn $
713  Revision 1.90  2005/01/22 12:46:15  rurban
714  fix oldmakrup button label
715  update pref[edit*] settings
716
717  Revision 1.89  2005/01/21 14:07:49  rurban
718  reformatting
719
720  Revision 1.88  2004/12/17 16:39:03  rurban
721  minor reformatting
722
723  Revision 1.87  2004/12/16 18:28:05  rurban
724  keep wikiblog summary = page title
725
726  Revision 1.86  2004/12/11 14:50:15  rurban
727  new edit_convert button, to get rid of old markup eventually
728
729  Revision 1.85  2004/12/06 19:49:56  rurban
730  enable action=remove which is undoable and seeable in RecentChanges: ADODB ony for now.
731  renamed delete_page to purge_page.
732  enable action=edit&version=-1 to force creation of a new version.
733  added BABYCART_PATH config
734  fixed magiqc in adodb.inc.php
735  and some more docs
736
737  Revision 1.84  2004/12/04 12:58:26  rurban
738  enable babycart Blog::SpamAssassin module on ENABLE_SPAMASSASSIN=true
739  (currently only for php >= 4.3.0)
740
741  Revision 1.83  2004/12/04 11:55:39  rurban
742  First simple AntiSpam prevention:
743    No more than 20 new http:// links allowed
744
745  Revision 1.82  2004/11/30 22:21:56  rurban
746  changed gif to optimized (pngout) png
747
748  Revision 1.81  2004/11/29 17:57:27  rurban
749  translated pulldown buttons
750
751  Revision 1.80  2004/11/25 17:20:51  rurban
752  and again a couple of more native db args: backlinks
753
754  Revision 1.79  2004/11/21 11:59:20  rurban
755  remove final \n to be ob_cache independent
756
757  Revision 1.78  2004/11/16 17:57:45  rurban
758  fix search&replace button
759  use new addTagButton machinery
760  new showPulldown for categories, TODO: in a seperate request
761
762  Revision 1.77  2004/11/15 15:52:35  rurban
763  improve js stability
764
765  Revision 1.76  2004/11/15 15:37:34  rurban
766  fix JS_SEARCHREPLACE
767    don't use document.write for replace, otherwise self.opener is not defined.
768
769  Revision 1.75  2004/09/16 08:00:52  rurban
770  just some comments
771
772  Revision 1.74  2004/07/03 07:36:28  rurban
773  do not get unneccessary content
774
775  Revision 1.73  2004/06/16 21:23:44  rurban
776  fixed non-object fatal #215
777
778  Revision 1.72  2004/06/14 11:31:37  rurban
779  renamed global $Theme to $WikiTheme (gforge nameclash)
780  inherit PageList default options from PageList
781    default sortby=pagename
782  use options in PageList_Selectable (limit, sortby, ...)
783  added action revert, with button at action=diff
784  added option regex to WikiAdminSearchReplace
785
786  Revision 1.71  2004/06/03 18:06:29  rurban
787  fix file locking issues (only needed on write)
788  fixed immediate LANG and THEME in-session updates if not stored in prefs
789  advanced editpage toolbars (search & replace broken)
790
791  Revision 1.70  2004/06/02 20:47:47  rurban
792  dont use the wikiaction class
793
794  Revision 1.69  2004/06/02 10:17:56  rurban
795  integrated search/replace into toolbar
796  added save+preview buttons
797
798  Revision 1.68  2004/06/01 15:28:00  rurban
799  AdminUser only ADMIN_USER not member of Administrators
800  some RateIt improvements by dfrankow
801  edit_toolbar buttons
802
803  Revision _1.6  2004/05/26 15:48:00  syilek
804  fixed problem with creating page with slashes from one true page
805
806  Revision _1.5  2004/05/25 16:51:53  syilek
807  added ability to create a page from the category page and not have to edit it
808
809  Revision 1.67  2004/05/27 17:49:06  rurban
810  renamed DB_Session to DbSession (in CVS also)
811  added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
812  remove leading slash in error message
813  added force_unlock parameter to File_Passwd (no return on stale locks)
814  fixed adodb session AffectedRows
815  added FileFinder helpers to unify local filenames and DATA_PATH names
816  editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
817
818  Revision 1.66  2004/04/29 23:25:12  rurban
819  re-ordered locale init (as in 1.3.9)
820  fixed loadfile with subpages, and merge/restore anyway
821    (sf.net bug #844188)
822
823  Revision 1.65  2004/04/18 01:11:52  rurban
824  more numeric pagename fixes.
825  fixed action=upload with merge conflict warnings.
826  charset changed from constant to global (dynamic utf-8 switching)
827
828  Revision 1.64  2004/04/06 19:48:56  rurban
829  temp workaround for action=edit AddComment form
830
831  Revision 1.63  2004/03/24 19:39:02  rurban
832  php5 workaround code (plus some interim debugging code in XmlElement)
833    php5 doesn't work yet with the current XmlElement class constructors,
834    WikiUserNew does work better than php4.
835  rewrote WikiUserNew user upgrading to ease php5 update
836  fixed pref handling in WikiUserNew
837  added Email Notification
838  added simple Email verification
839  removed emailVerify userpref subclass: just a email property
840  changed pref binary storage layout: numarray => hash of non default values
841  print optimize message only if really done.
842  forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
843    prefs should be stored in db or homepage, besides the current session.
844
845  Revision 1.62  2004/03/17 18:41:05  rurban
846  initial_content and template support for CreatePage
847
848  Revision 1.61  2004/03/12 20:59:17  rurban
849  important cookie fix by Konstantin Zadorozhny
850  new editpage feature: JS_SEARCHREPLACE
851
852  Revision 1.60  2004/02/15 21:34:37  rurban
853  PageList enhanced and improved.
854  fixed new WikiAdmin... plugins
855  editpage, Theme with exp. htmlarea framework
856    (htmlarea yet committed, this is really questionable)
857  WikiUser... code with better session handling for prefs
858  enhanced UserPreferences (again)
859  RecentChanges for show_deleted: how should pages be deleted then?
860
861  Revision 1.59  2003/12/07 20:35:26  carstenklapp
862  Bugfix: Concurrent updates broken since after 1.3.4 release: Fatal
863  error: Call to undefined function: gettransformedcontent() in
864  /home/groups/p/ph/phpwiki/htdocs/phpwiki2/lib/editpage.php on line
865  205.
866
867  Revision 1.58  2003/03/10 18:25:22  dairiki
868  Bug/typo fix.  If you use the edit page to un/lock a page, it
869  failed with: Fatal error: Call to a member function on a
870  non-object in editpage.php on line 136
871
872  Revision 1.57  2003/02/26 03:40:22  dairiki
873  New action=create.  Essentially the same as action=edit, except that if the
874  page already exists, it falls back to action=browse.
875
876  This is for use in the "question mark" links for unknown wiki words
877  to avoid problems and confusion when following links from stale pages.
878  (If the "unknown page" has been created in the interim, the user probably
879  wants to view the page before editing it.)
880
881  Revision 1.56  2003/02/21 18:07:14  dairiki
882  Minor, nitpicky, currently inconsequential changes.
883
884  Revision 1.55  2003/02/21 04:10:58  dairiki
885  Fixes for new cached markup.
886  Some minor code cleanups.
887
888  Revision 1.54  2003/02/16 19:47:16  dairiki
889  Update WikiDB timestamp when editing or deleting pages.
890
891  Revision 1.53  2003/02/15 23:20:27  dairiki
892  Redirect back to browse current version of page upon save,
893  even when no changes were made.
894
895  Revision 1.52  2003/01/03 22:22:00  carstenklapp
896  Minor adjustments to diff block markers ("<<<<<<<"). Source reformatting.
897
898  Revision 1.51  2003/01/03 02:43:26  carstenklapp
899  New class LoadFileConflictPageEditor, for merging / comparing a loaded
900  pgsrc file with an existing page.
901
902  */
903
904 // Local Variables:
905 // mode: php
906 // tab-width: 8
907 // c-basic-offset: 4
908 // c-hanging-comment-ender-p: nil
909 // indent-tabs-mode: nil
910 // End:
911 ?>