]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/editpage.php
more numeric pagename fixes.
[SourceForge/phpwiki.git] / lib / editpage.php
1 <?php
2 rcs_id('$Id: editpage.php,v 1.65 2004-04-18 01:11:52 rurban Exp $');
3
4 require_once('lib/Template.php');
5
6 // Not yet enabled, since we cannot convert HTML to Wiki Markup yet.
7 // We might use a HTML PageType, which is contra wiki, but some people might prefer HTML markup.
8 // Todo: change from constant to user preference variable. (or checkbox setting)
9 if (!defined('USE_HTMLAREA')) define('USE_HTMLAREA',false);
10 if (USE_HTMLAREA) require_once('lib/htmlarea.php');
11
12 class PageEditor
13 {
14     function PageEditor (&$request) {
15         $this->request = &$request;
16
17         $this->user = $request->getUser();
18         $this->page = $request->getPage();
19
20         $this->current = $this->page->getCurrentRevision();
21
22         // HACKish short circuit to browse on action=create
23         if ($request->getArg('action') == 'create') {
24             if (! $this->current->hasDefaultContents()) 
25                 $request->redirect(WikiURL($this->page->getName())); // noreturn
26         }
27         
28         
29         $this->meta = array('author' => $this->user->getId(),
30                             'author_id' => $this->user->getAuthenticatedId(),
31                             'mtime' => time());
32         
33         $this->tokens = array();
34         
35         $version = $request->getArg('version');
36         if ($version !== false) {
37             $this->selected = $this->page->getRevision($version);
38             $this->version = $version;
39         }
40         else {
41             $this->selected = $this->current;
42             $this->version = $this->current->getVersion();
43         }
44
45         if ($this->_restoreState()) {
46             $this->_initialEdit = false;
47         }
48         else {
49             $this->_initializeState();
50             $this->_initialEdit = true;
51
52             // The edit request has specified some initial content from a template 
53             if (  ($template = $request->getArg('template')) and 
54                   $request->_dbi->isWikiPage($template)) {
55                 $page = $request->_dbi->getPage($template);
56                 $current = $page->getCurrentRevision();
57                 $this->_content = $current->getPackedContent();
58             } elseif ($initial_content = $request->getArg('initial_content')) {
59                 $this->_content = $initial_content;
60             }
61         }
62         header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
63     }
64
65     function editPage () {
66         $saveFailed = false;
67         $tokens = &$this->tokens;
68
69         if (! $this->canEdit()) {
70             if ($this->isInitialEdit())
71                 return $this->viewSource();
72             $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
73         }
74         elseif ($this->editaction == 'save') {
75             if ($this->savePage())
76                 return true;    // Page saved.
77             $saveFailed = true;
78         }
79
80         if ($saveFailed || $this->isConcurrentUpdate())
81         {
82             // Get the text of the original page, and the two conflicting edits
83             // The diff3 class takes arrays as input.  So retrieve content as
84             // an array, or convert it as necesary.
85             $orig = $this->page->getRevision($this->_currentVersion);
86             // FIXME: what if _currentVersion has be deleted?
87             $orig_content = $orig->getContent();
88             $this_content = explode("\n", $this->_content);
89             $other_content = $this->current->getContent();
90             include_once("lib/diff3.php");
91             $diff = new diff3($orig_content, $this_content, $other_content);
92             $output = $diff->merged_output(_("Your version"), _("Other version"));
93             // Set the content of the textarea to the merged diff
94             // output, and update the version
95             $this->_content = implode ("\n", $output);
96             $this->_currentVersion = $this->current->getVersion();
97             $this->version = $this->_currentVersion;
98             $unresolved = $diff->ConflictingBlocks;
99             $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage($unresolved);
100         }
101
102         if ($this->editaction == 'preview')
103             $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
104
105         // FIXME: NOT_CURRENT_MESSAGE?
106
107         $tokens = array_merge($tokens, $this->getFormElements());
108
109         if (defined('JS_SEARCHREPLACE') and JS_SEARCHREPLACE) {
110             $tokens['JS_SEARCHREPLACE'] = 1;
111             $GLOBALS['Theme']->addMoreHeaders(Javascript("
112 var wart=0, d, f, x='', replacewin, pretxt=new Array(), pretxt_anzahl=0;
113 var fag='<font face=\"arial,helvetica,sans-serif\" size=\"-1\">', fr='<font color=\"#cc0000\">', spn='<span class=\"grey\">';
114
115 function define_f() {
116    f=document.getElementById('editpage');
117    f.editarea=document.getElementById('edit[content]');
118    if(f.rck.style) f.rck.style.color='#ececec';
119 }
120
121 function replace() {
122    replacewin=window.open('','','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes,copyhistory=no,height=90,width=450');
123    replacewin.window.document.write('<html><head><title>"._("Search & Replace")."</title><style type=\"text/css\"><'+'!'+'-- input.btt {font-family:Tahoma,Verdana,Geneva,sans-serif;font-size:10pt} --'+'></style></head><body bgcolor=\"#dddddd\" onload=\"if(document.forms[0].ein.focus) document.forms[0].ein.focus()\"><form><center><table><tr><td align=\"right\">'+fag+'"._("Search").":</font></td><td align=\"left\"><input type=\"text\" name=\"ein\" size=\"50\" maxlength=\"500\"></td></tr><tr><td align=\"right\">'+fag+' "._("Replace with").":</font></td><td align=\"left\"><input type=\"text\" name=\"aus\" size=\"50\" maxlength=\"500\"></td></tr><tr><td colspan=\"2\" align=\"center\"><input class=\"btt\" type=\"button\" value=\" "._("OK")." \" onclick=\"self.opener.do_replace()\">&nbsp;&nbsp;&nbsp;<input class=\"btt\" type=\"button\" value=\""._("Close")."\" onclick=\"self.close()\"></td></tr></table></center></form></body></html>');
124    replacewin.window.document.close();
125 }
126
127 function do_replace() {
128    var txt=pretxt[pretxt_anzahl]=f.editarea.value, ein=new RegExp(replacewin.document.forms[0].ein.value,'g'), aus=replacewin.document.forms[0].aus.value;
129    if(ein==''||ein==null) {
130       replacewin.window.document.forms[0].ein.focus();
131       return;
132    }
133    var z_repl=txt.match(ein)? txt.match(ein).length : 0;
134    txt=txt.replace(ein,aus);
135    ein=ein.toString().substring(1,ein.toString().length-2);
136    result(z_repl, 'Substring \"'+ein+'\" found '+z_repl+' times. Replace with \"'+aus+'\"?', txt, 'String \"'+ein+'\" not found.');
137    replacewin.window.focus();
138    replacewin.window.document.forms[0].ein.focus();
139 }
140 function result(zahl,frage,txt,alert_txt) {
141    if(wart!=0&&wart.window) {
142       wart.window.close();
143       wart=0;
144    }
145    if(zahl>0) {
146       if(window.confirm(frage)==true) {
147          f.editarea.value=txt;
148          pretxt_anzahl++;
149          if(f.rck.style) f.rck.style.color='#000000';
150          f.rck.value='"._("Undo")."';
151       }
152    } else alert(alert_txt);
153 }
154 function rueck() {
155    if(pretxt_anzahl==0) return;
156    else if(pretxt_anzahl>0) {
157       f.editarea.value=pretxt[pretxt_anzahl-1];
158       pretxt[pretxt_anzahl]=null;
159       pretxt_anzahl--;
160       if(pretxt_anzahl==0) {
161          alert('Operation undone.');
162          if(f.rck.style) f.rck.style.color='#ececec';
163          f.rck.value='("._("Undo").")';
164          if(f.rck.blur) f.rck.blur();
165       }
166    }
167 }
168 function speich() {
169    pretxt[pretxt_anzahl]=f.editarea.value;
170    pretxt_anzahl++;
171    if(f.rck.style) f.rck.style.color='#000000';
172    f.rck.value='"._("Undo")."';
173 }
174 "));
175             $GLOBALS['Theme']->addMoreAttr('body'," onload='define_f()'");
176         }
177
178         return $this->output('editpage', _("Edit: %s"));
179     }
180
181     function output ($template, $title_fs) {
182         global $Theme;
183         $selected = &$this->selected;
184         $current = &$this->current;
185
186         if ($selected && $selected->getVersion() != $current->getVersion()) {
187             $rev = $selected;
188             $pagelink = WikiLink($selected);
189         }
190         else {
191             $rev = $current;
192             $pagelink = WikiLink($this->page);
193         }
194
195
196         $title = new FormattedText ($title_fs, $pagelink);
197         if ($template == 'editpage' and USE_HTMLAREA) {
198             $Theme->addMoreHeaders(Edit_HtmlArea_Head());
199             //$tokens['PAGE_SOURCE'] = Edit_HtmlArea_ConvertBefore($this->_content);
200         }
201         $template = Template($template, $this->tokens);
202         GeneratePage($template, $title, $rev);
203         return true;
204     }
205
206
207     function viewSource () {
208         assert($this->isInitialEdit());
209         assert($this->selected);
210
211         $this->tokens['PAGE_SOURCE'] = $this->_content;
212         return $this->output('viewsource', _("View Source: %s"));
213     }
214
215     function updateLock() {
216         if ((bool)$this->page->get('locked') == (bool)$this->locked)
217             return false;       // Not changed.
218
219         if (!$this->user->isAdmin()) {
220             // FIXME: some sort of message
221             return false;         // not allowed.
222         }
223
224         $this->page->set('locked', (bool)$this->locked);
225         $this->tokens['LOCK_CHANGED_MSG']
226             = $this->locked ? _("Page now locked.") : _("Page now unlocked.");
227
228         return true;            // lock changed.
229     }
230
231     function savePage () {
232         $request = &$this->request;
233
234         if ($this->isUnchanged()) {
235             // Allow admin lock/unlock even if
236             // no text changes were made.
237             if ($this->updateLock()) {
238                 $dbi = $request->getDbh();
239                 $dbi->touch();
240             }
241             // Save failed. No changes made.
242             $this->_redirectToBrowsePage();
243             // user will probably not see the rest of this...
244             include_once('lib/display.php');
245             // force browse of current version:
246             $request->setArg('version', false);
247             displayPage($request, 'nochanges');
248             return true;
249         }
250
251         $page = &$this->page;
252
253         // Include any meta-data from original page version which
254         // has not been explicitly updated.
255         // (Except don't propagate pgsrc_version --- moot for now,
256         //  because at present it never gets into the db...)
257         $meta = $this->selected->getMetaData();
258         unset($meta['pgsrc_version']);
259         $meta = array_merge($meta, $this->meta);
260         
261         // Save new revision
262         $this->_content = $this->getContent();
263         $newrevision = $page->save($this->_content, $this->_currentVersion + 1, $meta);
264         if (!isa($newrevision, 'wikidb_pagerevision')) {
265             // Save failed.  (Concurrent updates).
266             return false;
267         }
268         
269         // New contents successfully saved...
270         $this->updateLock();
271
272         // Clean out archived versions of this page.
273         include_once('lib/ArchiveCleaner.php');
274         $cleaner = new ArchiveCleaner($GLOBALS['ExpireParams']);
275         $cleaner->cleanPageRevisions($page);
276
277         /* generate notification emails done in WikiDB::save to catch all direct calls 
278           (admin plugins) */
279
280         $dbi = $request->getDbh();
281         $warnings = $dbi->GenericWarnings();
282         $dbi->touch();
283         
284         global $Theme;
285         if (empty($warnings) && ! $Theme->getImageURL('signature')) {
286             // Do redirect to browse page if no signature has
287             // been defined.  In this case, the user will most
288             // likely not see the rest of the HTML we generate
289             // (below).
290             $this->_redirectToBrowsePage();
291         }
292
293         // Force browse of current page version.
294         $request->setArg('version', false);
295         //$request->setArg('action', false);
296
297         $template = Template('savepage', $this->tokens);
298         $template->replace('CONTENT', $newrevision->getTransformedContent());
299         if (!empty($warnings))
300             $template->replace('WARNINGS', $warnings);
301
302         $pagelink = WikiLink($page);
303
304         GeneratePage($template, fmt("Saved: %s", $pagelink), $newrevision);
305         return true;
306     }
307
308     function isConcurrentUpdate () {
309         assert($this->current->getVersion() >= $this->_currentVersion);
310         return $this->current->getVersion() != $this->_currentVersion;
311     }
312
313     function canEdit () {
314         return !$this->page->get('locked') || $this->user->isAdmin();
315     }
316
317     function isInitialEdit () {
318         return $this->_initialEdit;
319     }
320
321     function isUnchanged () {
322         $current = &$this->current;
323
324         if ($this->meta['markup'] !=  $current->get('markup'))
325             return false;
326
327         return $this->_content == $current->getPackedContent();
328     }
329
330     function getPreview () {
331         include_once('lib/PageType.php');
332         $this->_content = $this->getContent();
333         return new TransformedText($this->page, $this->_content, $this->meta);
334     }
335
336     // possibly convert HTMLAREA content back to Wiki markup
337     function getContent () {
338         if (USE_HTMLAREA) {
339             $xml_output = Edit_HtmlArea_ConvertAfter($this->_content);
340             $this->_content = join("",$xml_output->_content);
341             return $this->_content;
342         } else {
343             return $this->_content;
344         }
345     }
346
347     function getLockedMessage () {
348         return
349             HTML(HTML::h2(_("Page Locked")),
350                  HTML::p(_("This page has been locked by the administrator so your changes can not be saved.")),
351                  HTML::p(_("(Copy your changes to the clipboard. You can try editing a different page or save your text in a text editor.)")),
352                  HTML::p(_("Sorry for the inconvenience.")));
353     }
354
355     function getConflictMessage ($unresolved = false) {
356         /*
357          xgettext only knows about c/c++ line-continuation strings
358          it does not know about php's dot operator.
359          We want to translate this entire paragraph as one string, of course.
360          */
361
362         //$re_edit_link = Button('edit', _("Edit the new version"), $this->page);
363
364         if ($unresolved)
365             $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.",
366                                 "<<<<<<< ". _("Your version"),
367                                 ">>>>>>> ". _("Other version")));
368         else
369             $message = HTML::p(_("Please check it through before saving."));
370
371
372
373         /*$steps = HTML::ol(HTML::li(_("Copy your changes to the clipboard or to another temporary place (e.g. text editor).")),
374           HTML::li(fmt("%s of the page. You should now see the most current version of the page. Your changes are no longer there.",
375                        $re_edit_link)),
376           HTML::li(_("Make changes to the file again. Paste your additions from the clipboard (or text editor).")),
377           HTML::li(_("Save your updated changes.")));
378         */
379         return
380             HTML(HTML::h2(_("Conflicting Edits!")),
381                  HTML::p(_("In the time since you started editing this page, another user has saved a new version of it.")),
382                  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.")),
383                  $message);
384     }
385
386
387     function getTextArea () {
388         $request = &$this->request;
389
390         // wrap=virtual is not HTML4, but without it NS4 doesn't wrap
391         // long lines
392         $readonly = ! $this->canEdit(); // || $this->isConcurrentUpdate();
393         if (USE_HTMLAREA) {
394             $html = $this->getPreview();
395             $this->_wikicontent = $this->_content;
396             $this->_content = $html->asXML();
397         }
398         $textarea = HTML::textarea(array('class' => 'wikiedit',
399                                          'name' => 'edit[content]',
400                                          'id'   => 'edit[content]',
401                                          'rows' => $request->getPref('editHeight'),
402                                          'cols' => $request->getPref('editWidth'),
403                                          'readonly' => (bool) $readonly,
404                                          'wrap' => 'virtual'),
405                                    $this->_content);
406         if (USE_HTMLAREA)
407             return Edit_HtmlArea_Textarea($textarea,$this->_wikicontent,'edit[content]');
408         else
409             return $textarea;
410     }
411
412     function getFormElements () {
413         $request = &$this->request;
414         $page = &$this->page;
415
416
417         $h = array('action'   => 'edit',
418                    'pagename' => $page->getName(),
419                    'version'  => $this->version,
420                    'edit[pagetype]' => $this->meta['pagetype'],
421                    'edit[current_version]' => $this->_currentVersion);
422
423         $el['HIDDEN_INPUTS'] = HiddenInputs($h);
424
425
426         $el['EDIT_TEXTAREA'] = $this->getTextArea();
427
428         $el['SUMMARY_INPUT']
429             = HTML::input(array('type'  => 'text',
430                                 'class' => 'wikitext',
431                                 'name'  => 'edit[summary]',
432                                 'size'  => 50,
433                                 'maxlength' => 256,
434                                 'value' => $this->meta['summary']));
435         $el['MINOR_EDIT_CB']
436             = HTML::input(array('type' => 'checkbox',
437                                 'name'  => 'edit[minor_edit]',
438                                 'checked' => (bool) $this->meta['is_minor_edit']));
439         $el['OLD_MARKUP_CB']
440             = HTML::input(array('type' => 'checkbox',
441                                 'name' => 'edit[markup]',
442                                 'value' => 'old',
443                                 'checked' => $this->meta['markup'] < 2.0,
444                                 'id' => 'useOldMarkup',
445                                 'onclick' => 'showOldMarkupRules(this.checked)'));
446
447         $el['LOCKED_CB']
448             = HTML::input(array('type' => 'checkbox',
449                                 'name' => 'edit[locked]',
450                                 'disabled' => (bool) !$this->user->isadmin(),
451                                 'checked'  => (bool) $this->locked));
452
453         $el['PREVIEW_B'] = Button('submit:edit[preview]', _("Preview"),
454                                   'wikiaction');
455
456         //if (!$this->isConcurrentUpdate() && $this->canEdit())
457         $el['SAVE_B'] = Button('submit:edit[save]', _("Save"), 'wikiaction');
458
459         $el['IS_CURRENT'] = $this->version == $this->current->getVersion();
460
461         return $el;
462     }
463
464     function _redirectToBrowsePage() {
465         $this->request->redirect(WikiURL($this->page, false, 'absolute_url'));
466     }
467     
468
469     function _restoreState () {
470         $request = &$this->request;
471
472         $posted = $request->getArg('edit');
473         $request->setArg('edit', false);
474
475         if (!$posted || !$request->isPost()
476             || $request->getArg('action') != 'edit')
477             return false;
478
479         if (!isset($posted['content']) || !is_string($posted['content']))
480             return false;
481         $this->_content = preg_replace('/[ \t\r]+\n/', "\n",
482                                         rtrim($posted['content']));
483         $this->_content = $this->getContent();
484
485         $this->_currentVersion = (int) $posted['current_version'];
486
487         if ($this->_currentVersion < 0)
488             return false;
489         if ($this->_currentVersion > $this->current->getVersion())
490             return false;       // FIXME: some kind of warning?
491
492         $is_old_markup = !empty($posted['markup']) && $posted['markup'] == 'old';
493         $meta['markup'] = $is_old_markup ? false : 2.0;
494         $meta['summary'] = trim(substr($posted['summary'], 0, 256));
495         $meta['is_minor_edit'] = !empty($posted['minor_edit']);
496         $meta['pagetype'] = !empty($posted['pagetype']) ? $posted['pagetype'] : false;
497         $this->meta = array_merge($this->meta, $meta);
498         $this->locked = !empty($posted['locked']);
499
500         if (!empty($posted['preview']))
501             $this->editaction = 'preview';
502         elseif (!empty($posted['save']))
503             $this->editaction = 'save';
504         else
505             $this->editaction = 'edit';
506
507         return true;
508     }
509
510     function _initializeState () {
511         $request = &$this->request;
512         $current = &$this->current;
513         $selected = &$this->selected;
514         $user = &$this->user;
515
516         if (!$selected)
517             NoSuchRevision($request, $this->page, $this->version); // noreturn
518
519         $this->_currentVersion = $current->getVersion();
520         $this->_content = $selected->getPackedContent();
521
522         $this->meta['summary'] = '';
523         $this->locked = $this->page->get('locked');
524
525         // If author same as previous author, default minor_edit to on.
526         $age = $this->meta['mtime'] - $current->get('mtime');
527         $this->meta['is_minor_edit'] = ( $age < MINOR_EDIT_TIMEOUT
528                                          && $current->get('author') == $user->getId()
529                                          );
530
531         // Default for new pages is new-style markup.
532         if ($selected->hasDefaultContents())
533             $is_new_markup = true;
534         else
535             $is_new_markup = $selected->get('markup') >= 2.0;
536
537         $this->meta['markup'] = $is_new_markup ? 2.0: false;
538         $this->meta['pagetype'] = $selected->get('pagetype');
539         $this->editaction = 'edit';
540     }
541 }
542
543 class LoadFileConflictPageEditor
544 extends PageEditor
545 {
546     function editPage ($saveFailed = true) {
547         $tokens = &$this->tokens;
548
549         if (!$this->canEdit()) {
550             if ($this->isInitialEdit())
551                 return $this->viewSource();
552             $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
553         }
554         elseif ($this->editaction == 'save') {
555             if ($this->savePage())
556                 return true;    // Page saved.
557             $saveFailed = true;
558         }
559
560         if ($saveFailed || $this->isConcurrentUpdate())
561         {
562             // Get the text of the original page, and the two conflicting edits
563             // The diff class takes arrays as input.  So retrieve content as
564             // an array, or convert it as necesary.
565             $orig = $this->page->getRevision($this->_currentVersion);
566             $this_content = explode("\n", $this->_content);
567             $other_content = $this->current->getContent();
568             include_once("lib/diff.php");
569             $diff2 = new Diff($other_content, $this_content);
570             $context_lines = max(4, count($other_content) + 1,
571                                  count($this_content) + 1);
572             $fmt = new BlockDiffFormatter($context_lines);
573
574             $this->_content = $fmt->format($diff2);
575             // FIXME: integrate this into class BlockDiffFormatter
576             $this->_content = str_replace(">>>>>>>\n<<<<<<<\n", "=======\n",
577                                           $this->_content);
578             $this->_content = str_replace("<<<<<<<\n>>>>>>>\n", "=======\n",
579                                           $this->_content);
580
581             $this->_currentVersion = $this->current->getVersion();
582             $this->version = $this->_currentVersion;
583             $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage();
584         }
585
586         if ($this->editaction == 'preview')
587             $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
588
589         // FIXME: NOT_CURRENT_MESSAGE?
590
591         $tokens = array_merge($tokens, $this->getFormElements());
592
593         return $this->output('editpage', _("Merge and Edit: %s"));
594         // FIXME: this doesn't display
595     }
596
597     function output ($template, $title_fs) {
598         $selected = &$this->selected;
599         $current = &$this->current;
600
601         if ($selected && $selected->getVersion() != $current->getVersion()) {
602             $rev = $selected;
603             $pagelink = WikiLink($selected);
604         }
605         else {
606             $rev = $current;
607             $pagelink = WikiLink($this->page);
608         }
609
610         $title = new FormattedText ($title_fs, $pagelink);
611         $template = Template($template, $this->tokens);
612
613         //GeneratePage($template, $title, $rev);
614         PrintXML($template);
615         return true;
616     }
617     function getConflictMessage () {
618         $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.",
619                                     "<<<<<<<",
620                                     "======="),
621                                 HTML::p(_("Please check it through before saving."))));
622         return $message;
623     }
624 }
625
626 /**
627  $Log: not supported by cvs2svn $
628  Revision 1.64  2004/04/06 19:48:56  rurban
629  temp workaround for action=edit AddComment form
630
631  Revision 1.63  2004/03/24 19:39:02  rurban
632  php5 workaround code (plus some interim debugging code in XmlElement)
633    php5 doesn't work yet with the current XmlElement class constructors,
634    WikiUserNew does work better than php4.
635  rewrote WikiUserNew user upgrading to ease php5 update
636  fixed pref handling in WikiUserNew
637  added Email Notification
638  added simple Email verification
639  removed emailVerify userpref subclass: just a email property
640  changed pref binary storage layout: numarray => hash of non default values
641  print optimize message only if really done.
642  forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
643    prefs should be stored in db or homepage, besides the current session.
644
645  Revision 1.62  2004/03/17 18:41:05  rurban
646  initial_content and template support for CreatePage
647
648  Revision 1.61  2004/03/12 20:59:17  rurban
649  important cookie fix by Konstantin Zadorozhny
650  new editpage feature: JS_SEARCHREPLACE
651
652  Revision 1.60  2004/02/15 21:34:37  rurban
653  PageList enhanced and improved.
654  fixed new WikiAdmin... plugins
655  editpage, Theme with exp. htmlarea framework
656    (htmlarea yet committed, this is really questionable)
657  WikiUser... code with better session handling for prefs
658  enhanced UserPreferences (again)
659  RecentChanges for show_deleted: how should pages be deleted then?
660
661  Revision 1.59  2003/12/07 20:35:26  carstenklapp
662  Bugfix: Concurrent updates broken since after 1.3.4 release: Fatal
663  error: Call to undefined function: gettransformedcontent() in
664  /home/groups/p/ph/phpwiki/htdocs/phpwiki2/lib/editpage.php on line
665  205.
666
667  Revision 1.58  2003/03/10 18:25:22  dairiki
668  Bug/typo fix.  If you use the edit page to un/lock a page, it
669  failed with: Fatal error: Call to a member function on a
670  non-object in editpage.php on line 136
671
672  Revision 1.57  2003/02/26 03:40:22  dairiki
673  New action=create.  Essentially the same as action=edit, except that if the
674  page already exists, it falls back to action=browse.
675
676  This is for use in the "question mark" links for unknown wiki words
677  to avoid problems and confusion when following links from stale pages.
678  (If the "unknown page" has been created in the interim, the user probably
679  wants to view the page before editing it.)
680
681  Revision 1.56  2003/02/21 18:07:14  dairiki
682  Minor, nitpicky, currently inconsequential changes.
683
684  Revision 1.55  2003/02/21 04:10:58  dairiki
685  Fixes for new cached markup.
686  Some minor code cleanups.
687
688  Revision 1.54  2003/02/16 19:47:16  dairiki
689  Update WikiDB timestamp when editing or deleting pages.
690
691  Revision 1.53  2003/02/15 23:20:27  dairiki
692  Redirect back to browse current version of page upon save,
693  even when no changes were made.
694
695  Revision 1.52  2003/01/03 22:22:00  carstenklapp
696  Minor adjustments to diff block markers ("<<<<<<<"). Source reformatting.
697
698  Revision 1.51  2003/01/03 02:43:26  carstenklapp
699  New class LoadFileConflictPageEditor, for merging / comparing a loaded
700  pgsrc file with an existing page.
701
702  */
703
704 // Local Variables:
705 // mode: php
706 // tab-width: 8
707 // c-basic-offset: 4
708 // c-hanging-comment-ender-p: nil
709 // indent-tabs-mode: nil
710 // End:
711 ?>