2 rcs_id('$Id: editpage.php,v 1.35 2002-02-04 20:40:25 carstenklapp 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();
16 $this->meta = array('author' => $this->user->getId(),
17 'locked' => $this->page->get('locked'),
18 'author_id' => $this->user->getAuthenticatedId());
20 $version = $request->getArg('version');
21 if ($version !== false) {
22 $this->selected = $this->page->getRevision($version);
23 $this->version = $version;
26 $this->selected = $this->current;
27 $this->version = $this->current->getVersion();
30 if ($this->_restoreState()) {
31 $this->_initialEdit = false;
34 $this->_initializeState();
35 $this->_initialEdit = true;
39 function editPage () {
43 if ($this->canEdit()) {
44 if ($this->isInitialEdit())
45 return $this->viewSource();
46 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
48 elseif ($this->editaction == 'save') {
49 if ($this->savePage())
50 return true; // Page saved.
54 if ($saveFailed || $this->isConcurrentUpdate())
55 $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage();
57 if ($this->editaction == 'preview')
58 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
60 // FIXME: NOT_CURRENT_MESSAGE?
62 $tokens = array_merge($tokens, $this->getFormElements());
64 return $this->output('editpage', _("Edit: %s"), $tokens);
67 function output ($template, $title_fs, $tokens) {
68 $selected = &$this->selected;
69 $current = &$this->current;
71 if ($selected && $selected->getVersion() != $current->getVersion()) {
73 $pagelink = WikiLink($selected);
77 $pagelink = WikiLink($this->page);
81 $title = new FormattedText ($title_fs, $pagelink);
82 $template = Template($template, $tokens);
84 GeneratePage($template, $title, $rev);
89 function viewSource ($tokens = false) {
90 assert($this->isInitialEdit());
91 assert($this->selected);
93 $tokens['PAGE_SOURCE'] = $this->_content;
95 return $this->output('viewsource', _("View Source: %s"), $tokens);
98 function setPageLockChanged($isadmin, $lock, &$page) {
100 if (! $page->get('locked') == $lock) {
101 $request = &$this->request;
102 $request->setArg('lockchanged', true); //is it safe to add new args to $request like this?
104 $page->set('locked', $lock);
108 function savePage () {
109 $request = &$this->request;
111 if ($this->isUnchanged()) {
112 // Allow admin lock/unlock even if
113 // no text changes were made.
114 if ($isadmin = $this->user->isadmin()) {
115 $page = &$this->page;
116 $lock = $this->meta['locked'];
117 $this->setPageLockChanged($isadmin, $lock, &$page);
119 // Save failed. No changes made.
120 include_once('lib/display.php');
121 // force browse of current version:
122 $request->setArg('version', false);
123 displayPage($request, 'nochanges');
127 $page = &$this->page;
128 $lock = $this->meta['locked'];
129 $this->meta['locked'] = ''; // hackish
132 $newrevision = $page->createRevision($this->_currentVersion + 1,
135 ExtractWikiPageLinks($this->_content));
136 if (!is_object($newrevision)) {
137 // Save failed. (Concurrent updates).
140 // New contents successfully saved...
141 if ($isadmin = $this->user->isadmin())
142 $this->setPageLockChanged($isadmin, $lock, &$page);
144 // Clean out archived versions of this page.
145 include_once('lib/ArchiveCleaner.php');
146 $cleaner = new ArchiveCleaner($GLOBALS['ExpireParams']);
147 $cleaner->cleanPageRevisions($page);
149 $dbi = $request->getDbh();
150 $warnings = $dbi->GenericWarnings();
153 if (empty($warnings) && ! $Theme->getImageURL('signature')) {
154 // Do redirect to browse page if no signature has
155 // been defined. In this case, the user will most
156 // likely not see the rest of the HTML we generate
158 $request->redirect(WikiURL($page, false, 'absolute_url'));
161 // Force browse of current page version.
162 $request->setArg('version', false);
163 include_once('lib/BlockParser.php');
164 $template = Template('savepage',
165 array('CONTENT' => TransformRevision($newrevision)));
166 if (!empty($warnings))
167 $template->replace('WARNINGS', $warnings);
169 $pagelink = WikiLink($page);
171 GeneratePage($template, fmt("Saved: %s", $pagelink), $newrevision);
175 function isConcurrentUpdate () {
176 assert($this->current->getVersion() >= $this->_currentVersion);
177 return $this->current->getVersion() != $this->_currentVersion;
180 function canEdit () {
181 return $this->page->get('locked') && !$this->user->isAdmin();
184 function isInitialEdit () {
185 return $this->_initialEdit;
188 function isUnchanged () {
189 $current = &$this->current;
191 if ($this->meta['markup'] != $current->get('markup'))
194 return $this->_content == $current->getPackedContent();
197 function getPreview () {
198 if ($this->meta['markup'] == 'new') {
199 include_once('lib/BlockParser.php');
200 $trfm = 'NewTransform';
203 include_once('lib/transform.php');
204 $trfm = 'do_transform';
206 return $trfm($this->_content);
209 function getLockedMessage () {
211 HTML(HTML::h2(_("Page Locked")),
212 HTML::p(_("This page has been locked by the administrator so your changes can not be saved.")),
213 HTML::p(_("(Copy your changes to the clipboard. You can try editing a different page or save your text in a text editor.)")),
214 HTML::p(_("Sorry for the inconvenience.")));
217 function getConflictMessage () {
219 xgettext only knows about c/c++ line-continuation strings
220 it does not know about php's dot operator.
221 We want to translate this entire paragraph as one string, of course.
224 $re_edit_link = Button('edit', _("Edit the new version"), $this->page);
226 $steps = HTML::ol(HTML::li(_("Copy your changes to the clipboard or to another temporary place (e.g. text editor).")),
227 HTML::li(fmt("%s of the page. You should now see the most current version of the page. Your changes are no longer there.",
229 HTML::li(_("Make changes to the file again. Paste your additions from the clipboard (or text editor).")),
230 HTML::li(_("Save your updated changes.")));
232 return HTML(HTML::h2(_("Conflicting Edits!")),
233 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.")),
234 HTML::p(_("In order to recover from this situation, follow these steps:")),
236 HTML::p(_("Sorry for the inconvenience.")));
240 function getTextArea () {
241 $request = &$this->request;
243 // wrap=virtual is not HTML4, but without it NS4 doesn't wrap long lines
244 $readonly = $this->canEdit() || $this->isConcurrentUpdate();
246 return HTML::textarea(array('class' => 'wikiedit',
247 'name' => 'edit[content]',
248 'rows' => $request->getPref('editHeight'),
249 'cols' => $request->getPref('editWidth'),
250 'readonly' => (bool) $readonly,
251 'wrap' => 'virtual'),
255 function getFormElements () {
256 $request = &$this->request;
257 $page = &$this->page;
260 $h = array('action' => 'edit',
261 'pagename' => $page->getName(),
262 'version' => $this->version,
263 'edit[current_version]' => $this->_currentVersion);
265 $el['HIDDEN_INPUTS'] = HiddenInputs($h);
268 $el['EDIT_TEXTAREA'] = $this->getTextArea();
271 = HTML::input(array('type' => 'text',
272 'class' => 'wikitext',
273 'name' => 'edit[summary]',
275 'value' => $this->meta['summary']));
277 = HTML::input(array('type' => 'checkbox',
278 'name' => 'edit[minor_edit]',
279 'checked' => (bool) $this->meta['is_minor_edit']));
281 = HTML::input(array('type' => 'checkbox',
282 'name' => 'edit[markup]',
284 'checked' => $this->meta['markup'] == 'new'));
287 = HTML::input(array('type' => 'checkbox',
288 'name' => 'edit[locked]',
289 'disabled' => (bool) !$this->user->isadmin(),
290 'checked' => (bool) $this->meta['locked']));
292 $el['PREVIEW_B'] = Button('submit:edit[preview]', _("Preview"));
294 if (!$this->isConcurrentUpdate() && !$this->canEdit())
295 $el['SAVE_B'] = Button('submit:edit[save]', _("Save"));
297 $el['IS_CURRENT'] = $this->version == $this->current->getVersion();
303 function _restoreState () {
304 $request = &$this->request;
306 $posted = $request->getArg('edit');
307 $request->setArg('edit', false);
309 if (!$posted || !$request->isPost() || $request->getArg('action') != 'edit')
312 if (!isset($posted['content']) || !is_string($posted['content']))
314 $this->_content = preg_replace('/[ \t\r]+\n/', "\n",
315 rtrim($posted['content']));
317 $this->_currentVersion = (int) $posted['current_version'];
319 if ($this->_currentVersion < 0)
321 if ($this->_currentVersion > $this->current->getVersion())
322 return false; // FIXME: some kind of warning?
324 $is_new_markup = !empty($posted['markup']) && $posted['markup'] == 'new';
325 $meta['markup'] = $is_new_markup ? 'new' : false;
326 $meta['summary'] = trim($posted['summary']);
327 $meta['locked'] = !empty($posted['locked']);
328 $meta['is_minor_edit'] = !empty($posted['minor_edit']);
330 $this->meta = array_merge($this->meta, $meta);
332 if (!empty($posted['preview']))
333 $this->editaction = 'preview';
334 elseif (!empty($posted['save']))
335 $this->editaction = 'save';
337 $this->editaction = 'edit';
342 function _initializeState () {
343 $request = &$this->request;
344 $current = &$this->current;
345 $selected = &$this->selected;
346 $user = &$this->user;
349 NoSuchRevision($request, $this->page, $this->version); // noreturn
351 $this->_currentVersion = $current->getVersion();
352 $this->_content = $selected->getPackedContent();
354 $this->meta['summary'] = '';
355 $this->meta['locked'] = $this->page->get('locked');
357 // If author same as previous author, default minor_edit to on.
358 $age = time() - $current->get('mtime');
359 $this->meta['is_minor_edit'] = ( $age < MINOR_EDIT_TIMEOUT
360 && $current->get('author') == $user->getId()
363 // Default for new pages is new-style markup.
364 if ($selected->hasDefaultContents())
365 $this->meta['markup'] = 'new';
367 $this->meta['markup'] = $selected->get('markup');
369 $this->editaction = 'edit';
377 // c-hanging-comment-ender-p: nil
378 // indent-tabs-mode: nil