2 rcs_id('$Id: editpage.php,v 1.32 2002-01-30 01:33:15 dairiki 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 'author_id' => $this->user->getAuthenticatedId());
19 $version = $request->getArg('version');
20 if ($version !== false) {
21 $this->selected = $this->page->getRevision($version);
22 $this->version = $version;
25 $this->selected = $this->current;
26 $this->version = $this->current->getVersion();
29 if ($this->_restoreState()) {
30 $this->_initialEdit = false;
33 $this->_initializeState();
34 $this->_initialEdit = true;
38 function editPage () {
42 if ($this->isLocked()) {
43 if ($this->isInitialEdit())
44 return $this->viewSource();
45 $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
47 elseif ($this->editaction == 'save') {
48 if ($this->savePage())
49 return true; // Page saved.
53 if ($saveFailed || $this->isConcurrentUpdate())
54 $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage();
56 if ($this->editaction == 'preview')
57 $tokens['PREVIEW_CONTENT'] = $this->getPreview(); // FIXME: convert to _MESSAGE?
59 // FIXME: NOT_CURRENT_MESSAGE?
61 $tokens = array_merge($tokens, $this->getFormElements());
63 return $this->output('editpage', _("Edit: %s"), $tokens);
66 function output ($template, $title_fs, $tokens) {
69 $pagename = $this->page->getName();
70 $selected = &$this->selected;
71 $current = &$this->current;
73 if ($selected && $selected->getVersion() != $current->getVersion()) {
75 $pagelink = $Theme->LinkExistingWikiWord($pagename, '',
76 $selected->getVersion());
80 $pagelink = $Theme->LinkExistingWikiWord($pagename);
84 $title = new FormattedText ($title_fs, $pagelink);
85 $template = Template($template, $tokens);
87 GeneratePage($template, $title, $rev);
92 function viewSource ($tokens = false) {
93 assert($this->isInitialEdit());
94 assert($this->selected);
96 $tokens['PAGE_SOURCE'] = $this->_content;
98 return $this->output('viewsource', _("View Source: %s"), $tokens);
101 function savePage () {
102 $request = &$this->request;
104 if ($this->isUnchanged()) {
105 // Save failed. No changes made.
106 include_once('lib/display.php');
107 // force browse of current version:
108 $request->setArg('version', false);
109 displayPage($request, 'nochanges');
113 $page = &$this->page;
116 $newrevision = $page->createRevision($this->_currentVersion + 1,
119 ExtractWikiPageLinks($this->_content));
120 if (!is_object($newrevision)) {
121 // Save failed. (Concurrent updates).
125 // New contents successfully saved...
127 // Clean out archived versions of this page.
128 include_once('lib/ArchiveCleaner.php');
129 $cleaner = new ArchiveCleaner($GLOBALS['ExpireParams']);
130 $cleaner->cleanPageRevisions($page);
132 $dbi = $request->getDbh();
133 $warnings = $dbi->GenericWarnings();
136 if (empty($warnings) && ! $Theme->getImageURL('signature')) {
137 // Do redirect to browse page if no signature has
138 // been defined. In this case, the user will most
139 // likely not see the rest of the HTML we generate
141 $request->redirect(WikiURL($page, false, 'absolute_url'));
144 // Force browse of current page version.
145 $request->setArg('version', false);
146 include_once('lib/BlockParser.php');
147 $template = Template('savepage',
148 array('CONTENT' => TransformRevision($newrevision)));
149 if (!empty($warnings))
150 $template->replace('WARNINGS', $warnings);
152 $pagelink = $Theme->linkExistingWikiWord($page->getName());
154 GeneratePage($template, fmt("Saved: %s", $pagelink), $newrevision);
158 function isConcurrentUpdate () {
159 assert($this->current->getVersion() >= $this->_currentVersion);
160 return $this->current->getVersion() != $this->_currentVersion;
163 function isLocked () {
164 return $this->page->get('locked') && !$this->user->isAdmin();
167 function isInitialEdit () {
168 return $this->_initialEdit;
171 function isUnchanged () {
172 $current = &$this->current;
174 if ($this->meta['markup'] != $current->get('markup'))
177 return $this->_content == $current->getPackedContent();
180 function getPreview () {
181 if ($this->meta['markup'] == 'new') {
182 include_once('lib/BlockParser.php');
183 $trfm = 'NewTransform';
186 include_once('lib/transform.php');
187 $trfm = 'do_transform';
189 return $trfm($this->_content);
192 function getLockedMessage () {
194 HTML(HTML::h2(_("Page Locked")),
195 HTML::p(_("This page has been locked by the administrator so your changes can not be saved.")),
196 HTML::p(_("(Copy your changes to the clipboard. You can try editing a different page or save your text in a text editor.)")),
197 HTML::p(_("Sorry for the inconvenience.")));
200 function getConflictMessage () {
202 xgettext only knows about c/c++ line-continuation strings
203 it does not know about php's dot operator.
204 We want to translate this entire paragraph as one string, of course.
207 $re_edit_url = WikiURL($this->page, array('action' => 'edit'));
208 $re_edit_link = HTML::a(array('href' => $re_edit_url),
209 _("Edit the new version"));
211 $steps = HTML::ol(HTML::li(_("Copy your changes to the clipboard or to another temporary place (e.g. text editor).")),
212 HTML::li(fmt("%s of the page. You should now see the most current version of the page. Your changes are no longer there.",
214 HTML::li(_("Make changes to the file again. Paste your additions from the clipboard (or text editor).")),
215 HTML::li(_("Save your updated changes.")));
217 return HTML(HTML::h2(_("Conflicting Edits!")),
218 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.")),
219 HTML::p(_("In order to recover from this situation, follow these steps:")),
221 HTML::p(_("Sorry for the inconvenience.")));
225 function getTextArea () {
226 $request = &$this->request;
228 // wrap=virtual is not HTML4, but without it NS4 doesn't wrap long lines
229 $readonly = $this->isLocked() || $this->isConcurrentUpdate();
231 return HTML::textarea(array('class' => 'wikiedit',
232 'name' => 'edit[content]',
233 'rows' => $request->getPref('editHeight'),
234 'cols' => $request->getPref('editWidth'),
235 'readonly' => (bool) $readonly,
236 'wrap' => 'virtual'),
240 function getFormElements () {
241 $request = &$this->request;
242 $page = &$this->page;
245 $h = array('action' => 'edit',
246 'pagename' => $page->getName(),
247 'version' => $this->version,
248 'edit[current_version]' => $this->_currentVersion);
250 $el['HIDDEN_INPUTS'] = HiddenInputs($h);
253 $el['EDIT_TEXTAREA'] = $this->getTextArea();
256 = HTML::input(array('type' => 'text',
257 'class' => 'wikitext',
258 'name' => 'edit[summary]',
260 'value' => $this->meta['summary']));
262 = HTML::input(array('type' => 'checkbox',
263 'name' => 'edit[minor_edit]',
264 'checked' => (bool) $this->meta['is_minor_edit']));
266 = HTML::input(array('type' => 'checkbox',
267 'name' => 'edit[markup]',
269 'checked' => $this->meta['markup'] == 'new'));
272 = $Theme->makeSubmitButton(_("Preview"), 'edit[preview]', 'button');
274 if (!$this->isConcurrentUpdate() && !$this->isLocked())
276 = $Theme->makeSubmitButton(_("Save"), 'edit[save]', 'button');
279 = $this->version == $this->current->getVersion();
285 function _restoreState () {
286 $request = &$this->request;
288 $posted = $request->getArg('edit');
289 $request->setArg('edit', false);
291 if (!$posted || !$request->isPost() || $request->getArg('action') != 'edit')
294 if (!isset($posted['content']) || !is_string($posted['content']))
296 $this->_content = preg_replace('/[ \t\r]+\n/', "\n",
297 rtrim($posted['content']));
299 $this->_currentVersion = (int) $posted['current_version'];
301 if ($this->_currentVersion < 0)
303 if ($this->_currentVersion > $this->current->getVersion())
304 return false; // FIXME: some kind of warning?
306 $is_new_markup = !empty($posted['markup']) && $posted['markup'] == 'new';
307 $meta['markup'] = $is_new_markup ? 'new' : false;
308 $meta['summary'] = trim($posted['summary']);
309 $meta['is_minor_edit'] = !empty($posted['minor_edit']);
311 $this->meta = array_merge($this->meta, $meta);
313 if (!empty($posted['preview']))
314 $this->editaction = 'preview';
315 elseif (!empty($posted['save']))
316 $this->editaction = 'save';
318 $this->editaction = 'edit';
323 function _initializeState () {
324 $request = &$this->request;
325 $current = &$this->current;
326 $selected = &$this->selected;
327 $user = &$this->user;
330 NoSuchRevision($request, $this->page, $this->version); // noreturn
332 $this->_currentVersion = $current->getVersion();
333 $this->_content = $selected->getPackedContent();
335 $this->meta['summary'] = '';
337 // If author same as previous author, default minor_edit to on.
338 $age = time() - $current->get('mtime');
339 $this->meta['is_minor_edit'] = ( $age < MINOR_EDIT_TIMEOUT
340 && $current->get('author') == $user->getId()
343 // Default for new pages is new-style markup.
344 if ($selected->hasDefaultContents())
345 $this->meta['markup'] = 'new';
347 $this->meta['markup'] = $selected->get('markup');
349 $this->editaction = 'edit';
357 // c-hanging-comment-ender-p: nil
358 // indent-tabs-mode: nil