]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/editpage.php
added a locked checkbox to the edit page for the admin
[SourceForge/phpwiki.git] / lib / editpage.php
1 <?php
2 rcs_id('$Id: editpage.php,v 1.34 2002-02-04 17:21:34 carstenklapp Exp $');
3
4 require_once('lib/Template.php');
5
6 class PageEditor
7 {
8     function PageEditor (&$request) {
9         $this->request = &$request;
10         
11         $this->user = $request->getUser();
12         $this->page = $request->getPage();
13
14         $this->current = $this->page->getCurrentRevision();
15
16         $this->meta = array('author' => $this->user->getId(),
17                             'locked' => $this->page->get('locked'),
18                             'author_id' => $this->user->getAuthenticatedId());
19         
20         $version = $request->getArg('version');
21         if ($version !== false) {
22             $this->selected = $this->page->getRevision($version);
23             $this->version = $version;
24         }
25         else {
26             $this->selected = $this->current;
27             $this->version = $this->current->getVersion();
28         }
29         
30         if ($this->_restoreState()) {
31             $this->_initialEdit = false;
32         }
33         else {
34             $this->_initializeState();
35             $this->_initialEdit = true;
36         }
37     }
38
39     function editPage () {
40         $saveFailed = false;
41         $tokens = array();
42         
43         if ($this->canEdit()) {
44             if ($this->isInitialEdit())
45                 return $this->viewSource();
46             $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
47         }
48         elseif ($this->editaction == 'save') {
49             if ($this->savePage())
50                 return true;    // Page saved.
51             $saveFailed = true;
52         }
53
54         if ($saveFailed || $this->isConcurrentUpdate())
55             $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage();
56
57         if ($this->editaction == 'preview')
58             $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
59
60         // FIXME: NOT_CURRENT_MESSAGE?
61         
62         $tokens = array_merge($tokens, $this->getFormElements());
63
64         return $this->output('editpage', _("Edit: %s"), $tokens);
65     }
66
67     function output ($template, $title_fs, $tokens) {
68         $selected = &$this->selected;
69         $current = &$this->current;
70         
71         if ($selected && $selected->getVersion() != $current->getVersion()) {
72             $rev = $selected;
73             $pagelink = WikiLink($selected);
74         }
75         else {
76             $rev = $current;
77             $pagelink = WikiLink($this->page);
78         }
79         
80         
81         $title = new FormattedText ($title_fs, $pagelink);
82         $template = Template($template, $tokens);
83
84         GeneratePage($template, $title, $rev);
85         return true;
86     }
87     
88     
89     function viewSource ($tokens = false) {
90         assert($this->isInitialEdit());
91         assert($this->selected);
92         
93         $tokens['PAGE_SOURCE'] = $this->_content;
94         
95         return $this->output('viewsource', _("View Source: %s"), $tokens);
96     }
97
98     function savePage () {
99         $request = &$this->request;
100         
101         if ($this->isUnchanged()) {
102             // Save failed. No changes made.
103             include_once('lib/display.php');
104             // force browse of current version:
105             $request->setArg('version', false);
106             displayPage($request, 'nochanges');
107             return true;
108         }
109
110         $page = &$this->page;
111         $lock = $this->meta['locked'];
112         $this->meta['locked'] = ''; // hackish
113         // Save new revision
114         $newrevision = $page->createRevision($this->_currentVersion + 1,
115                                              $this->_content,
116                                              $this->meta,
117                                              ExtractWikiPageLinks($this->_content));
118         if (!is_object($newrevision)) {
119             // Save failed.  (Concurrent updates).
120             return false;
121         }
122         // New contents successfully saved...
123         if ($lock && $this->user->isadmin()) $page->set('locked', true);
124
125         // Clean out archived versions of this page.
126         include_once('lib/ArchiveCleaner.php');
127         $cleaner = new ArchiveCleaner($GLOBALS['ExpireParams']);
128         $cleaner->cleanPageRevisions($page);
129
130         $dbi = $request->getDbh();
131         $warnings = $dbi->GenericWarnings();
132
133         global $Theme;
134         if (empty($warnings) && ! $Theme->getImageURL('signature')) {
135             // Do redirect to browse page if no signature has
136             // been defined.  In this case, the user will most
137             // likely not see the rest of the HTML we generate
138             // (below).
139             $request->redirect(WikiURL($page, false, 'absolute_url'));
140         }
141
142         // Force browse of current page version.
143         $request->setArg('version', false);
144         include_once('lib/BlockParser.php');
145         $template = Template('savepage',
146                              array('CONTENT' => TransformRevision($newrevision)));
147         if (!empty($warnings))
148             $template->replace('WARNINGS', $warnings);
149
150         $pagelink = WikiLink($page);
151         
152         GeneratePage($template, fmt("Saved: %s", $pagelink), $newrevision);
153         return true;
154     }
155     
156     function isConcurrentUpdate () {
157         assert($this->current->getVersion() >= $this->_currentVersion);
158         return $this->current->getVersion() != $this->_currentVersion;
159     }
160
161     function canEdit () {
162         return $this->page->get('locked') && !$this->user->isAdmin();
163     }
164
165     function isInitialEdit () {
166         return $this->_initialEdit;
167     }
168
169     function isUnchanged () {
170         $current = &$this->current;
171         
172         if ($this->meta['markup'] !=  $current->get('markup'))
173             return false;
174
175         return $this->_content == $current->getPackedContent();
176     }
177
178     function getPreview () {
179         if ($this->meta['markup'] == 'new') {
180             include_once('lib/BlockParser.php');
181             $trfm = 'NewTransform';
182         }
183         else {
184             include_once('lib/transform.php');
185             $trfm = 'do_transform';
186         }
187         return $trfm($this->_content);
188     }
189
190     function getLockedMessage () {
191         return
192             HTML(HTML::h2(_("Page Locked")),
193                  HTML::p(_("This page has been locked by the administrator so your changes can not be saved.")),
194                  HTML::p(_("(Copy your changes to the clipboard. You can try editing a different page or save your text in a text editor.)")),
195                  HTML::p(_("Sorry for the inconvenience.")));
196     }
197     
198     function getConflictMessage () {
199         /*
200           xgettext only knows about c/c++ line-continuation strings
201           it does not know about php's dot operator.
202           We want to translate this entire paragraph as one string, of course.
203         */
204
205         $re_edit_link = Button('edit', _("Edit the new version"), $this->page);
206
207         $steps = HTML::ol(HTML::li(_("Copy your changes to the clipboard or to another temporary place (e.g. text editor).")),
208                           HTML::li(fmt("%s of the page. You should now see the most current version of the page. Your changes are no longer there.",
209                                        $re_edit_link)),
210                           HTML::li(_("Make changes to the file again. Paste your additions from the clipboard (or text editor).")),
211                           HTML::li(_("Save your updated changes.")));
212          
213         return HTML(HTML::h2(_("Conflicting Edits!")),
214                     HTML::p(_("In the time since you started editing this page, another user has saved a new version of it.  Your changes can not be saved, since doing so would overwrite the other author's changes.")),
215                     HTML::p(_("In order to recover from this situation, follow these steps:")),
216                     $steps,
217                     HTML::p(_("Sorry for the inconvenience.")));
218     }
219
220
221     function getTextArea () {
222         $request = &$this->request;
223
224         // wrap=virtual is not HTML4, but without it NS4 doesn't wrap long lines
225         $readonly = $this->canEdit() || $this->isConcurrentUpdate();
226         
227         return HTML::textarea(array('class' => 'wikiedit',
228                                     'name' => 'edit[content]',
229                                     'rows' => $request->getPref('editHeight'),
230                                     'cols' => $request->getPref('editWidth'),
231                                     'readonly' => (bool) $readonly,
232                                     'wrap' => 'virtual'),
233                               $this->_content);
234     }
235     
236     function getFormElements () {
237         $request = &$this->request;
238         $page = &$this->page;
239
240
241         $h = array('action'                => 'edit',
242                    'pagename'              => $page->getName(),
243                    'version'               => $this->version,
244                    'edit[current_version]' => $this->_currentVersion);
245
246         $el['HIDDEN_INPUTS'] = HiddenInputs($h);
247         
248
249         $el['EDIT_TEXTAREA'] = $this->getTextArea();
250
251         $el['SUMMARY_INPUT'] 
252             = HTML::input(array('type' => 'text',
253                                 'class' => 'wikitext',
254                                 'name' => 'edit[summary]',
255                                 'size' => 50,
256                                 'value' => $this->meta['summary']));
257         $el['MINOR_EDIT_CB']
258             = HTML::input(array('type' => 'checkbox',
259                                 'name' => 'edit[minor_edit]',
260                                  'checked' => (bool) $this->meta['is_minor_edit']));
261         $el['NEW_MARKUP_CB']
262             = HTML::input(array('type' => 'checkbox',
263                                 'name' => 'edit[markup]',
264                                 'value' => 'new',
265                                 'checked' => $this->meta['markup'] == 'new'));
266
267         $el['LOCKED_CB']
268             = HTML::input(array('type' => 'checkbox',
269                                 'name' => 'edit[locked]',
270                                 'disabled' => (bool) !$this->user->isadmin(),
271                                 'checked' => (bool) $this->meta['locked']));
272
273         $el['PREVIEW_B'] = Button('submit:edit[preview]', _("Preview"));
274
275         if (!$this->isConcurrentUpdate() && !$this->canEdit())
276             $el['SAVE_B'] = Button('submit:edit[save]', _("Save"));
277
278         $el['IS_CURRENT'] = $this->version == $this->current->getVersion();
279
280         return $el;
281     }
282
283
284     function _restoreState () {
285         $request = &$this->request;
286         
287         $posted = $request->getArg('edit');
288         $request->setArg('edit', false);
289         
290         if (!$posted || !$request->isPost() || $request->getArg('action') != 'edit')
291             return false;
292
293         if (!isset($posted['content']) || !is_string($posted['content']))
294             return false;
295         $this->_content = preg_replace('/[ \t\r]+\n/', "\n",
296                                        rtrim($posted['content']));
297         
298         $this->_currentVersion = (int) $posted['current_version'];
299
300         if ($this->_currentVersion < 0)
301             return false;
302         if ($this->_currentVersion > $this->current->getVersion())
303             return false;       // FIXME: some kind of warning?
304
305         $is_new_markup = !empty($posted['markup']) && $posted['markup'] == 'new';
306         $meta['markup'] = $is_new_markup ? 'new' : false;
307         $meta['summary'] = trim($posted['summary']);
308         $meta['locked'] = !empty($posted['locked']);
309         $meta['is_minor_edit'] = !empty($posted['minor_edit']);
310
311         $this->meta = array_merge($this->meta, $meta);
312         
313         if (!empty($posted['preview']))
314             $this->editaction = 'preview';
315         elseif (!empty($posted['save']))
316             $this->editaction = 'save';
317         else
318             $this->editaction = 'edit';
319
320         return true;
321     }
322     
323     function _initializeState () {
324         $request = &$this->request;
325         $current = &$this->current;
326         $selected = &$this->selected;
327         $user = &$this->user;
328
329         if (!$selected)
330             NoSuchRevision($request, $this->page, $this->version); // noreturn
331
332         $this->_currentVersion = $current->getVersion();
333         $this->_content = $selected->getPackedContent();
334         
335         $this->meta['summary'] = '';
336         $this->meta['locked'] = $this->page->get('locked');
337
338         // If author same as previous author, default minor_edit to on.
339         $age = time() - $current->get('mtime');
340         $this->meta['is_minor_edit'] = ( $age < MINOR_EDIT_TIMEOUT
341                                          && $current->get('author') == $user->getId()
342                                          );
343
344         // Default for new pages is new-style markup.
345         if ($selected->hasDefaultContents())
346             $this->meta['markup'] = 'new';
347         else
348             $this->meta['markup'] = $selected->get('markup');
349
350         $this->editaction = 'edit';
351     }
352 }
353
354 // Local Variables:
355 // mode: php
356 // tab-width: 8
357 // c-basic-offset: 4
358 // c-hanging-comment-ender-p: nil
359 // indent-tabs-mode: nil
360 // End:   
361 ?>