bc59468028c2b60aa1b9b79d6238e2b312f0b83c
[lhc/web/wiklou.git] / includes / EditPage.php
1 <?php
2
3 # Splitting edit page/HTML interface from Article...
4 # The actual database and text munging is still in Article,
5 # but it should get easier to call those from alternate
6 # interfaces.
7
8 class EditPage {
9 var $mArticle;
10 var $mTitle;
11
12 function EditPage( $article ) {
13 $this->mArticle =& $article;
14 global $wgTitle;
15 $this->mTitle =& $wgTitle;
16 }
17
18 # This is the function that gets called for "action=edit".
19
20 function edit()
21 {
22 global $wgOut, $wgUser, $wgWhitelistEdit;
23 global $wpTextbox1, $wpSummary, $wpSave, $wpPreview;
24 global $wpMinoredit, $wpEdittime, $wpTextbox2;
25 // this is not an article
26 $wgOut->setArticleFlag(false);
27
28 $fields = array( "wpTextbox1", "wpSummary", "wpTextbox2" );
29 wfCleanFormFields( $fields );
30
31 if ( ! $this->mTitle->userCanEdit() ) {
32 $wgOut->readOnlyPage( $this->mArticle->getContent(), true );
33 return;
34 }
35 if ( $wgUser->isBlocked() ) {
36 $this->blockedIPpage();
37 return;
38 }
39 if ( !$wgUser->getID() && $wgWhitelistEdit ) {
40 $this->userNotLoggedInPage();
41 return;
42 }
43 if ( wfReadOnly() ) {
44 if( isset( $wpSave ) or isset( $wpPreview ) ) {
45 $this->editForm( "preview" );
46 } else {
47 $wgOut->readOnlyPage( $this->mArticle->getContent() );
48 }
49 return;
50 }
51 if ( $_SERVER['REQUEST_METHOD'] != "POST" ) unset( $wpSave );
52 if ( isset( $wpSave ) ) {
53 $this->editForm( "save" );
54 } else if ( isset( $wpPreview ) ) {
55 $this->editForm( "preview" );
56 } else { # First time through
57 $this->editForm( "initial" );
58 }
59 }
60
61 # Since there is only one text field on the edit form,
62 # pressing <enter> will cause the form to be submitted, but
63 # the submit button value won't appear in the query, so we
64 # Fake it here before going back to edit(). This is kind of
65 # ugly, but it helps some old URLs to still work.
66
67 function submit()
68 {
69 global $wpSave, $wpPreview;
70 if ( ! isset( $wpPreview ) ) { $wpSave = 1; }
71
72 $this->edit();
73 }
74
75 # The edit form is self-submitting, so that when things like
76 # preview and edit conflicts occur, we get the same form back
77 # with the extra stuff added. Only when the final submission
78 # is made and all is well do we actually save and redirect to
79 # the newly-edited page.
80
81 function editForm( $formtype )
82 {
83 global $wgOut, $wgUser;
84 global $wpTextbox1, $wpSummary, $wpWatchthis;
85 global $wpSave, $wpPreview;
86 global $wpMinoredit, $wpEdittime, $wpTextbox2, $wpSection;
87 global $oldid, $redirect, $section;
88 global $wgLang, $wgParser, $wgTitle;
89 global $wgAllowAnonymousMinor;
90
91 if(isset($wpSection)) { $section=$wpSection; } else { $wpSection=$section; }
92
93 $sk = $wgUser->getSkin();
94 $isConflict = false;
95 $wpTextbox1 = rtrim ( $wpTextbox1 ) ; # To avoid text getting longer on each preview
96
97 if(!$this->mTitle->getArticleID()) { # new article
98 $wgOut->addWikiText(wfmsg("newarticletext"));
99 }
100
101 $talknamespaces = array( NS_TALK, NS_WP_TALK, NS_IMAGE_TALK, NS_MEDIAWIKI_TALK );
102 if( in_array( $this->mTitle->getNamespace(), $talknamespaces ) ) {
103 $wgOut->addWikiText(wfmsg("talkpagetext"));
104 }
105
106 # Attempt submission here. This will check for edit conflicts,
107 # and redundantly check for locked database, blocked IPs, etc.
108 # that edit() already checked just in case someone tries to sneak
109 # in the back door with a hand-edited submission URL.
110
111 if ( "save" == $formtype ) {
112 if ( $wgUser->isBlocked() ) {
113 $this->blockedIPpage();
114 return;
115 }
116 if ( !$wgUser->getID() && $wgWhitelistEdit ) {
117 $this->userNotLoggedInPage();
118 return;
119 }
120 if ( wfReadOnly() ) {
121 $wgOut->readOnlyPage();
122 return;
123 }
124 # If article is new, insert it.
125
126 $aid = $this->mTitle->getArticleID();
127 if ( 0 == $aid ) {
128 # we need to strip Windoze linebreaks because some browsers
129 # append them and the string comparison fails
130 if ( ( "" == $wpTextbox1 ) ||
131 ( wfMsg( "newarticletext" ) == rtrim( preg_replace("/\r/","",$wpTextbox1) ) ) ) {
132 $wgOut->redirect( $this->mTitle->getURL() );
133 return;
134 }
135 $this->mArticle->insertNewArticle( $wpTextbox1, $wpSummary, $wpMinoredit, $wpWatchthis );
136 return;
137 }
138 # Article exists. Check for edit conflict.
139 # Don't check for conflict when appending a comment - this should always work
140
141 $this->mArticle->clear(); # Force reload of dates, etc.
142 if ( $section!="new" && ( $this->mArticle->getTimestamp() != $wpEdittime ) ) {
143 $isConflict = true;
144 }
145 $u = $wgUser->getID();
146
147 # Suppress edit conflict with self
148
149 if ( ( 0 != $u ) && ( $this->mArticle->getUser() == $u ) ) {
150 $isConflict = false;
151 } else {
152 # switch from section editing to normal editing in edit conflict
153 if($isConflict) {
154 $section="";$wpSection="";
155 }
156
157 }
158 if ( ! $isConflict ) {
159 # All's well: update the article here
160 if($this->mArticle->updateArticle( $wpTextbox1, $wpSummary, $wpMinoredit, $wpWatchthis, $wpSection ))
161 return;
162 else
163 $isConflict = true;
164 }
165 }
166 # First time through: get contents, set time for conflict
167 # checking, etc.
168
169 if ( "initial" == $formtype ) {
170 $wpEdittime = $this->mArticle->getTimestamp();
171 $wpTextbox1 = $this->mArticle->getContent(true);
172 $wpSummary = "";
173 }
174 $wgOut->setRobotpolicy( "noindex,nofollow" );
175
176 # Enabled article-related sidebar, toplinks, etc.
177 $wgOut->setArticleRelated( true );
178
179 if ( $isConflict ) {
180 $s = wfMsg( "editconflict", $this->mTitle->getPrefixedText() );
181 $wgOut->setPageTitle( $s );
182 $wgOut->addHTML( wfMsg( "explainconflict" ) );
183
184 $wpTextbox2 = $wpTextbox1;
185 $wpTextbox1 = $this->mArticle->getContent(true);
186 $wpEdittime = $this->mArticle->getTimestamp();
187 } else {
188 $s = wfMsg( "editing", $this->mTitle->getPrefixedText() );
189
190 if($section!="") {
191 if($section=="new") {
192 $s.=wfMsg("commentedit");
193 } else {
194 $s.=wfMsg("sectionedit");
195 }
196 }
197 $wgOut->setPageTitle( $s );
198 if ( $oldid ) {
199 $this->mArticle->setOldSubtitle();
200 $wgOut->addHTML( wfMsg( "editingold" ) );
201 }
202 }
203
204 if( wfReadOnly() ) {
205 $wgOut->addHTML( "<strong>" .
206 wfMsg( "readonlywarning" ) .
207 "</strong>" );
208 }
209 if( $this->mTitle->isProtected() ) {
210 $wgOut->addHTML( "<strong>" . wfMsg( "protectedpagewarning" ) .
211 "</strong><br />\n" );
212 }
213
214 $kblength = (int)(strlen( $wpTextbox1 ) / 1024);
215 if( $kblength > 29 ) {
216 $wgOut->addHTML( "<strong>" .
217 wfMsg( "longpagewarning", $kblength )
218 . "</strong>" );
219 }
220
221 $rows = $wgUser->getOption( "rows" );
222 $cols = $wgUser->getOption( "cols" );
223
224 $ew = $wgUser->getOption( "editwidth" );
225 if ( $ew ) $ew = " style=\"width:100%\"";
226 else $ew = "" ;
227
228 $q = "action=submit";
229 if ( "no" == $redirect ) { $q .= "&redirect=no"; }
230 $action = $this->mTitle->getURL( $q, true );
231
232 $summary = wfMsg( "summary" );
233 $subject = wfMsg("subject");
234 $minor = wfMsg( "minoredit" );
235 $watchthis = wfMsg ("watchthis");
236 $save = wfMsg( "savearticle" );
237 $prev = wfMsg( "showpreview" );
238
239 $cancel = $sk->makeKnownLink( $this->mTitle->getPrefixedURL(),
240 wfMsg( "cancel" ) );
241 $edithelp = $sk->makeKnownLink( wfMsg( "edithelppage" ),
242 wfMsg( "edithelp" ) );
243 $copywarn = wfMsg( "copyrightwarning", $sk->makeKnownLink(
244 wfMsg( "copyrightpage" ) ) );
245
246 $wpTextbox1 = wfEscapeHTML( $wpTextbox1 );
247 $wpTextbox2 = wfEscapeHTML( $wpTextbox2 );
248 $wpSummary = wfEscapeHTML( $wpSummary );
249
250
251 if($wgUser->getOption("showtoolbar")) {
252 // prepare toolbar for edit buttons
253 $toolbar=$sk->getEditToolbar();
254 }
255
256 // activate checkboxes if user wants them to be always active
257 if (!$wpPreview && $wgUser->getOption("watchdefault")) $wpWatchthis=1;
258 if (!$wpPreview && $wgUser->getOption("minordefault")) $wpMinoredit=1;
259
260 // activate checkbox also if user is already watching the page,
261 // require wpWatchthis to be unset so that second condition is not
262 // checked unnecessarily
263 if (!$wpWatchthis && !$wpPreview && $this->mTitle->userIsWatching()) $wpWatchthis=1;
264
265 $minoredithtml = "";
266
267 if ( 0 != $wgUser->getID() || $wgAllowAnonymousMinor ) {
268 $minoredithtml =
269 "<input tabindex=3 type=checkbox value=1 name='wpMinoredit'".($wpMinoredit?" checked":"")." id='wpMinoredit'>".
270 "<label for='wpMinoredit'>{$minor}</label>";
271 }
272
273 $watchhtml = "";
274
275 if ( 0 != $wgUser->getID() ) {
276 $watchhtml = "<input tabindex=4 type=checkbox name='wpWatchthis'".($wpWatchthis?" checked":"")." id='wpWatchthis'>".
277 "<label for='wpWatchthis'>{$watchthis}</label>";
278
279 }
280
281 $checkboxhtml= $minoredithtml . $watchhtml . "<br>";
282
283 if ( "preview" == $formtype) {
284
285 $previewhead="<h2>" . wfMsg( "preview" ) . "</h2>\n<p><large><center><font color=\"#cc0000\">" .
286 wfMsg( "note" ) . wfMsg( "previewnote" ) . "</font></center></large><P>\n";
287 if ( $isConflict ) {
288 $previewhead.="<h2>" . wfMsg( "previewconflict" ) .
289 "</h2>\n";
290 }
291 $previewtext = wfUnescapeHTML( $wpTextbox1 );
292
293 $parserOptions = ParserOptions::newFromUser( $wgUser );
294 $parserOptions->setUseCategoryMagic( false );
295 $parserOptions->setEditSection( false );
296 $parserOptions->setEditSectionOnRightClick( false );
297 $parserOutput = $wgParser->parse( $this->mArticle->preSaveTransform( $previewtext ) ."\n\n",
298 $wgTitle, $parserOptions );
299 $previewHTML = $parserOutput->mText;
300
301 if($wgUser->getOption("previewontop")) {
302 $wgOut->addHTML($previewhead);
303 $wgOut->addHTML($previewHTML);
304 }
305 $wgOut->addHTML( "<br clear=\"all\" />\n" );
306 }
307
308 # if this is a comment, show a subject line at the top, which is also the edit summary.
309 # Otherwise, show a summary field at the bottom
310 if($section=="new") {
311
312 $commentsubject="{$subject}: <input tabindex=1 type=text value=\"{$wpSummary}\" name=\"wpSummary\" maxlength=200 size=60><br>";
313 } else {
314
315 $editsummary="{$summary}: <input tabindex=3 type=text value=\"{$wpSummary}\" name=\"wpSummary\" maxlength=200 size=60><br>";
316 }
317
318 if( $_GET["action"] == "edit" ) {
319 # Don't select the edit box on preview; this interferes with seeing what's going on.
320 $wgOut->setOnloadHandler( "document.editform.wpTextbox1.focus()" );
321 }
322 $wgOut->addHTML( "
323 {$toolbar}
324 <form id=\"editform\" name=\"editform\" method=\"post\" action=\"$action\"
325 enctype=\"application/x-www-form-urlencoded\">
326 {$commentsubject}
327 <textarea tabindex=2 name=\"wpTextbox1\" rows={$rows}
328 cols={$cols}{$ew} wrap=\"virtual\">" .
329 $wgLang->recodeForEdit( $wpTextbox1 ) .
330 "
331 </textarea>
332 <br>{$editsummary}
333 {$checkboxhtml}
334 <input tabindex=5 type=submit value=\"{$save}\" name=\"wpSave\" accesskey=\"s\">
335 <input tabindex=6 type=submit value=\"{$prev}\" name=\"wpPreview\" accesskey=\"p\">
336 <em>{$cancel}</em> | <em>{$edithelp}</em>
337 <br><br>{$copywarn}
338 <input type=hidden value=\"{$section}\" name=\"wpSection\">
339 <input type=hidden value=\"{$wpEdittime}\" name=\"wpEdittime\">\n" );
340
341 if ( $isConflict ) {
342 $wgOut->addHTML( "<h2>" . wfMsg( "yourdiff" ) . "</h2>\n" );
343 DifferenceEngine::showDiff( $wpTextbox2, $wpTextbox1,
344 wfMsg( "yourtext" ), wfMsg( "storedversion" ) );
345
346 $wgOut->addHTML( "<h2>" . wfMsg( "yourtext" ) . "</h2>
347 <textarea tabindex=6 name=\"wpTextbox2\" rows={$rows} cols={$cols} wrap=virtual>"
348 . $wgLang->recodeForEdit( $wpTextbox2 ) .
349 "
350 </textarea>" );
351 }
352 $wgOut->addHTML( "</form>\n" );
353 if($formtype =="preview" && !$wgUser->getOption("previewontop")) {
354 $wgOut->addHTML($previewhead);
355 $wgOut->addHTML($previewHTML);
356 }
357
358 }
359
360 function blockedIPpage()
361 {
362 global $wgOut, $wgUser, $wgLang, $wgIP;
363
364 $wgOut->setPageTitle( wfMsg( "blockedtitle" ) );
365 $wgOut->setRobotpolicy( "noindex,nofollow" );
366 $wgOut->setArticleRelated( false );
367
368 $id = $wgUser->blockedBy();
369 $reason = $wgUser->blockedFor();
370 $ip = $wgIP;
371
372 $name = User::whoIs( $id );
373 $link = "[[" . $wgLang->getNsText( Namespace::getUser() ) .
374 ":{$name}|{$name}]]";
375
376 $wgOut->addWikiText( wfMsg( "blockedtext", $link, $reason, $ip ) );
377 $wgOut->returnToMain( false );
378 }
379
380
381
382 function userNotLoggedInPage()
383 {
384 global $wgOut, $wgUser, $wgLang;
385
386 $wgOut->setPageTitle( wfMsg( "whitelistedittitle" ) );
387 $wgOut->setRobotpolicy( "noindex,nofollow" );
388 $wgOut->setArticleRelated( false );
389
390 $wgOut->addWikiText( wfMsg( "whitelistedittext" ) );
391 $wgOut->returnToMain( false );
392 }
393
394
395 }
396
397 ?>