Index: trunk/phase3/docs/hooks.txt |
— | — | @@ -264,6 +264,17 @@ |
265 | 265 | $user: the User object about to be created (read-only, incomplete) |
266 | 266 | $message: out parameter: error message to display on abort |
267 | 267 | |
| 268 | +'ActionBeforeFormDisplay': Modify the form shown for an action (added 1.18) |
| 269 | +$action: String |
| 270 | +$form: HTMLForm |
| 271 | +$page: Article |
| 272 | + |
| 273 | +'ActionModifyFormFields': Modify the descriptor array which will be used to create an |
| 274 | +action form |
| 275 | +$action: String |
| 276 | +$fields: Array |
| 277 | +$page: Article |
| 278 | + |
268 | 279 | 'AddNewAccount': after a user account is created |
269 | 280 | $user: the User object that was created. (Parameter added in 1.7) |
270 | 281 | $byEmail: true when account was created "by email" (added in 1.12) |
— | — | @@ -384,12 +395,6 @@ |
385 | 396 | $article: the article (object) being loaded from the database |
386 | 397 | $content: the content (string) of the article |
387 | 398 | |
388 | | -'ArticleConfirmDelete': before writing the confirmation form for article |
389 | | - deletion |
390 | | -$article: the article (object) being deleted |
391 | | -$output: the OutputPage object ($wgOut) |
392 | | -&$reason: the reason (string) the article is being deleted |
393 | | - |
394 | 399 | 'ArticleContentOnDiff': before showing the article content below a diff. |
395 | 400 | Use this to change the content in this area or how it is loaded. |
396 | 401 | $diffEngine: the DifferenceEngine |
Index: trunk/phase3/includes/Credits.php |
— | — | @@ -1,238 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * Formats credits for articles |
5 | | - * |
6 | | - * Copyright 2004, Evan Prodromou <evan@wikitravel.org>. |
7 | | - * |
8 | | - * This program is free software; you can redistribute it and/or modify |
9 | | - * it under the terms of the GNU General Public License as published by |
10 | | - * the Free Software Foundation; either version 2 of the License, or |
11 | | - * (at your option) any later version. |
12 | | - * |
13 | | - * This program is distributed in the hope that it will be useful, |
14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | - * GNU General Public License for more details. |
17 | | - * |
18 | | - * You should have received a copy of the GNU General Public License |
19 | | - * along with this program; if not, write to the Free Software |
20 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
21 | | - * |
22 | | - * @file |
23 | | - * @author <evan@wikitravel.org> |
24 | | - */ |
25 | | - |
26 | | -class Credits { |
27 | | - /** |
28 | | - * This is largely cadged from PageHistory::history |
29 | | - * @param $article Article object |
30 | | - */ |
31 | | - public static function showPage( Article $article ) { |
32 | | - global $wgOut; |
33 | | - |
34 | | - wfProfileIn( __METHOD__ ); |
35 | | - |
36 | | - $wgOut->setPageTitle( $article->mTitle->getPrefixedText() ); |
37 | | - $wgOut->setSubtitle( wfMsg( 'creditspage' ) ); |
38 | | - $wgOut->setArticleFlag( false ); |
39 | | - $wgOut->setArticleRelated( true ); |
40 | | - $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
41 | | - |
42 | | - if ( $article->mTitle->getArticleID() == 0 ) { |
43 | | - $s = wfMsg( 'nocredits' ); |
44 | | - } else { |
45 | | - $s = self::getCredits( $article, -1 ); |
46 | | - } |
47 | | - |
48 | | - $wgOut->addHTML( $s ); |
49 | | - |
50 | | - wfProfileOut( __METHOD__ ); |
51 | | - } |
52 | | - |
53 | | - /** |
54 | | - * Get a list of contributors of $article |
55 | | - * @param $article Article object |
56 | | - * @param $cnt Int: maximum list of contributors to show |
57 | | - * @param $showIfMax Bool: whether to contributors if there more than $cnt |
58 | | - * @return String: html |
59 | | - */ |
60 | | - public static function getCredits( Article $article, $cnt, $showIfMax = true ) { |
61 | | - wfProfileIn( __METHOD__ ); |
62 | | - $s = ''; |
63 | | - |
64 | | - if ( isset( $cnt ) && $cnt != 0 ) { |
65 | | - $s = self::getAuthor( $article ); |
66 | | - if ( $cnt > 1 || $cnt < 0 ) { |
67 | | - $s .= ' ' . self::getContributors( $article, $cnt - 1, $showIfMax ); |
68 | | - } |
69 | | - } |
70 | | - |
71 | | - wfProfileOut( __METHOD__ ); |
72 | | - return $s; |
73 | | - } |
74 | | - |
75 | | - /** |
76 | | - * Get the last author with the last modification time |
77 | | - * @param $article Article object |
78 | | - */ |
79 | | - protected static function getAuthor( Article $article ) { |
80 | | - global $wgLang; |
81 | | - |
82 | | - $user = User::newFromId( $article->getUser() ); |
83 | | - |
84 | | - $timestamp = $article->getTimestamp(); |
85 | | - if ( $timestamp ) { |
86 | | - $d = $wgLang->date( $article->getTimestamp(), true ); |
87 | | - $t = $wgLang->time( $article->getTimestamp(), true ); |
88 | | - } else { |
89 | | - $d = ''; |
90 | | - $t = ''; |
91 | | - } |
92 | | - return wfMsgExt( 'lastmodifiedatby', 'parsemag', $d, $t, self::userLink( $user ), $user->getName() ); |
93 | | - } |
94 | | - |
95 | | - /** |
96 | | - * Get a list of contributors of $article |
97 | | - * @param $article Article object |
98 | | - * @param $cnt Int: maximum list of contributors to show |
99 | | - * @param $showIfMax Bool: whether to contributors if there more than $cnt |
100 | | - * @return String: html |
101 | | - */ |
102 | | - protected static function getContributors( Article $article, $cnt, $showIfMax ) { |
103 | | - global $wgLang, $wgHiddenPrefs; |
104 | | - |
105 | | - $contributors = $article->getContributors(); |
106 | | - |
107 | | - $others_link = false; |
108 | | - |
109 | | - # Hmm... too many to fit! |
110 | | - if ( $cnt > 0 && $contributors->count() > $cnt ) { |
111 | | - $others_link = self::othersLink( $article ); |
112 | | - if ( !$showIfMax ) |
113 | | - return wfMsgExt( 'othercontribs', 'parsemag', $others_link, $contributors->count() ); |
114 | | - } |
115 | | - |
116 | | - $real_names = array(); |
117 | | - $user_names = array(); |
118 | | - $anon_ips = array(); |
119 | | - |
120 | | - # Sift for real versus user names |
121 | | - foreach ( $contributors as $user ) { |
122 | | - $cnt--; |
123 | | - if ( $user->isLoggedIn() ) { |
124 | | - $link = self::link( $user ); |
125 | | - if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) { |
126 | | - $real_names[] = $link; |
127 | | - } else { |
128 | | - $user_names[] = $link; |
129 | | - } |
130 | | - } else { |
131 | | - $anon_ips[] = self::link( $user ); |
132 | | - } |
133 | | - |
134 | | - if ( $cnt == 0 ) { |
135 | | - break; |
136 | | - } |
137 | | - } |
138 | | - |
139 | | - if ( count( $real_names ) ) { |
140 | | - $real = $wgLang->listToText( $real_names ); |
141 | | - } else { |
142 | | - $real = false; |
143 | | - } |
144 | | - |
145 | | - # "ThisSite user(s) A, B and C" |
146 | | - if ( count( $user_names ) ) { |
147 | | - $user = wfMsgExt( |
148 | | - 'siteusers', |
149 | | - 'parsemag', |
150 | | - $wgLang->listToText( $user_names ), count( $user_names ) |
151 | | - ); |
152 | | - } else { |
153 | | - $user = false; |
154 | | - } |
155 | | - |
156 | | - if ( count( $anon_ips ) ) { |
157 | | - $anon = wfMsgExt( |
158 | | - 'anonusers', |
159 | | - 'parsemag', |
160 | | - $wgLang->listToText( $anon_ips ), count( $anon_ips ) |
161 | | - ); |
162 | | - } else { |
163 | | - $anon = false; |
164 | | - } |
165 | | - |
166 | | - # This is the big list, all mooshed together. We sift for blank strings |
167 | | - $fulllist = array(); |
168 | | - foreach ( array( $real, $user, $anon, $others_link ) as $s ) { |
169 | | - if ( $s ) { |
170 | | - array_push( $fulllist, $s ); |
171 | | - } |
172 | | - } |
173 | | - |
174 | | - # Make the list into text... |
175 | | - $creds = $wgLang->listToText( $fulllist ); |
176 | | - |
177 | | - # "Based on work by ..." |
178 | | - return strlen( $creds ) |
179 | | - ? wfMsgExt( 'othercontribs', 'parsemag', $creds, count( $fulllist ) ) |
180 | | - : ''; |
181 | | - } |
182 | | - |
183 | | - /** |
184 | | - * Get a link to $user's user page |
185 | | - * @param $user User object |
186 | | - * @return String: html |
187 | | - */ |
188 | | - protected static function link( User $user ) { |
189 | | - global $wgUser, $wgHiddenPrefs; |
190 | | - if ( !in_array( 'realname', $wgHiddenPrefs ) && !$user->isAnon() ) { |
191 | | - $real = $user->getRealName(); |
192 | | - } else { |
193 | | - $real = false; |
194 | | - } |
195 | | - |
196 | | - $skin = $wgUser->getSkin(); |
197 | | - $page = $user->isAnon() ? |
198 | | - SpecialPage::getTitleFor( 'Contributions', $user->getName() ) : |
199 | | - $user->getUserPage(); |
200 | | - |
201 | | - return $skin->link( $page, htmlspecialchars( $real ? $real : $user->getName() ) ); |
202 | | - } |
203 | | - |
204 | | - /** |
205 | | - * Get a link to $user's user page |
206 | | - * @param $user User object |
207 | | - * @return String: html |
208 | | - */ |
209 | | - protected static function userLink( User $user ) { |
210 | | - $link = self::link( $user ); |
211 | | - if ( $user->isAnon() ) { |
212 | | - return wfMsgExt( 'anonuser', array( 'parseinline', 'replaceafter' ), $link ); |
213 | | - } else { |
214 | | - global $wgHiddenPrefs; |
215 | | - if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) { |
216 | | - return $link; |
217 | | - } else { |
218 | | - return wfMsgExt( 'siteuser', 'parsemag', $link, $user->getName() ); |
219 | | - } |
220 | | - } |
221 | | - } |
222 | | - |
223 | | - /** |
224 | | - * Get a link to action=credits of $article page |
225 | | - * @param $article Article object |
226 | | - * @return String: html |
227 | | - */ |
228 | | - protected static function othersLink( Article $article ) { |
229 | | - global $wgUser; |
230 | | - $skin = $wgUser->getSkin(); |
231 | | - return $skin->link( |
232 | | - $article->getTitle(), |
233 | | - wfMsgHtml( 'others' ), |
234 | | - array(), |
235 | | - array( 'action' => 'credits' ), |
236 | | - array( 'known' ) |
237 | | - ); |
238 | | - } |
239 | | -} |
Index: trunk/phase3/includes/ProtectionForm.php |
— | — | @@ -317,9 +317,9 @@ |
318 | 318 | } |
319 | 319 | |
320 | 320 | if( $wgRequest->getCheck( 'mwProtectWatch' ) && $wgUser->isLoggedIn() ) { |
321 | | - $this->mArticle->doWatch(); |
| 321 | + Action::factory( 'watch', $this->mArticle )->execute(); |
322 | 322 | } elseif( $this->mTitle->userIsWatching() ) { |
323 | | - $this->mArticle->doUnwatch(); |
| 323 | + Action::factory( 'unwatch', $this->mArticle )->execute(); |
324 | 324 | } |
325 | 325 | return $ok; |
326 | 326 | } |
Index: trunk/phase3/includes/Article.php |
— | — | @@ -2345,27 +2345,10 @@ |
2346 | 2346 | |
2347 | 2347 | /** |
2348 | 2348 | * User-interface handler for the "watch" action |
| 2349 | + * @deprecated since 1.18 |
2349 | 2350 | */ |
2350 | 2351 | public function watch() { |
2351 | | - global $wgOut; |
2352 | | - |
2353 | | - if ( $wgOut->getUser()->isAnon() ) { |
2354 | | - $wgOut->showErrorPage( 'watchnologin', 'watchnologintext' ); |
2355 | | - return; |
2356 | | - } |
2357 | | - |
2358 | | - if ( wfReadOnly() ) { |
2359 | | - $wgOut->readOnlyPage(); |
2360 | | - return; |
2361 | | - } |
2362 | | - |
2363 | | - if ( $this->doWatch() ) { |
2364 | | - $wgOut->setPagetitle( wfMsg( 'addedwatch' ) ); |
2365 | | - $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
2366 | | - $wgOut->addWikiMsg( 'addedwatchtext', $this->mTitle->getPrefixedText() ); |
2367 | | - } |
2368 | | - |
2369 | | - $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() ); |
| 2352 | + Action::factory( 'watch', $this )->show(); |
2370 | 2353 | } |
2371 | 2354 | |
2372 | 2355 | /** |
— | — | @@ -2374,64 +2357,27 @@ |
2375 | 2358 | * This is safe to be called multiple times |
2376 | 2359 | * |
2377 | 2360 | * @return bool true on successful watch operation |
| 2361 | + * @deprecated since 1.18 |
2378 | 2362 | */ |
2379 | 2363 | public function doWatch() { |
2380 | | - global $wgUser; |
2381 | | - |
2382 | | - if ( $wgUser->isAnon() ) { |
2383 | | - return false; |
2384 | | - } |
2385 | | - |
2386 | | - if ( wfRunHooks( 'WatchArticle', array( &$wgUser, &$this ) ) ) { |
2387 | | - $wgUser->addWatch( $this->mTitle ); |
2388 | | - return wfRunHooks( 'WatchArticleComplete', array( &$wgUser, &$this ) ); |
2389 | | - } |
2390 | | - |
2391 | | - return false; |
| 2364 | + return Action::factory( 'watch', $this )->execute(); |
2392 | 2365 | } |
2393 | 2366 | |
2394 | 2367 | /** |
2395 | 2368 | * User interface handler for the "unwatch" action. |
| 2369 | + * @deprecated since 1.18 |
2396 | 2370 | */ |
2397 | 2371 | public function unwatch() { |
2398 | | - global $wgOut; |
2399 | | - |
2400 | | - if ( $wgOut->getUser()->isAnon() ) { |
2401 | | - $wgOut->showErrorPage( 'watchnologin', 'watchnologintext' ); |
2402 | | - return; |
2403 | | - } |
2404 | | - |
2405 | | - if ( wfReadOnly() ) { |
2406 | | - $wgOut->readOnlyPage(); |
2407 | | - return; |
2408 | | - } |
2409 | | - |
2410 | | - if ( $this->doUnwatch() ) { |
2411 | | - $wgOut->setPagetitle( wfMsg( 'removedwatch' ) ); |
2412 | | - $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
2413 | | - $wgOut->addWikiMsg( 'removedwatchtext', $this->mTitle->getPrefixedText() ); |
2414 | | - } |
2415 | | - |
2416 | | - $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() ); |
| 2372 | + Action::factory( 'unwatch', $this )->show(); |
2417 | 2373 | } |
2418 | 2374 | |
2419 | 2375 | /** |
2420 | 2376 | * Stop watching a page |
2421 | 2377 | * @return bool true on successful unwatch |
| 2378 | + * @deprecated since 1.18 |
2422 | 2379 | */ |
2423 | 2380 | public function doUnwatch() { |
2424 | | - global $wgUser; |
2425 | | - |
2426 | | - if ( $wgUser->isAnon() ) { |
2427 | | - return false; |
2428 | | - } |
2429 | | - |
2430 | | - if ( wfRunHooks( 'UnwatchArticle', array( &$wgUser, &$this ) ) ) { |
2431 | | - $wgUser->removeWatch( $this->mTitle ); |
2432 | | - return wfRunHooks( 'UnwatchArticleComplete', array( &$wgUser, &$this ) ); |
2433 | | - } |
2434 | | - |
2435 | | - return false; |
| 2381 | + return Action::factory( 'unwatch', $this )->execute(); |
2436 | 2382 | } |
2437 | 2383 | |
2438 | 2384 | /** |
— | — | @@ -2663,229 +2609,28 @@ |
2664 | 2610 | * @param &$hasHistory Boolean: whether the page has a history |
2665 | 2611 | * @return mixed String containing deletion reason or empty string, or boolean false |
2666 | 2612 | * if no revision occurred |
| 2613 | + * @deprecated since 1.18 |
2667 | 2614 | */ |
2668 | 2615 | public function generateReason( &$hasHistory ) { |
2669 | | - global $wgContLang; |
2670 | | - |
2671 | | - $dbw = wfGetDB( DB_MASTER ); |
2672 | | - // Get the last revision |
2673 | | - $rev = Revision::newFromTitle( $this->mTitle ); |
2674 | | - |
2675 | | - if ( is_null( $rev ) ) { |
2676 | | - return false; |
2677 | | - } |
2678 | | - |
2679 | | - // Get the article's contents |
2680 | | - $contents = $rev->getText(); |
2681 | | - $blank = false; |
2682 | | - |
2683 | | - // If the page is blank, use the text from the previous revision, |
2684 | | - // which can only be blank if there's a move/import/protect dummy revision involved |
2685 | | - if ( $contents == '' ) { |
2686 | | - $prev = $rev->getPrevious(); |
2687 | | - |
2688 | | - if ( $prev ) { |
2689 | | - $contents = $prev->getText(); |
2690 | | - $blank = true; |
2691 | | - } |
2692 | | - } |
2693 | | - |
2694 | | - // Find out if there was only one contributor |
2695 | | - // Only scan the last 20 revisions |
2696 | | - $res = $dbw->select( 'revision', 'rev_user_text', |
2697 | | - array( 'rev_page' => $this->getID(), $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ), |
2698 | | - __METHOD__, |
2699 | | - array( 'LIMIT' => 20 ) |
2700 | | - ); |
2701 | | - |
2702 | | - if ( $res === false ) { |
2703 | | - // This page has no revisions, which is very weird |
2704 | | - return false; |
2705 | | - } |
2706 | | - |
2707 | | - $hasHistory = ( $res->numRows() > 1 ); |
2708 | | - $row = $dbw->fetchObject( $res ); |
2709 | | - |
2710 | | - if ( $row ) { // $row is false if the only contributor is hidden |
2711 | | - $onlyAuthor = $row->rev_user_text; |
2712 | | - // Try to find a second contributor |
2713 | | - foreach ( $res as $row ) { |
2714 | | - if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999 |
2715 | | - $onlyAuthor = false; |
2716 | | - break; |
2717 | | - } |
2718 | | - } |
2719 | | - } else { |
2720 | | - $onlyAuthor = false; |
2721 | | - } |
2722 | | - |
2723 | | - // Generate the summary with a '$1' placeholder |
2724 | | - if ( $blank ) { |
2725 | | - // The current revision is blank and the one before is also |
2726 | | - // blank. It's just not our lucky day |
2727 | | - $reason = wfMsgForContent( 'exbeforeblank', '$1' ); |
2728 | | - } else { |
2729 | | - if ( $onlyAuthor ) { |
2730 | | - $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor ); |
2731 | | - } else { |
2732 | | - $reason = wfMsgForContent( 'excontent', '$1' ); |
2733 | | - } |
2734 | | - } |
2735 | | - |
2736 | | - if ( $reason == '-' ) { |
2737 | | - // Allow these UI messages to be blanked out cleanly |
2738 | | - return ''; |
2739 | | - } |
2740 | | - |
2741 | | - // Replace newlines with spaces to prevent uglyness |
2742 | | - $contents = preg_replace( "/[\n\r]/", ' ', $contents ); |
2743 | | - // Calculate the maximum amount of chars to get |
2744 | | - // Max content length = max comment length - length of the comment (excl. $1) |
2745 | | - $maxLength = 255 - ( strlen( $reason ) - 2 ); |
2746 | | - $contents = $wgContLang->truncate( $contents, $maxLength ); |
2747 | | - // Remove possible unfinished links |
2748 | | - $contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents ); |
2749 | | - // Now replace the '$1' placeholder |
2750 | | - $reason = str_replace( '$1', $contents, $reason ); |
2751 | | - |
2752 | | - return $reason; |
| 2616 | + return DeleteAction::getAutoReason( $this ); |
2753 | 2617 | } |
2754 | 2618 | |
2755 | 2619 | |
2756 | 2620 | /* |
2757 | 2621 | * UI entry point for page deletion |
| 2622 | + * @deprecated since 1.18 |
2758 | 2623 | */ |
2759 | 2624 | public function delete() { |
2760 | | - global $wgOut, $wgRequest; |
2761 | | - |
2762 | | - $confirm = $wgRequest->wasPosted() && |
2763 | | - $wgOut->getUser()->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ); |
2764 | | - |
2765 | | - $this->DeleteReasonList = $wgRequest->getText( 'wpDeleteReasonList', 'other' ); |
2766 | | - $this->DeleteReason = $wgRequest->getText( 'wpReason' ); |
2767 | | - |
2768 | | - $reason = $this->DeleteReasonList; |
2769 | | - |
2770 | | - if ( $reason != 'other' && $this->DeleteReason != '' ) { |
2771 | | - // Entry from drop down menu + additional comment |
2772 | | - $reason .= wfMsgForContent( 'colon-separator' ) . $this->DeleteReason; |
2773 | | - } elseif ( $reason == 'other' ) { |
2774 | | - $reason = $this->DeleteReason; |
2775 | | - } |
2776 | | - |
2777 | | - # Flag to hide all contents of the archived revisions |
2778 | | - $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgOut->getUser()->isAllowed( 'suppressrevision' ); |
2779 | | - |
2780 | | - # This code desperately needs to be totally rewritten |
2781 | | - |
2782 | | - # Read-only check... |
2783 | | - if ( wfReadOnly() ) { |
2784 | | - $wgOut->readOnlyPage(); |
2785 | | - |
2786 | | - return; |
2787 | | - } |
2788 | | - |
2789 | | - # Check permissions |
2790 | | - $permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $wgOut->getUser() ); |
2791 | | - |
2792 | | - if ( count( $permission_errors ) > 0 ) { |
2793 | | - $wgOut->showPermissionsErrorPage( $permission_errors ); |
2794 | | - |
2795 | | - return; |
2796 | | - } |
2797 | | - |
2798 | | - $wgOut->setPagetitle( wfMsg( 'delete-confirm', $this->mTitle->getPrefixedText() ) ); |
2799 | | - |
2800 | | - # Better double-check that it hasn't been deleted yet! |
2801 | | - $dbw = wfGetDB( DB_MASTER ); |
2802 | | - $conds = $this->mTitle->pageCond(); |
2803 | | - $latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ ); |
2804 | | - if ( $latest === false ) { |
2805 | | - $wgOut->showFatalError( |
2806 | | - Html::rawElement( |
2807 | | - 'div', |
2808 | | - array( 'class' => 'error mw-error-cannotdelete' ), |
2809 | | - wfMsgExt( 'cannotdelete', array( 'parse' ), $this->mTitle->getPrefixedText() ) |
2810 | | - ) |
2811 | | - ); |
2812 | | - $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) ); |
2813 | | - LogEventsList::showLogExtract( |
2814 | | - $wgOut, |
2815 | | - 'delete', |
2816 | | - $this->mTitle->getPrefixedText() |
2817 | | - ); |
2818 | | - |
2819 | | - return; |
2820 | | - } |
2821 | | - |
2822 | | - # Hack for big sites |
2823 | | - $bigHistory = $this->isBigDeletion(); |
2824 | | - if ( $bigHistory && !$this->mTitle->userCan( 'bigdelete' ) ) { |
2825 | | - global $wgLang, $wgDeleteRevisionsLimit; |
2826 | | - |
2827 | | - $wgOut->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n", |
2828 | | - array( 'delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) ); |
2829 | | - |
2830 | | - return; |
2831 | | - } |
2832 | | - |
2833 | | - if ( $confirm ) { |
2834 | | - $this->doDelete( $reason, $suppress ); |
2835 | | - |
2836 | | - if ( $wgRequest->getCheck( 'wpWatch' ) && $wgOut->getUser()->isLoggedIn() ) { |
2837 | | - $this->doWatch(); |
2838 | | - } elseif ( $this->mTitle->userIsWatching() ) { |
2839 | | - $this->doUnwatch(); |
2840 | | - } |
2841 | | - |
2842 | | - return; |
2843 | | - } |
2844 | | - |
2845 | | - // Generate deletion reason |
2846 | | - $hasHistory = false; |
2847 | | - if ( !$reason ) { |
2848 | | - $reason = $this->generateReason( $hasHistory ); |
2849 | | - } |
2850 | | - |
2851 | | - // If the page has a history, insert a warning |
2852 | | - if ( $hasHistory && !$confirm ) { |
2853 | | - global $wgLang; |
2854 | | - |
2855 | | - $skin = $wgOut->getSkin(); |
2856 | | - $revisions = $this->estimateRevisionCount(); |
2857 | | - //FIXME: lego |
2858 | | - $wgOut->addHTML( '<strong class="mw-delete-warning-revisions">' . |
2859 | | - wfMsgExt( 'historywarning', array( 'parseinline' ), $wgLang->formatNum( $revisions ) ) . |
2860 | | - wfMsgHtml( 'word-separator' ) . $skin->link( $this->mTitle, |
2861 | | - wfMsgHtml( 'history' ), |
2862 | | - array( 'rel' => 'archives' ), |
2863 | | - array( 'action' => 'history' ) ) . |
2864 | | - '</strong>' |
2865 | | - ); |
2866 | | - |
2867 | | - if ( $bigHistory ) { |
2868 | | - global $wgDeleteRevisionsLimit; |
2869 | | - $wgOut->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n", |
2870 | | - array( 'delete-warning-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) ); |
2871 | | - } |
2872 | | - } |
2873 | | - |
2874 | | - return $this->confirmDelete( $reason ); |
| 2625 | + return Action::factory( 'delete', $this )->show(); |
2875 | 2626 | } |
2876 | 2627 | |
2877 | 2628 | /** |
2878 | 2629 | * @return bool whether or not the page surpasses $wgDeleteRevisionsLimit revisions |
| 2630 | + * @deprecated since 1.18 |
2879 | 2631 | */ |
2880 | 2632 | public function isBigDeletion() { |
2881 | 2633 | global $wgDeleteRevisionsLimit; |
2882 | | - |
2883 | | - if ( $wgDeleteRevisionsLimit ) { |
2884 | | - $revCount = $this->estimateRevisionCount(); |
2885 | | - |
2886 | | - return $revCount > $wgDeleteRevisionsLimit; |
2887 | | - } |
2888 | | - |
2889 | | - return false; |
| 2634 | + return $wgDeleteRevisionsLimit && $this->estimateRevisionCount() > $wgDeleteRevisionsLimit; |
2890 | 2635 | } |
2891 | 2636 | |
2892 | 2637 | /** |
— | — | @@ -2954,150 +2699,19 @@ |
2955 | 2700 | } |
2956 | 2701 | |
2957 | 2702 | /** |
2958 | | - * Output deletion confirmation dialog |
2959 | | - * FIXME: Move to another file? |
2960 | | - * @param $reason String: prefilled reason |
2961 | | - */ |
2962 | | - public function confirmDelete( $reason ) { |
2963 | | - global $wgOut; |
2964 | | - |
2965 | | - wfDebug( "Article::confirmDelete\n" ); |
2966 | | - |
2967 | | - $deleteBackLink = $wgOut->getSkin()->linkKnown( $this->mTitle ); |
2968 | | - $wgOut->setSubtitle( wfMsgHtml( 'delete-backlink', $deleteBackLink ) ); |
2969 | | - $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
2970 | | - $wgOut->addWikiMsg( 'confirmdeletetext' ); |
2971 | | - |
2972 | | - wfRunHooks( 'ArticleConfirmDelete', array( $this, $wgOut, &$reason ) ); |
2973 | | - |
2974 | | - if ( $wgOut->getUser()->isAllowed( 'suppressrevision' ) ) { |
2975 | | - $suppress = "<tr id=\"wpDeleteSuppressRow\"> |
2976 | | - <td></td> |
2977 | | - <td class='mw-input'><strong>" . |
2978 | | - Xml::checkLabel( wfMsg( 'revdelete-suppress' ), |
2979 | | - 'wpSuppress', 'wpSuppress', false, array( 'tabindex' => '4' ) ) . |
2980 | | - "</strong></td> |
2981 | | - </tr>"; |
2982 | | - } else { |
2983 | | - $suppress = ''; |
2984 | | - } |
2985 | | - $checkWatch = $wgOut->getUser()->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching(); |
2986 | | - |
2987 | | - $form = Xml::openElement( 'form', array( 'method' => 'post', |
2988 | | - 'action' => $this->mTitle->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) . |
2989 | | - Xml::openElement( 'fieldset', array( 'id' => 'mw-delete-table' ) ) . |
2990 | | - Xml::tags( 'legend', null, wfMsgExt( 'delete-legend', array( 'parsemag', 'escapenoentities' ) ) ) . |
2991 | | - Xml::openElement( 'table', array( 'id' => 'mw-deleteconfirm-table' ) ) . |
2992 | | - "<tr id=\"wpDeleteReasonListRow\"> |
2993 | | - <td class='mw-label'>" . |
2994 | | - Xml::label( wfMsg( 'deletecomment' ), 'wpDeleteReasonList' ) . |
2995 | | - "</td> |
2996 | | - <td class='mw-input'>" . |
2997 | | - Xml::listDropDown( 'wpDeleteReasonList', |
2998 | | - wfMsgForContent( 'deletereason-dropdown' ), |
2999 | | - wfMsgForContent( 'deletereasonotherlist' ), '', 'wpReasonDropDown', 1 ) . |
3000 | | - "</td> |
3001 | | - </tr> |
3002 | | - <tr id=\"wpDeleteReasonRow\"> |
3003 | | - <td class='mw-label'>" . |
3004 | | - Xml::label( wfMsg( 'deleteotherreason' ), 'wpReason' ) . |
3005 | | - "</td> |
3006 | | - <td class='mw-input'>" . |
3007 | | - Html::input( 'wpReason', $reason, 'text', array( |
3008 | | - 'size' => '60', |
3009 | | - 'maxlength' => '255', |
3010 | | - 'tabindex' => '2', |
3011 | | - 'id' => 'wpReason', |
3012 | | - 'autofocus' |
3013 | | - ) ) . |
3014 | | - "</td> |
3015 | | - </tr>"; |
3016 | | - |
3017 | | - # Disallow watching if user is not logged in |
3018 | | - if ( $wgOut->getUser()->isLoggedIn() ) { |
3019 | | - $form .= " |
3020 | | - <tr> |
3021 | | - <td></td> |
3022 | | - <td class='mw-input'>" . |
3023 | | - Xml::checkLabel( wfMsg( 'watchthis' ), |
3024 | | - 'wpWatch', 'wpWatch', $checkWatch, array( 'tabindex' => '3' ) ) . |
3025 | | - "</td> |
3026 | | - </tr>"; |
3027 | | - } |
3028 | | - |
3029 | | - $form .= " |
3030 | | - $suppress |
3031 | | - <tr> |
3032 | | - <td></td> |
3033 | | - <td class='mw-submit'>" . |
3034 | | - Xml::submitButton( wfMsg( 'deletepage' ), |
3035 | | - array( 'name' => 'wpConfirmB', 'id' => 'wpConfirmB', 'tabindex' => '5' ) ) . |
3036 | | - "</td> |
3037 | | - </tr>" . |
3038 | | - Xml::closeElement( 'table' ) . |
3039 | | - Xml::closeElement( 'fieldset' ) . |
3040 | | - Html::hidden( 'wpEditToken', $wgOut->getUser()->editToken() ) . |
3041 | | - Xml::closeElement( 'form' ); |
3042 | | - |
3043 | | - if ( $wgOut->getUser()->isAllowed( 'editinterface' ) ) { |
3044 | | - $skin = $wgOut->getSkin(); |
3045 | | - $title = Title::makeTitle( NS_MEDIAWIKI, 'Deletereason-dropdown' ); |
3046 | | - $link = $skin->link( |
3047 | | - $title, |
3048 | | - wfMsgHtml( 'delete-edit-reasonlist' ), |
3049 | | - array(), |
3050 | | - array( 'action' => 'edit' ) |
3051 | | - ); |
3052 | | - $form .= '<p class="mw-delete-editreasons">' . $link . '</p>'; |
3053 | | - } |
3054 | | - |
3055 | | - $wgOut->addHTML( $form ); |
3056 | | - $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) ); |
3057 | | - LogEventsList::showLogExtract( $wgOut, 'delete', |
3058 | | - $this->mTitle->getPrefixedText() |
3059 | | - ); |
3060 | | - } |
3061 | | - |
3062 | | - /** |
3063 | 2703 | * Perform a deletion and output success or failure messages |
| 2704 | + * @deprecated since 1.18 |
3064 | 2705 | */ |
3065 | 2706 | public function doDelete( $reason, $suppress = false ) { |
3066 | | - global $wgOut; |
3067 | | - |
3068 | | - $id = $this->mTitle->getArticleID( Title::GAID_FOR_UPDATE ); |
3069 | | - |
3070 | | - $error = ''; |
3071 | | - if ( $this->doDeleteArticle( $reason, $suppress, $id, $error ) ) { |
3072 | | - $deleted = $this->mTitle->getPrefixedText(); |
3073 | | - |
3074 | | - $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) ); |
3075 | | - $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
3076 | | - |
3077 | | - $loglink = '[[Special:Log/delete|' . wfMsgNoTrans( 'deletionlog' ) . ']]'; |
3078 | | - |
3079 | | - $wgOut->addWikiMsg( 'deletedtext', $deleted, $loglink ); |
3080 | | - $wgOut->returnToMain( false ); |
3081 | | - } else { |
3082 | | - if ( $error == '' ) { |
3083 | | - $wgOut->showFatalError( |
3084 | | - Html::rawElement( |
3085 | | - 'div', |
3086 | | - array( 'class' => 'error mw-error-cannotdelete' ), |
3087 | | - wfMsgExt( 'cannotdelete', array( 'parse' ), $this->mTitle->getPrefixedText() ) |
3088 | | - ) |
3089 | | - ); |
3090 | | - |
3091 | | - $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) ); |
3092 | | - |
3093 | | - LogEventsList::showLogExtract( |
3094 | | - $wgOut, |
3095 | | - 'delete', |
3096 | | - $this->mTitle->getPrefixedText() |
3097 | | - ); |
3098 | | - } else { |
3099 | | - $wgOut->showFatalError( $error ); |
3100 | | - } |
3101 | | - } |
| 2707 | + return DeleteAction::doDeleteArticle( |
| 2708 | + $this, |
| 2709 | + $this->getContext(), |
| 2710 | + array( |
| 2711 | + 'Suppress' => $suppress !== false, |
| 2712 | + 'Reason' => $reason, |
| 2713 | + ), |
| 2714 | + true |
| 2715 | + ); |
3102 | 2716 | } |
3103 | 2717 | |
3104 | 2718 | /** |
— | — | @@ -3113,143 +2727,19 @@ |
3114 | 2728 | * @param $id int article ID |
3115 | 2729 | * @param $commit boolean defaults to true, triggers transaction end |
3116 | 2730 | * @return boolean true if successful |
| 2731 | + * |
| 2732 | + * @deprecated since 1.18 |
3117 | 2733 | */ |
3118 | 2734 | public function doDeleteArticle( $reason, $suppress = false, $id = 0, $commit = true, &$error = '' ) { |
3119 | | - global $wgDeferredUpdateList, $wgUseTrackbacks; |
3120 | | - global $wgUser; |
3121 | | - |
3122 | | - wfDebug( __METHOD__ . "\n" ); |
3123 | | - |
3124 | | - if ( ! wfRunHooks( 'ArticleDelete', array( &$this, &$wgUser, &$reason, &$error ) ) ) { |
3125 | | - return false; |
3126 | | - } |
3127 | | - $dbw = wfGetDB( DB_MASTER ); |
3128 | | - $t = $this->mTitle->getDBkey(); |
3129 | | - $id = $id ? $id : $this->mTitle->getArticleID( Title::GAID_FOR_UPDATE ); |
3130 | | - |
3131 | | - if ( $t === '' || $id == 0 ) { |
3132 | | - return false; |
3133 | | - } |
3134 | | - |
3135 | | - $u = new SiteStatsUpdate( 0, 1, - (int)$this->isCountable( $this->getRawText() ), -1 ); |
3136 | | - array_push( $wgDeferredUpdateList, $u ); |
3137 | | - |
3138 | | - // Bitfields to further suppress the content |
3139 | | - if ( $suppress ) { |
3140 | | - $bitfield = 0; |
3141 | | - // This should be 15... |
3142 | | - $bitfield |= Revision::DELETED_TEXT; |
3143 | | - $bitfield |= Revision::DELETED_COMMENT; |
3144 | | - $bitfield |= Revision::DELETED_USER; |
3145 | | - $bitfield |= Revision::DELETED_RESTRICTED; |
3146 | | - } else { |
3147 | | - $bitfield = 'rev_deleted'; |
3148 | | - } |
3149 | | - |
3150 | | - $dbw->begin(); |
3151 | | - // For now, shunt the revision data into the archive table. |
3152 | | - // Text is *not* removed from the text table; bulk storage |
3153 | | - // is left intact to avoid breaking block-compression or |
3154 | | - // immutable storage schemes. |
3155 | | - // |
3156 | | - // For backwards compatibility, note that some older archive |
3157 | | - // table entries will have ar_text and ar_flags fields still. |
3158 | | - // |
3159 | | - // In the future, we may keep revisions and mark them with |
3160 | | - // the rev_deleted field, which is reserved for this purpose. |
3161 | | - $dbw->insertSelect( 'archive', array( 'page', 'revision' ), |
| 2735 | + return DeleteAction::doDeleteArticle( |
| 2736 | + $this, |
| 2737 | + $this->getContext(), |
3162 | 2738 | array( |
3163 | | - 'ar_namespace' => 'page_namespace', |
3164 | | - 'ar_title' => 'page_title', |
3165 | | - 'ar_comment' => 'rev_comment', |
3166 | | - 'ar_user' => 'rev_user', |
3167 | | - 'ar_user_text' => 'rev_user_text', |
3168 | | - 'ar_timestamp' => 'rev_timestamp', |
3169 | | - 'ar_minor_edit' => 'rev_minor_edit', |
3170 | | - 'ar_rev_id' => 'rev_id', |
3171 | | - 'ar_text_id' => 'rev_text_id', |
3172 | | - 'ar_text' => '\'\'', // Be explicit to appease |
3173 | | - 'ar_flags' => '\'\'', // MySQL's "strict mode"... |
3174 | | - 'ar_len' => 'rev_len', |
3175 | | - 'ar_page_id' => 'page_id', |
3176 | | - 'ar_deleted' => $bitfield |
3177 | | - ), array( |
3178 | | - 'page_id' => $id, |
3179 | | - 'page_id = rev_page' |
3180 | | - ), __METHOD__ |
| 2739 | + 'Suppress' => $suppress !== false, |
| 2740 | + 'Reason' => $reason, |
| 2741 | + ), |
| 2742 | + $commit |
3181 | 2743 | ); |
3182 | | - |
3183 | | - # Delete restrictions for it |
3184 | | - $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ ); |
3185 | | - |
3186 | | - # Now that it's safely backed up, delete it |
3187 | | - $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ ); |
3188 | | - $ok = ( $dbw->affectedRows() > 0 ); // getArticleId() uses slave, could be laggy |
3189 | | - |
3190 | | - if ( !$ok ) { |
3191 | | - $dbw->rollback(); |
3192 | | - return false; |
3193 | | - } |
3194 | | - |
3195 | | - # Fix category table counts |
3196 | | - $cats = array(); |
3197 | | - $res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ ); |
3198 | | - |
3199 | | - foreach ( $res as $row ) { |
3200 | | - $cats [] = $row->cl_to; |
3201 | | - } |
3202 | | - |
3203 | | - $this->updateCategoryCounts( array(), $cats ); |
3204 | | - |
3205 | | - # If using cascading deletes, we can skip some explicit deletes |
3206 | | - if ( !$dbw->cascadingDeletes() ) { |
3207 | | - $dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ ); |
3208 | | - |
3209 | | - if ( $wgUseTrackbacks ) |
3210 | | - $dbw->delete( 'trackbacks', array( 'tb_page' => $id ), __METHOD__ ); |
3211 | | - |
3212 | | - # Delete outgoing links |
3213 | | - $dbw->delete( 'pagelinks', array( 'pl_from' => $id ) ); |
3214 | | - $dbw->delete( 'imagelinks', array( 'il_from' => $id ) ); |
3215 | | - $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) ); |
3216 | | - $dbw->delete( 'templatelinks', array( 'tl_from' => $id ) ); |
3217 | | - $dbw->delete( 'externallinks', array( 'el_from' => $id ) ); |
3218 | | - $dbw->delete( 'langlinks', array( 'll_from' => $id ) ); |
3219 | | - $dbw->delete( 'redirect', array( 'rd_from' => $id ) ); |
3220 | | - } |
3221 | | - |
3222 | | - # If using cleanup triggers, we can skip some manual deletes |
3223 | | - if ( !$dbw->cleanupTriggers() ) { |
3224 | | - # Clean up recentchanges entries... |
3225 | | - $dbw->delete( 'recentchanges', |
3226 | | - array( 'rc_type != ' . RC_LOG, |
3227 | | - 'rc_namespace' => $this->mTitle->getNamespace(), |
3228 | | - 'rc_title' => $this->mTitle->getDBkey() ), |
3229 | | - __METHOD__ ); |
3230 | | - $dbw->delete( 'recentchanges', |
3231 | | - array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ), |
3232 | | - __METHOD__ ); |
3233 | | - } |
3234 | | - |
3235 | | - # Clear caches |
3236 | | - Article::onArticleDelete( $this->mTitle ); |
3237 | | - |
3238 | | - # Clear the cached article id so the interface doesn't act like we exist |
3239 | | - $this->mTitle->resetArticleID( 0 ); |
3240 | | - |
3241 | | - # Log the deletion, if the page was suppressed, log it at Oversight instead |
3242 | | - $logtype = $suppress ? 'suppress' : 'delete'; |
3243 | | - $log = new LogPage( $logtype ); |
3244 | | - |
3245 | | - # Make sure logging got through |
3246 | | - $log->addEntry( 'delete', $this->mTitle, $reason, array() ); |
3247 | | - |
3248 | | - if ( $commit ) { |
3249 | | - $dbw->commit(); |
3250 | | - } |
3251 | | - |
3252 | | - wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$wgUser, $reason, $id ) ); |
3253 | | - return true; |
3254 | 2744 | } |
3255 | 2745 | |
3256 | 2746 | /** |
Index: trunk/phase3/includes/Setup.php |
— | — | @@ -270,6 +270,14 @@ |
271 | 271 | $wgHiddenPrefs[] = 'enotifminoredits'; |
272 | 272 | } |
273 | 273 | |
| 274 | +# $wgDisabledActions is deprecated as of 1.18 |
| 275 | +foreach( $wgDisabledActions as $action ){ |
| 276 | + $wgActions[$action] = false; |
| 277 | +} |
| 278 | +if( !$wgAllowPageInfo ){ |
| 279 | + $wgActions['info'] = false; |
| 280 | +} |
| 281 | + |
274 | 282 | if ( !$wgHtml5Version && $wgHtml5 && $wgAllowRdfaAttributes ) { |
275 | 283 | # see http://www.w3.org/TR/rdfa-in-html/#document-conformance |
276 | 284 | if ( $wgMimeType == 'application/xhtml+xml' ) { |
Index: trunk/phase3/includes/EditPage.php |
— | — | @@ -1153,9 +1153,9 @@ |
1154 | 1154 | $dbw = wfGetDB( DB_MASTER ); |
1155 | 1155 | $dbw->begin(); |
1156 | 1156 | if ( $this->watchthis ) { |
1157 | | - $this->mArticle->doWatch(); |
| 1157 | + Action::factory( 'watch', $this->mArticle )->execute(); |
1158 | 1158 | } else { |
1159 | | - $this->mArticle->doUnwatch(); |
| 1159 | + Action::factory( 'watch', $this->mArticle )->execute(); |
1160 | 1160 | } |
1161 | 1161 | $dbw->commit(); |
1162 | 1162 | } |
Index: trunk/phase3/includes/actions/CreditsAction.php |
— | — | @@ -0,0 +1,237 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Formats credits for articles |
| 5 | + * |
| 6 | + * Copyright 2004, Evan Prodromou <evan@wikitravel.org>. |
| 7 | + * |
| 8 | + * This program is free software; you can redistribute it and/or modify |
| 9 | + * it under the terms of the GNU General Public License as published by |
| 10 | + * the Free Software Foundation; either version 2 of the License, or |
| 11 | + * (at your option) any later version. |
| 12 | + * |
| 13 | + * This program is distributed in the hope that it will be useful, |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | + * GNU General Public License for more details. |
| 17 | + * |
| 18 | + * You should have received a copy of the GNU General Public License |
| 19 | + * along with this program; if not, write to the Free Software |
| 20 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| 21 | + * |
| 22 | + * @file |
| 23 | + * @ingroup Actions |
| 24 | + * @author <evan@wikitravel.org> |
| 25 | + */ |
| 26 | + |
| 27 | +class CreditsAction extends FormlessAction { |
| 28 | + |
| 29 | + public function getName(){ |
| 30 | + return 'credits'; |
| 31 | + } |
| 32 | + |
| 33 | + public function getRestriction(){ |
| 34 | + return null; |
| 35 | + } |
| 36 | + |
| 37 | + /** |
| 38 | + * This is largely cadged from PageHistory::history |
| 39 | + */ |
| 40 | + public function onView() { |
| 41 | + wfProfileIn( __METHOD__ ); |
| 42 | + |
| 43 | + if ( $this->page->getID() == 0 ) { |
| 44 | + $s = wfMsg( 'nocredits' ); |
| 45 | + } else { |
| 46 | + $s = $this->getCredits( -1 ); |
| 47 | + } |
| 48 | + |
| 49 | + wfProfileOut( __METHOD__ ); |
| 50 | + |
| 51 | + return $s; |
| 52 | + } |
| 53 | + |
| 54 | + /** |
| 55 | + * Get a list of contributors of $article |
| 56 | + * @param $article Article object |
| 57 | + * @param $cnt Int: maximum list of contributors to show |
| 58 | + * @param $showIfMax Bool: whether to contributors if there more than $cnt |
| 59 | + * @return String: html |
| 60 | + */ |
| 61 | + protected function getCredits( $cnt, $showIfMax = true ) { |
| 62 | + wfProfileIn( __METHOD__ ); |
| 63 | + $s = ''; |
| 64 | + |
| 65 | + if ( isset( $cnt ) && $cnt != 0 ) { |
| 66 | + $s = self::getAuthor( $this->page ); |
| 67 | + if ( $cnt > 1 || $cnt < 0 ) { |
| 68 | + $s .= ' ' . $this->getContributors( $cnt - 1, $showIfMax ); |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + wfProfileOut( __METHOD__ ); |
| 73 | + return $s; |
| 74 | + } |
| 75 | + |
| 76 | + /** |
| 77 | + * Get the last author with the last modification time |
| 78 | + * @param $article Article object |
| 79 | + */ |
| 80 | + protected static function getAuthor( Article $article ) { |
| 81 | + global $wgLang; |
| 82 | + |
| 83 | + $user = User::newFromId( $article->getUser() ); |
| 84 | + |
| 85 | + $timestamp = $article->getTimestamp(); |
| 86 | + if ( $timestamp ) { |
| 87 | + $d = $wgLang->date( $article->getTimestamp(), true ); |
| 88 | + $t = $wgLang->time( $article->getTimestamp(), true ); |
| 89 | + } else { |
| 90 | + $d = ''; |
| 91 | + $t = ''; |
| 92 | + } |
| 93 | + return wfMsgExt( 'lastmodifiedatby', 'parsemag', $d, $t, self::userLink( $user ), $user->getName() ); |
| 94 | + } |
| 95 | + |
| 96 | + /** |
| 97 | + * Get a list of contributors of $article |
| 98 | + * @param $article Article object |
| 99 | + * @param $cnt Int: maximum list of contributors to show |
| 100 | + * @param $showIfMax Bool: whether to contributors if there more than $cnt |
| 101 | + * @return String: html |
| 102 | + */ |
| 103 | + protected function getContributors( $cnt, $showIfMax ) { |
| 104 | + global $wgLang, $wgHiddenPrefs; |
| 105 | + |
| 106 | + $contributors = $this->page->getContributors(); |
| 107 | + |
| 108 | + $others_link = false; |
| 109 | + |
| 110 | + # Hmm... too many to fit! |
| 111 | + if ( $cnt > 0 && $contributors->count() > $cnt ) { |
| 112 | + $others_link = $this->othersLink(); |
| 113 | + if ( !$showIfMax ) |
| 114 | + return wfMsgExt( 'othercontribs', 'parsemag', $others_link, $contributors->count() ); |
| 115 | + } |
| 116 | + |
| 117 | + $real_names = array(); |
| 118 | + $user_names = array(); |
| 119 | + $anon_ips = array(); |
| 120 | + |
| 121 | + # Sift for real versus user names |
| 122 | + foreach ( $contributors as $user ) { |
| 123 | + $cnt--; |
| 124 | + if ( $user->isLoggedIn() ) { |
| 125 | + $link = self::link( $user ); |
| 126 | + if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) { |
| 127 | + $real_names[] = $link; |
| 128 | + } else { |
| 129 | + $user_names[] = $link; |
| 130 | + } |
| 131 | + } else { |
| 132 | + $anon_ips[] = self::link( $user ); |
| 133 | + } |
| 134 | + |
| 135 | + if ( $cnt == 0 ) { |
| 136 | + break; |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + if ( count( $real_names ) ) { |
| 141 | + $real = $wgLang->listToText( $real_names ); |
| 142 | + } else { |
| 143 | + $real = false; |
| 144 | + } |
| 145 | + |
| 146 | + # "ThisSite user(s) A, B and C" |
| 147 | + if ( count( $user_names ) ) { |
| 148 | + $user = wfMsgExt( |
| 149 | + 'siteusers', |
| 150 | + 'parsemag', |
| 151 | + $wgLang->listToText( $user_names ), count( $user_names ) |
| 152 | + ); |
| 153 | + } else { |
| 154 | + $user = false; |
| 155 | + } |
| 156 | + |
| 157 | + if ( count( $anon_ips ) ) { |
| 158 | + $anon = wfMsgExt( |
| 159 | + 'anonusers', |
| 160 | + 'parsemag', |
| 161 | + $wgLang->listToText( $anon_ips ), count( $anon_ips ) |
| 162 | + ); |
| 163 | + } else { |
| 164 | + $anon = false; |
| 165 | + } |
| 166 | + |
| 167 | + # This is the big list, all mooshed together. We sift for blank strings |
| 168 | + $fulllist = array(); |
| 169 | + foreach ( array( $real, $user, $anon, $others_link ) as $s ) { |
| 170 | + if ( $s ) { |
| 171 | + array_push( $fulllist, $s ); |
| 172 | + } |
| 173 | + } |
| 174 | + |
| 175 | + # Make the list into text... |
| 176 | + $creds = $wgLang->listToText( $fulllist ); |
| 177 | + |
| 178 | + # "Based on work by ..." |
| 179 | + return strlen( $creds ) |
| 180 | + ? wfMsgExt( 'othercontribs', 'parsemag', $creds, count( $fulllist ) ) |
| 181 | + : ''; |
| 182 | + } |
| 183 | + |
| 184 | + /** |
| 185 | + * Get a link to $user's user page |
| 186 | + * @param $user User object |
| 187 | + * @return String: html |
| 188 | + */ |
| 189 | + protected static function link( User $user ) { |
| 190 | + global $wgUser, $wgHiddenPrefs; |
| 191 | + if ( !in_array( 'realname', $wgHiddenPrefs ) && !$user->isAnon() ) { |
| 192 | + $real = $user->getRealName(); |
| 193 | + } else { |
| 194 | + $real = false; |
| 195 | + } |
| 196 | + |
| 197 | + $page = $user->isAnon() |
| 198 | + ? SpecialPage::getTitleFor( 'Contributions', $user->getName() ) |
| 199 | + : $user->getUserPage(); |
| 200 | + |
| 201 | + return Linker::link( $page, htmlspecialchars( $real ? $real : $user->getName() ) ); |
| 202 | + } |
| 203 | + |
| 204 | + /** |
| 205 | + * Get a link to $user's user page |
| 206 | + * @param $user User object |
| 207 | + * @return String: html |
| 208 | + */ |
| 209 | + protected static function userLink( User $user ) { |
| 210 | + $link = self::link( $user ); |
| 211 | + if ( $user->isAnon() ) { |
| 212 | + return wfMsgExt( 'anonuser', array( 'parseinline', 'replaceafter' ), $link ); |
| 213 | + } else { |
| 214 | + global $wgHiddenPrefs; |
| 215 | + if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) { |
| 216 | + return $link; |
| 217 | + } else { |
| 218 | + return wfMsgExt( 'siteuser', 'parsemag', $link, $user->getName() ); |
| 219 | + } |
| 220 | + } |
| 221 | + } |
| 222 | + |
| 223 | + /** |
| 224 | + * Get a link to action=credits of $article page |
| 225 | + * @param $article Article object |
| 226 | + * @return String: html |
| 227 | + */ |
| 228 | + protected function othersLink() { |
| 229 | + global $wgUser; |
| 230 | + return Linker::link( |
| 231 | + $this->getTitle(), |
| 232 | + wfMsgHtml( 'others' ), |
| 233 | + array(), |
| 234 | + array( 'action' => 'credits' ), |
| 235 | + array( 'known' ) |
| 236 | + ); |
| 237 | + } |
| 238 | +} |
Property changes on: trunk/phase3/includes/actions/CreditsAction.php |
___________________________________________________________________ |
Added: svn:keywords |
1 | 239 | + Author Date Id Revision |
Added: svn:eol-style |
2 | 240 | + native |
Index: trunk/phase3/includes/actions/DeleteAction.php |
— | — | @@ -0,0 +1,476 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Performs the watch and unwatch actions on a page |
| 5 | + * |
| 6 | + * This program is free software; you can redistribute it and/or modify |
| 7 | + * it under the terms of the GNU General Public License as published by |
| 8 | + * the Free Software Foundation; either version 2 of the License, or |
| 9 | + * (at your option) any later version. |
| 10 | + * |
| 11 | + * This program is distributed in the hope that it will be useful, |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | + * GNU General Public License for more details. |
| 15 | + * |
| 16 | + * You should have received a copy of the GNU General Public License |
| 17 | + * along with this program; if not, write to the Free Software |
| 18 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| 19 | + * |
| 20 | + * @file |
| 21 | + * @ingroup Actions |
| 22 | + */ |
| 23 | + |
| 24 | +class DeleteAction extends Action { |
| 25 | + |
| 26 | + public function getName(){ |
| 27 | + return 'delete'; |
| 28 | + } |
| 29 | + |
| 30 | + public function getRestriction(){ |
| 31 | + return 'delete'; |
| 32 | + } |
| 33 | + |
| 34 | + protected function getDescription(){ |
| 35 | + return wfMsg( 'delete-confirm', $this->getTitle()->getPrefixedText() ); |
| 36 | + } |
| 37 | + |
| 38 | + /** |
| 39 | + * Check that the deletion can be executed. In addition to checking the user permissions, |
| 40 | + * check that the page is not too big and has not already been deleted. |
| 41 | + * @throws ErrorPageError |
| 42 | + * @see Action::checkCanExecute |
| 43 | + */ |
| 44 | + protected function checkCanExecute( User $user ){ |
| 45 | + |
| 46 | + // Check that the article hasn't already been deleted |
| 47 | + $dbw = wfGetDB( DB_MASTER ); |
| 48 | + $conds = $this->getTitle()->pageCond(); |
| 49 | + $latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ ); |
| 50 | + if ( $latest === false ) { |
| 51 | + // Get the deletion log |
| 52 | + $log = ''; |
| 53 | + LogEventsList::showLogExtract( |
| 54 | + $log, |
| 55 | + 'delete', |
| 56 | + $this->getTitle()->getPrefixedText() |
| 57 | + ); |
| 58 | + |
| 59 | + $msg = new Message( 'cannotdelete' ); |
| 60 | + $msg->params( $this->getTitle()->getPrefixedText() ); // This parameter is parsed |
| 61 | + $msg->rawParams( $log ); // This is not |
| 62 | + |
| 63 | + throw new ErrorPageError( 'internalerror', $msg ); |
| 64 | + } |
| 65 | + |
| 66 | + // Limit deletions of big pages |
| 67 | + $bigHistory = $this->isBigDeletion(); |
| 68 | + if ( $bigHistory && !$user->isAllowed( 'bigdelete' ) ) { |
| 69 | + global $wgDeleteRevisionsLimit; |
| 70 | + throw new ErrorPageError( |
| 71 | + 'internalerror', |
| 72 | + 'delete-toobig', |
| 73 | + $this->getContext()->lang->formatNum( $wgDeleteRevisionsLimit ) |
| 74 | + ); |
| 75 | + } |
| 76 | + |
| 77 | + return parent::checkCanExecute( $user ); |
| 78 | + } |
| 79 | + |
| 80 | + protected function getFormFields(){ |
| 81 | + // TODO: add more useful things here? |
| 82 | + $infoText = Html::rawElement( |
| 83 | + 'strong', |
| 84 | + array(), |
| 85 | + Linker::link( $this->getTitle(), $this->getTitle()->getText() ) |
| 86 | + ); |
| 87 | + |
| 88 | + $arr = array( |
| 89 | + 'Page' => array( |
| 90 | + 'type' => 'info', |
| 91 | + 'raw' => true, |
| 92 | + 'default' => $infoText, |
| 93 | + ), |
| 94 | + 'Reason' => array( |
| 95 | + 'type' => 'selectandother', |
| 96 | + 'label-message' => 'deletecomment', |
| 97 | + 'options-message' => 'deletereason-dropdown', |
| 98 | + 'size' => '60', |
| 99 | + 'maxlength' => '255', |
| 100 | + 'default' => self::getAutoReason( $this->page), |
| 101 | + ), |
| 102 | + ); |
| 103 | + |
| 104 | + if( $this->getUser()->isLoggedIn() ){ |
| 105 | + $arr['Watch'] = array( |
| 106 | + 'type' => 'check', |
| 107 | + 'label-message' => 'watchthis', |
| 108 | + 'default' => $this->getUser()->getBoolOption( 'watchdeletion' ) || $this->getTitle()->userIsWatching() |
| 109 | + ); |
| 110 | + } |
| 111 | + |
| 112 | + if( $this->getUser()->isAllowed( 'suppressrevision' ) ){ |
| 113 | + $arr['Suppress'] = array( |
| 114 | + 'type' => 'check', |
| 115 | + 'label-message' => 'revdelete-suppress', |
| 116 | + 'default' => false, |
| 117 | + ); |
| 118 | + } |
| 119 | + |
| 120 | + return $arr; |
| 121 | + } |
| 122 | + |
| 123 | + /** |
| 124 | + * Text to go at the top of the form, before the opening fieldset |
| 125 | + * @see Action::preText() |
| 126 | + * @return String |
| 127 | + */ |
| 128 | + protected function preText() { |
| 129 | + |
| 130 | + // If the page has a history, insert a warning |
| 131 | + if ( $this->page->estimateRevisionCount() ) { |
| 132 | + global $wgLang; |
| 133 | + |
| 134 | + $link = Linker::link( |
| 135 | + $this->getTitle(), |
| 136 | + wfMsgHtml( 'history' ), |
| 137 | + array( 'rel' => 'archives' ), |
| 138 | + array( 'action' => 'history' ) |
| 139 | + ); |
| 140 | + |
| 141 | + return Html::rawElement( |
| 142 | + 'strong', |
| 143 | + array( 'class' => 'mw-delete-warning-revisions' ), |
| 144 | + wfMessage( |
| 145 | + 'historywarning', |
| 146 | + $wgLang->formatNum( $this->page->estimateRevisionCount() ) |
| 147 | + )->rawParams( $link )->parse() |
| 148 | + ); |
| 149 | + } |
| 150 | + } |
| 151 | + |
| 152 | + /** |
| 153 | + * Text to go at the bottom of the form, below the closing fieldset |
| 154 | + * @see Action::postText() |
| 155 | + * @return string |
| 156 | + */ |
| 157 | + protected function postText(){ |
| 158 | + $s = ''; |
| 159 | + LogEventsList::showLogExtract( |
| 160 | + $s, |
| 161 | + 'delete', |
| 162 | + $this->getTitle()->getPrefixedText() |
| 163 | + ); |
| 164 | + return Html::element( 'h2', array(), LogPage::logName( 'delete' ) ) . $s; |
| 165 | + } |
| 166 | + |
| 167 | + protected function alterForm( HTMLForm &$form ){ |
| 168 | + $form->setWrapperLegend( wfMsgExt( 'delete-legend', array( 'parsemag', 'escapenoentities' ) ) ); |
| 169 | + |
| 170 | + if ( $this->getUser()->isAllowed( 'editinterface' ) ) { |
| 171 | + $link = Linker::link( |
| 172 | + Title::makeTitle( NS_MEDIAWIKI, 'Deletereason-dropdown' ), |
| 173 | + wfMsgHtml( 'delete-edit-reasonlist' ), |
| 174 | + array(), |
| 175 | + array( 'action' => 'edit' ) |
| 176 | + ); |
| 177 | + $form->addHeaderText( '<p class="mw-delete-editreasons">' . $link . '</p>' ); |
| 178 | + } |
| 179 | + } |
| 180 | + |
| 181 | + /** |
| 182 | + * Function called on form submission. Privilege checks and validation have already been |
| 183 | + * completed by this point; we just need to jump out to the heavy-lifting function, |
| 184 | + * which is implemented as a static method so it can be called from other places |
| 185 | + * TODO: make those other places call $action->execute() properly |
| 186 | + * @see Action::onSubmit() |
| 187 | + * @param $data Array |
| 188 | + * @return Array|Bool |
| 189 | + */ |
| 190 | + public function onSubmit( $data ){ |
| 191 | + $status = self::doDeleteArticle( $this->page, $this->getContext(), $data, true ); |
| 192 | + return $status; |
| 193 | + } |
| 194 | + |
| 195 | + public function onSuccess(){ |
| 196 | + // Watch or unwatch, if requested |
| 197 | + if( $this->getRequest()->getCheck( 'wpWatch' ) && $this->getUser()->isLoggedIn() ) { |
| 198 | + Action::factory( 'watch', $this->page )->execute(); |
| 199 | + } elseif ( $this->getTitle()->userIsWatching() ) { |
| 200 | + Action::factory( 'unwatch', $this->page )->execute(); |
| 201 | + } |
| 202 | + |
| 203 | + $this->getOutput()->setPagetitle( wfMsg( 'actioncomplete' ) ); |
| 204 | + $this->getOutput()->addWikiMsg( |
| 205 | + 'deletedtext', |
| 206 | + $this->getTitle()->getPrefixedText(), |
| 207 | + '[[Special:Log/delete|' . wfMsgNoTrans( 'deletionlog' ) . ']]' |
| 208 | + ); |
| 209 | + $this->getOutput()->returnToMain( false ); |
| 210 | + } |
| 211 | + |
| 212 | + /** |
| 213 | + * @return bool whether or not the page surpasses $wgDeleteRevisionsLimit revisions |
| 214 | + */ |
| 215 | + protected function isBigDeletion() { |
| 216 | + global $wgDeleteRevisionsLimit; |
| 217 | + return $wgDeleteRevisionsLimit && $this->page->estimateRevisionCount() > $wgDeleteRevisionsLimit; |
| 218 | + } |
| 219 | + |
| 220 | + /** |
| 221 | + * Back-end article deletion |
| 222 | + * Deletes the article with database consistency, writes logs, purges caches |
| 223 | + * |
| 224 | + * @param $commit boolean defaults to true, triggers transaction end |
| 225 | + * @return Bool|Array true if successful, error array on failure |
| 226 | + */ |
| 227 | + public static function doDeleteArticle( Article $page, RequestContext $context, array $data, $commit = true ) { |
| 228 | + global $wgDeferredUpdateList, $wgUseTrackbacks; |
| 229 | + |
| 230 | + wfDebug( __METHOD__ . "\n" ); |
| 231 | + |
| 232 | + // The normal syntax from HTMLSelectAndOtherField is for the reason to be in the form |
| 233 | + // 'Reason' => array( <full reason>, <dropdown>, <custom> ), but it's reasonable for other |
| 234 | + // functions to just pass 'Reason' => <reason> |
| 235 | + $data['Reason'] = (array)$data['Reason']; |
| 236 | + |
| 237 | + $error = null; |
| 238 | + if ( !wfRunHooks( 'ArticleDelete', array( &$page, &$context->user, &$data['Reason'][0], &$error ) ) ) { |
| 239 | + return $error; |
| 240 | + } |
| 241 | + |
| 242 | + $title = $page->getTitle(); |
| 243 | + $id = $page->getID( Title::GAID_FOR_UPDATE ); |
| 244 | + |
| 245 | + if ( $title->getDBkey() === '' || $id == 0 ) { |
| 246 | + return false; |
| 247 | + } |
| 248 | + |
| 249 | + $updates = new SiteStatsUpdate( 0, 1, - (int)$page->isCountable( $page->getRawText() ), -1 ); |
| 250 | + array_push( $wgDeferredUpdateList, $updates ); |
| 251 | + |
| 252 | + // Bitfields to further suppress the content |
| 253 | + if ( isset( $data['Suppress'] ) && $data['Suppress'] ) { |
| 254 | + $bitfield = 0; |
| 255 | + // This should be 15... |
| 256 | + $bitfield |= Revision::DELETED_TEXT; |
| 257 | + $bitfield |= Revision::DELETED_COMMENT; |
| 258 | + $bitfield |= Revision::DELETED_USER; |
| 259 | + $bitfield |= Revision::DELETED_RESTRICTED; |
| 260 | + |
| 261 | + $logtype = 'suppress'; |
| 262 | + } else { |
| 263 | + // Otherwise, leave it unchanged |
| 264 | + $bitfield = 'rev_deleted'; |
| 265 | + $logtype = 'delete'; |
| 266 | + } |
| 267 | + |
| 268 | + $dbw = wfGetDB( DB_MASTER ); |
| 269 | + $dbw->begin(); |
| 270 | + // For now, shunt the revision data into the archive table. |
| 271 | + // Text is *not* removed from the text table; bulk storage |
| 272 | + // is left intact to avoid breaking block-compression or |
| 273 | + // immutable storage schemes. |
| 274 | + // |
| 275 | + // For backwards compatibility, note that some older archive |
| 276 | + // table entries will have ar_text and ar_flags fields still. |
| 277 | + // |
| 278 | + // In the future, we may keep revisions and mark them with |
| 279 | + // the rev_deleted field, which is reserved for this purpose. |
| 280 | + $dbw->insertSelect( |
| 281 | + 'archive', |
| 282 | + array( 'page', 'revision' ), |
| 283 | + array( |
| 284 | + 'ar_namespace' => 'page_namespace', |
| 285 | + 'ar_title' => 'page_title', |
| 286 | + 'ar_comment' => 'rev_comment', |
| 287 | + 'ar_user' => 'rev_user', |
| 288 | + 'ar_user_text' => 'rev_user_text', |
| 289 | + 'ar_timestamp' => 'rev_timestamp', |
| 290 | + 'ar_minor_edit' => 'rev_minor_edit', |
| 291 | + 'ar_rev_id' => 'rev_id', |
| 292 | + 'ar_text_id' => 'rev_text_id', |
| 293 | + 'ar_text' => "''", // Be explicit to appease |
| 294 | + 'ar_flags' => "''", // MySQL's "strict mode"... |
| 295 | + 'ar_len' => 'rev_len', |
| 296 | + 'ar_page_id' => 'page_id', |
| 297 | + 'ar_deleted' => $bitfield |
| 298 | + ), |
| 299 | + array( |
| 300 | + 'page_id' => $id, |
| 301 | + 'page_id = rev_page' |
| 302 | + ), |
| 303 | + __METHOD__ |
| 304 | + ); |
| 305 | + |
| 306 | + // Delete restrictions for it |
| 307 | + $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ ); |
| 308 | + |
| 309 | + // Now that it's safely backed up, delete it |
| 310 | + $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ ); |
| 311 | + |
| 312 | + // getArticleId() uses slave, could be laggy |
| 313 | + if ( $dbw->affectedRows() == 0 ) { |
| 314 | + $dbw->rollback(); |
| 315 | + return false; |
| 316 | + } |
| 317 | + |
| 318 | + // Fix category table counts |
| 319 | + $res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ ); |
| 320 | + $cats = array(); |
| 321 | + foreach ( $res as $row ) { |
| 322 | + $cats[] = $row->cl_to; |
| 323 | + } |
| 324 | + $page->updateCategoryCounts( array(), $cats ); |
| 325 | + |
| 326 | + // If using cascading deletes, we can skip some explicit deletes |
| 327 | + if ( !$dbw->cascadingDeletes() ) { |
| 328 | + $dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ ); |
| 329 | + |
| 330 | + if ( $wgUseTrackbacks ){ |
| 331 | + $dbw->delete( 'trackbacks', array( 'tb_page' => $id ), __METHOD__ ); |
| 332 | + } |
| 333 | + |
| 334 | + // Delete outgoing links |
| 335 | + $dbw->delete( 'pagelinks', array( 'pl_from' => $id ) ); |
| 336 | + $dbw->delete( 'imagelinks', array( 'il_from' => $id ) ); |
| 337 | + $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) ); |
| 338 | + $dbw->delete( 'templatelinks', array( 'tl_from' => $id ) ); |
| 339 | + $dbw->delete( 'externallinks', array( 'el_from' => $id ) ); |
| 340 | + $dbw->delete( 'langlinks', array( 'll_from' => $id ) ); |
| 341 | + $dbw->delete( 'redirect', array( 'rd_from' => $id ) ); |
| 342 | + } |
| 343 | + |
| 344 | + // If using cleanup triggers, we can skip some manual deletes |
| 345 | + if ( !$dbw->cleanupTriggers() ) { |
| 346 | + // Clean up recentchanges entries... |
| 347 | + $dbw->delete( 'recentchanges', |
| 348 | + array( |
| 349 | + 'rc_type != ' . RC_LOG, |
| 350 | + 'rc_namespace' => $title->getNamespace(), |
| 351 | + 'rc_title' => $title->getDBkey() ), |
| 352 | + __METHOD__ |
| 353 | + ); |
| 354 | + $dbw->delete( |
| 355 | + 'recentchanges', |
| 356 | + array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ), |
| 357 | + __METHOD__ |
| 358 | + ); |
| 359 | + } |
| 360 | + |
| 361 | + // Clear caches |
| 362 | + // TODO: should this be in here or left in Article? |
| 363 | + Article::onArticleDelete( $title ); |
| 364 | + |
| 365 | + // Clear the cached article id so the interface doesn't act like we exist |
| 366 | + $title->resetArticleID( 0 ); |
| 367 | + |
| 368 | + // Log the deletion, if the page was suppressed, log it at Oversight instead |
| 369 | + $log = new LogPage( $logtype ); |
| 370 | + |
| 371 | + // Make sure logging got through |
| 372 | + $log->addEntry( 'delete', $title, $data['Reason'][0], array() ); |
| 373 | + |
| 374 | + if ( $commit ) { |
| 375 | + $dbw->commit(); |
| 376 | + } |
| 377 | + |
| 378 | + wfRunHooks( 'ArticleDeleteComplete', array( &$page, &$context->user, $data['Reason'][0], $id ) ); |
| 379 | + return true; |
| 380 | + } |
| 381 | + |
| 382 | + /** |
| 383 | + * Auto-generates a deletion reason. Also sets $this->hasHistory if the page has old |
| 384 | + * revisions. |
| 385 | + * |
| 386 | + * @return mixed String containing default reason or empty string, or boolean false |
| 387 | + * if no revision was found |
| 388 | + */ |
| 389 | + public static function getAutoReason( Article $page ) { |
| 390 | + global $wgContLang; |
| 391 | + |
| 392 | + $dbw = wfGetDB( DB_MASTER ); |
| 393 | + // Get the last revision |
| 394 | + $rev = Revision::newFromTitle( $page->getTitle() ); |
| 395 | + |
| 396 | + if ( is_null( $rev ) ) { |
| 397 | + return false; |
| 398 | + } |
| 399 | + |
| 400 | + // Get the article's contents |
| 401 | + $contents = $rev->getText(); |
| 402 | + $blank = false; |
| 403 | + |
| 404 | + // If the page is blank, use the text from the previous revision, |
| 405 | + // which can only be blank if there's a move/import/protect dummy revision involved |
| 406 | + if ( $contents == '' ) { |
| 407 | + $prev = $rev->getPrevious(); |
| 408 | + |
| 409 | + if ( $prev ) { |
| 410 | + $contents = $prev->getText(); |
| 411 | + $blank = true; |
| 412 | + } |
| 413 | + } |
| 414 | + |
| 415 | + // Find out if there was only one contributor |
| 416 | + // Only scan the last 20 revisions |
| 417 | + $res = $dbw->select( 'revision', 'rev_user_text', |
| 418 | + array( |
| 419 | + 'rev_page' => $page->getID(), |
| 420 | + $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' |
| 421 | + ), |
| 422 | + __METHOD__, |
| 423 | + array( 'LIMIT' => 20 ) |
| 424 | + ); |
| 425 | + |
| 426 | + if ( $res === false ) { |
| 427 | + // This page has no revisions, which is very weird |
| 428 | + return false; |
| 429 | + } |
| 430 | + |
| 431 | + $row = $dbw->fetchObject( $res ); |
| 432 | + |
| 433 | + if ( $row ) { // $row is false if the only contributor is hidden |
| 434 | + $onlyAuthor = $row->rev_user_text; |
| 435 | + // Try to find a second contributor |
| 436 | + foreach ( $res as $row ) { |
| 437 | + if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999 |
| 438 | + $onlyAuthor = false; |
| 439 | + break; |
| 440 | + } |
| 441 | + } |
| 442 | + } else { |
| 443 | + $onlyAuthor = false; |
| 444 | + } |
| 445 | + |
| 446 | + // Generate the summary with a '$1' placeholder |
| 447 | + if ( $blank ) { |
| 448 | + // The current revision is blank and the one before is also |
| 449 | + // blank. It's just not our lucky day |
| 450 | + $reason = wfMessage( 'exbeforeblank', '$1' )->inContentLanguage()->text(); |
| 451 | + } else { |
| 452 | + if ( $onlyAuthor ) { |
| 453 | + $reason = wfMessage( 'excontentauthor', '$1', $onlyAuthor )->inContentLanguage()->text(); |
| 454 | + } else { |
| 455 | + $reason = wfMessage( 'excontent', '$1' )->inContentLanguage()->text(); |
| 456 | + } |
| 457 | + } |
| 458 | + |
| 459 | + if ( $reason == '-' ) { |
| 460 | + // Allow these UI messages to be blanked out cleanly |
| 461 | + return ''; |
| 462 | + } |
| 463 | + |
| 464 | + // Replace newlines with spaces to prevent uglyness |
| 465 | + $contents = preg_replace( "/[\n\r]/", ' ', $contents ); |
| 466 | + // Calculate the maximum number of chars to get |
| 467 | + // Max content length = max comment length - length of the comment (excl. $1) |
| 468 | + $maxLength = 255 - ( strlen( $reason ) - 2 ); |
| 469 | + $contents = $wgContLang->truncate( $contents, $maxLength ); |
| 470 | + // Remove possible unfinished links |
| 471 | + $contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents ); |
| 472 | + // Now replace the '$1' placeholder |
| 473 | + $reason = str_replace( '$1', $contents, $reason ); |
| 474 | + |
| 475 | + return $reason; |
| 476 | + } |
| 477 | +} |
Property changes on: trunk/phase3/includes/actions/DeleteAction.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 478 | + native |
Index: trunk/phase3/includes/actions/WatchAction.php |
— | — | @@ -0,0 +1,82 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Performs the watch and unwatch actions on a page |
| 5 | + * |
| 6 | + * This program is free software; you can redistribute it and/or modify |
| 7 | + * it under the terms of the GNU General Public License as published by |
| 8 | + * the Free Software Foundation; either version 2 of the License, or |
| 9 | + * (at your option) any later version. |
| 10 | + * |
| 11 | + * This program is distributed in the hope that it will be useful, |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | + * GNU General Public License for more details. |
| 15 | + * |
| 16 | + * You should have received a copy of the GNU General Public License |
| 17 | + * along with this program; if not, write to the Free Software |
| 18 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| 19 | + * |
| 20 | + * @file |
| 21 | + * @ingroup Actions |
| 22 | + */ |
| 23 | + |
| 24 | +class WatchAction extends FormlessAction { |
| 25 | + |
| 26 | + public function getName(){ |
| 27 | + return 'watch'; |
| 28 | + } |
| 29 | + |
| 30 | + public function getRestriction(){ |
| 31 | + return 'read'; |
| 32 | + } |
| 33 | + |
| 34 | + protected function getDescription(){ |
| 35 | + return wfMsg( 'addedwatch' ); |
| 36 | + } |
| 37 | + |
| 38 | + protected function checkCanExecute( User $user ){ |
| 39 | + if ( $user->isAnon() ) { |
| 40 | + throw new ErrorPageError( 'watchnologin', 'watchnologintext' ); |
| 41 | + } |
| 42 | + return parent::checkCanExecute( $user ); |
| 43 | + } |
| 44 | + |
| 45 | + public function onView() { |
| 46 | + wfProfileIn( __METHOD__ ); |
| 47 | + |
| 48 | + $user = $this->getUser(); |
| 49 | + if ( wfRunHooks( 'WatchArticle', array( &$user, &$this->page ) ) ) { |
| 50 | + $this->getUser()->addWatch( $this->getTitle() ); |
| 51 | + wfRunHooks( 'WatchArticleComplete', array( &$user, &$this->page ) ); |
| 52 | + } |
| 53 | + |
| 54 | + wfProfileOut( __METHOD__ ); |
| 55 | + |
| 56 | + return wfMessage( 'addedwatchtext', $this->getTitle()->getPrefixedText() )->parse(); |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +class UnwatchAction extends WatchAction { |
| 61 | + |
| 62 | + public function getName(){ |
| 63 | + return 'unwatch'; |
| 64 | + } |
| 65 | + |
| 66 | + protected function getDescription(){ |
| 67 | + return wfMsg( 'removedwatch' ); |
| 68 | + } |
| 69 | + |
| 70 | + public function onView() { |
| 71 | + wfProfileIn( __METHOD__ ); |
| 72 | + |
| 73 | + $user = $this->getUser(); |
| 74 | + if ( wfRunHooks( 'UnwatchArticle', array( &$user, &$this->page ) ) ) { |
| 75 | + $this->getUser()->removeWatch( $this->getTitle() ); |
| 76 | + wfRunHooks( 'UnwatchArticleComplete', array( &$user, &$this->page ) ); |
| 77 | + } |
| 78 | + |
| 79 | + wfProfileOut( __METHOD__ ); |
| 80 | + |
| 81 | + return wfMessage( 'removedwatchtext', $this->getTitle()->getPrefixedText() )->parse(); |
| 82 | + } |
| 83 | +} |
Property changes on: trunk/phase3/includes/actions/WatchAction.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 84 | + native |
Index: trunk/phase3/includes/api/ApiWatch.php |
— | — | @@ -59,11 +59,11 @@ |
60 | 60 | if ( $params['unwatch'] ) { |
61 | 61 | $res['unwatched'] = ''; |
62 | 62 | $res['message'] = wfMsgExt( 'removedwatchtext', array( 'parse' ), $title->getPrefixedText() ); |
63 | | - $success = $article->doUnwatch(); |
| 63 | + $success = Action::factory( 'unwatch', $article )->execute(); |
64 | 64 | } else { |
65 | 65 | $res['watched'] = ''; |
66 | 66 | $res['message'] = wfMsgExt( 'addedwatchtext', array( 'parse' ), $title->getPrefixedText() ); |
67 | | - $success = $article->doWatch(); |
| 67 | + $success = Action::factory( 'watch', $article )->execute(); |
68 | 68 | } |
69 | 69 | if ( !$success ) { |
70 | 70 | $this->dieUsageMsg( array( 'hookaborted' ) ); |
Index: trunk/phase3/includes/api/ApiDelete.php |
— | — | @@ -123,11 +123,6 @@ |
124 | 124 | * @return Title::getUserPermissionsErrors()-like array |
125 | 125 | */ |
126 | 126 | public static function delete( &$article, $token, &$reason = null ) { |
127 | | - global $wgUser; |
128 | | - if ( $article->isBigDeletion() && !$wgUser->isAllowed( 'bigdelete' ) ) { |
129 | | - global $wgDeleteRevisionsLimit; |
130 | | - return array( array( 'delete-toobig', $wgDeleteRevisionsLimit ) ); |
131 | | - } |
132 | 127 | $title = $article->getTitle(); |
133 | 128 | $errors = self::getPermissionsError( $title, $token ); |
134 | 129 | if ( count( $errors ) ) { |
— | — | @@ -136,22 +131,29 @@ |
137 | 132 | |
138 | 133 | // Auto-generate a summary, if necessary |
139 | 134 | if ( is_null( $reason ) ) { |
140 | | - // Need to pass a throwaway variable because generateReason expects |
141 | | - // a reference |
142 | | - $hasHistory = false; |
143 | | - $reason = $article->generateReason( $hasHistory ); |
| 135 | + $reason = DeleteAction::getAutoReason( $article ); |
144 | 136 | if ( $reason === false ) { |
145 | 137 | return array( array( 'cannotdelete' ) ); |
146 | 138 | } |
147 | 139 | } |
148 | 140 | |
149 | | - $error = ''; |
150 | | - // Luckily, Article.php provides a reusable delete function that does the hard work for us |
151 | | - if ( $article->doDeleteArticle( $reason, false, 0, true, $error ) ) { |
152 | | - return array(); |
153 | | - } else { |
154 | | - return array( array( 'cannotdelete', $article->mTitle->getPrefixedText() ) ); |
| 141 | + $action = Action::factory( 'delete', $article ); |
| 142 | + $data = array( |
| 143 | + 'Reason' => $reason, |
| 144 | + 'Suppress' => false, // The thought of people doing this through the API is scary... |
| 145 | + ); |
| 146 | + |
| 147 | + try { |
| 148 | + $action->execute( $data, false ); |
155 | 149 | } |
| 150 | + catch ( ErrorPageError $e ){ |
| 151 | + if( $e->msg == 'delete-toobig' ){ |
| 152 | + global $wgDeleteRevisionsLimit; |
| 153 | + return array( array( 'delete-toobig', $wgDeleteRevisionsLimit ) ); |
| 154 | + } else { |
| 155 | + array( array( 'cannotdelete', $article->mTitle->getPrefixedText() ) ); |
| 156 | + } |
| 157 | + } |
156 | 158 | } |
157 | 159 | |
158 | 160 | /** |
Index: trunk/phase3/includes/api/ApiBase.php |
— | — | @@ -645,9 +645,9 @@ |
646 | 646 | |
647 | 647 | $articleObj = new Article( $titleObj ); |
648 | 648 | if ( $value ) { |
649 | | - $articleObj->doWatch(); |
| 649 | + Action::factory( 'watch', $articleObj )->execute(); |
650 | 650 | } else { |
651 | | - $articleObj->doUnwatch(); |
| 651 | + Action::factory( 'unwatch', $articleObj )->execute(); |
652 | 652 | } |
653 | 653 | } |
654 | 654 | |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -14,6 +14,7 @@ |
15 | 15 | |
16 | 16 | $wgAutoloadLocalClasses = array( |
17 | 17 | # Includes |
| 18 | + 'Action' => 'includes/Action.php', |
18 | 19 | 'AjaxDispatcher' => 'includes/AjaxDispatcher.php', |
19 | 20 | 'AjaxResponse' => 'includes/AjaxResponse.php', |
20 | 21 | 'AlphabeticPager' => 'includes/Pager.php', |
— | — | @@ -51,7 +52,6 @@ |
52 | 53 | 'ConfEditorToken' => 'includes/ConfEditor.php', |
53 | 54 | 'ConstantDependency' => 'includes/CacheDependency.php', |
54 | 55 | 'CreativeCommonsRdf' => 'includes/Metadata.php', |
55 | | - 'Credits' => 'includes/Credits.php', |
56 | 56 | 'CSSJanus' => 'includes/libs/CSSJanus.php', |
57 | 57 | 'CSSMin' => 'includes/libs/CSSMin.php', |
58 | 58 | 'DependencyWrapper' => 'includes/CacheDependency.php', |
— | — | @@ -274,6 +274,12 @@ |
275 | 275 | 'ZhClient' => 'includes/ZhClient.php', |
276 | 276 | 'ZipDirectoryReader' => 'includes/ZipDirectoryReader.php', |
277 | 277 | |
| 278 | + # includes/actions |
| 279 | + 'CreditsAction' => 'includes/actions/CreditsAction.php', |
| 280 | + 'DeleteAction' => 'includes/actions/DeleteAction.php', |
| 281 | + 'UnwatchAction' => 'includes/actions/WatchAction.php', |
| 282 | + 'WatchAction' => 'includes/actions/WatchAction.php', |
| 283 | + |
278 | 284 | # includes/api |
279 | 285 | 'ApiBase' => 'includes/api/ApiBase.php', |
280 | 286 | 'ApiBlock' => 'includes/api/ApiBlock.php', |
Index: trunk/phase3/includes/Wiki.php |
— | — | @@ -471,9 +471,16 @@ |
472 | 472 | return; |
473 | 473 | } |
474 | 474 | |
475 | | - $action = $this->getAction(); |
| 475 | + $act = $this->getAction(); |
476 | 476 | |
477 | | - switch( $action ) { |
| 477 | + $action = Action::factory( $this->getAction(), $article ); |
| 478 | + if( $action instanceof Action ){ |
| 479 | + $action->show(); |
| 480 | + wfProfileOut( __METHOD__ ); |
| 481 | + return; |
| 482 | + } |
| 483 | + |
| 484 | + switch( $act ) { |
478 | 485 | case 'view': |
479 | 486 | $this->context->output->setSquidMaxage( $this->getVal( 'SquidMaxage' ) ); |
480 | 487 | $article->view(); |
— | — | @@ -484,9 +491,6 @@ |
485 | 492 | $raw->view(); |
486 | 493 | wfProfileOut( __METHOD__ . '-raw' ); |
487 | 494 | break; |
488 | | - case 'watch': |
489 | | - case 'unwatch': |
490 | | - case 'delete': |
491 | 495 | case 'revert': |
492 | 496 | case 'rollback': |
493 | 497 | case 'protect': |
— | — | @@ -496,7 +500,7 @@ |
497 | 501 | case 'render': |
498 | 502 | case 'deletetrackback': |
499 | 503 | case 'purge': |
500 | | - $article->$action(); |
| 504 | + $article->$act(); |
501 | 505 | break; |
502 | 506 | case 'print': |
503 | 507 | $article->view(); |
— | — | @@ -517,9 +521,6 @@ |
518 | 522 | $rdf->show(); |
519 | 523 | } |
520 | 524 | break; |
521 | | - case 'credits': |
522 | | - Credits::showPage( $article ); |
523 | | - break; |
524 | 525 | case 'submit': |
525 | 526 | if ( session_id() == '' ) { |
526 | 527 | // Send a cookie so anons get talk message notifications |
— | — | @@ -532,7 +533,7 @@ |
533 | 534 | $external = $this->context->request->getVal( 'externaledit' ); |
534 | 535 | $section = $this->context->request->getVal( 'section' ); |
535 | 536 | $oldid = $this->context->request->getVal( 'oldid' ); |
536 | | - if ( !$this->getVal( 'UseExternalEditor' ) || $action == 'submit' || $internal || |
| 537 | + if ( !$this->getVal( 'UseExternalEditor' ) || $act == 'submit' || $internal || |
537 | 538 | $section || $oldid || ( !$this->context->user->getOption( 'externaleditor' ) && !$external ) ) { |
538 | 539 | $editor = new EditPage( $article ); |
539 | 540 | $editor->submit(); |
— | — | @@ -561,7 +562,7 @@ |
562 | 563 | $special->execute( '' ); |
563 | 564 | break; |
564 | 565 | default: |
565 | | - if ( wfRunHooks( 'UnknownAction', array( $action, $article ) ) ) { |
| 566 | + if ( wfRunHooks( 'UnknownAction', array( $act, $article ) ) ) { |
566 | 567 | $this->context->output->showErrorPage( 'nosuchaction', 'nosuchactiontext' ); |
567 | 568 | } |
568 | 569 | } |
Index: trunk/phase3/includes/FileDeleteForm.php |
— | — | @@ -125,9 +125,9 @@ |
126 | 126 | if( $article->doDeleteArticle( $reason, $suppress, $id, false ) ) { |
127 | 127 | global $wgRequest; |
128 | 128 | if( $wgRequest->getCheck( 'wpWatch' ) && $wgUser->isLoggedIn() ) { |
129 | | - $article->doWatch(); |
| 129 | + Action::factory( 'watch', $article )->execute(); |
130 | 130 | } elseif( $title->userIsWatching() ) { |
131 | | - $article->doUnwatch(); |
| 131 | + Action::factory( 'unwatch', $article )->execute(); |
132 | 132 | } |
133 | 133 | $status = $file->delete( $reason, $suppress ); |
134 | 134 | if( $status->ok ) { |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -27,12 +27,10 @@ |
28 | 28 | } |
29 | 29 | |
30 | 30 | # Create a site configuration object. Not used for much in a default install |
31 | | -if ( !defined( 'MW_PHP4' ) ) { |
32 | | - if ( !defined( 'MW_COMPILED' ) ) { |
33 | | - require_once( "$IP/includes/SiteConfiguration.php" ); |
34 | | - } |
35 | | - $wgConf = new SiteConfiguration; |
| 31 | +if ( !defined( 'MW_COMPILED' ) ) { |
| 32 | + require_once( "$IP/includes/SiteConfiguration.php" ); |
36 | 33 | } |
| 34 | +$wgConf = new SiteConfiguration; |
37 | 35 | /** @endcond */ |
38 | 36 | |
39 | 37 | /** MediaWiki version number */ |
— | — | @@ -5024,6 +5022,38 @@ |
5025 | 5023 | /** @} */ # end special pages } |
5026 | 5024 | |
5027 | 5025 | /*************************************************************************//** |
| 5026 | + * @name Actions |
| 5027 | + * @{ |
| 5028 | + */ |
| 5029 | + |
| 5030 | +/** |
| 5031 | + * Array of allowed values for the title=foo&action=<action> parameter. Syntax is: |
| 5032 | + * 'foo' => 'ClassName' Load the specified class which subclasses Action |
| 5033 | + * 'foo' => true Load the class FooAction which subclasses Action |
| 5034 | + * 'foo' => false The action is disabled; show an error message |
| 5035 | + * Unsetting core actions will probably cause things to complain loudly. |
| 5036 | + */ |
| 5037 | +$wgActions = array( |
| 5038 | + 'credits' => true, |
| 5039 | + 'delete' => true, |
| 5040 | + 'unwatch' => true, |
| 5041 | + 'watch' => true, |
| 5042 | +); |
| 5043 | + |
| 5044 | +/** |
| 5045 | + * Array of disabled article actions, e.g. view, edit, dublincore, delete, etc. |
| 5046 | + * @deprecated since 1.18; just set $wgActions['action'] = false instead |
| 5047 | + */ |
| 5048 | +$wgDisabledActions = array(); |
| 5049 | + |
| 5050 | +/** |
| 5051 | + * Allow the "info" action, very inefficient at the moment |
| 5052 | + */ |
| 5053 | +$wgAllowPageInfo = false; |
| 5054 | + |
| 5055 | +/** @} */ # end actions } |
| 5056 | + |
| 5057 | +/*************************************************************************//** |
5028 | 5058 | * @name Robot (search engine crawler) policy |
5029 | 5059 | * See also $wgNoFollowLinks. |
5030 | 5060 | * @{ |
— | — | @@ -5288,18 +5318,10 @@ |
5289 | 5319 | * @{ |
5290 | 5320 | */ |
5291 | 5321 | |
5292 | | -/** Allow the "info" action, very inefficient at the moment */ |
5293 | | -$wgAllowPageInfo = false; |
5294 | | - |
5295 | 5322 | /** Name of the external diff engine to use */ |
5296 | 5323 | $wgExternalDiffEngine = false; |
5297 | 5324 | |
5298 | 5325 | /** |
5299 | | - * Array of disabled article actions, e.g. view, edit, dublincore, delete, etc. |
5300 | | - */ |
5301 | | -$wgDisabledActions = array(); |
5302 | | - |
5303 | | -/** |
5304 | 5326 | * Disable redirects to special pages and interwiki redirects, which use a 302 |
5305 | 5327 | * and have no "redirected from" link. Note this is only for articles with #Redirect |
5306 | 5328 | * in them. URL's containing a local interwiki prefix (or a non-canonical special |
Index: trunk/phase3/includes/specials/SpecialMovepage.php |
— | — | @@ -359,8 +359,11 @@ |
360 | 360 | $article = new Article( $nt ); |
361 | 361 | |
362 | 362 | # Disallow deletions of big articles |
363 | | - $bigHistory = $article->isBigDeletion(); |
364 | | - if( $bigHistory && !$nt->userCan( 'bigdelete' ) ) { |
| 363 | + global $wgDeleteRevisionsLimit; |
| 364 | + if ( $wgDeleteRevisionsLimit |
| 365 | + && $this->estimateRevisionCount() > $wgDeleteRevisionsLimit |
| 366 | + && !$nt->userCan( 'bigdelete' ) ) |
| 367 | + { |
365 | 368 | global $wgDeleteRevisionsLimit; |
366 | 369 | $this->showForm( array('delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) ); |
367 | 370 | return; |
— | — | @@ -373,7 +376,10 @@ |
374 | 377 | } |
375 | 378 | |
376 | 379 | // This may output an error message and exit |
377 | | - $article->doDelete( wfMsgForContent( 'delete_and_move_reason' ) ); |
| 380 | + Action::factory( 'delete', $article )->execute( |
| 381 | + array( 'Reason' => wfMsgForContent( 'delete_and_move_reason' ) ), |
| 382 | + false // Do not capture exceptions |
| 383 | + ); |
378 | 384 | } |
379 | 385 | |
380 | 386 | # don't allow moving to pages with # in |
Index: trunk/phase3/includes/Action.php |
— | — | @@ -0,0 +1,440 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Actions are things which can be done to pages (edit, delete, rollback, etc). They |
| 5 | + * are distinct from Special Pages because an action must apply to exactly one page. |
| 6 | + * |
| 7 | + * To add an action in an extension, create a subclass of Action, and add the key to |
| 8 | + * $wgActions. There is also the deprecated UnknownAction hook |
| 9 | + * |
| 10 | + * |
| 11 | + * This program is free software; you can redistribute it and/or modify |
| 12 | + * it under the terms of the GNU General Public License as published by |
| 13 | + * the Free Software Foundation; either version 2 of the License, or |
| 14 | + * (at your option) any later version. |
| 15 | + * |
| 16 | + * This program is distributed in the hope that it will be useful, |
| 17 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 18 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 19 | + * GNU General Public License for more details. |
| 20 | + * |
| 21 | + * You should have received a copy of the GNU General Public License |
| 22 | + * along with this program; if not, write to the Free Software |
| 23 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| 24 | + * |
| 25 | + * @file |
| 26 | + */ |
| 27 | +abstract class Action { |
| 28 | + |
| 29 | + // Page on which we're performing the action |
| 30 | + // @var Article |
| 31 | + protected $page; |
| 32 | + |
| 33 | + // RequestContext if specified; otherwise we'll use the Context from the Page |
| 34 | + // @var RequestContext |
| 35 | + protected $context; |
| 36 | + |
| 37 | + // The fields used to create the HTMLForm |
| 38 | + // @var Array |
| 39 | + protected $fields; |
| 40 | + |
| 41 | + /** |
| 42 | + * Get the Action subclass which should be used to handle this action, false if |
| 43 | + * the action is disabled, or null if it's not recognised |
| 44 | + * @param $action String |
| 45 | + * @return bool|null|string |
| 46 | + */ |
| 47 | + private final static function getClass( $action ){ |
| 48 | + global $wgActions; |
| 49 | + $action = strtolower( $action ); |
| 50 | + |
| 51 | + if( !isset( $wgActions[$action] ) ){ |
| 52 | + return null; |
| 53 | + } |
| 54 | + |
| 55 | + if( $wgActions[$action] === false ){ |
| 56 | + return false; |
| 57 | + } |
| 58 | + |
| 59 | + elseif( $wgActions[$action] === true ){ |
| 60 | + return ucfirst( $action ) . 'Action'; |
| 61 | + } |
| 62 | + |
| 63 | + else { |
| 64 | + return $wgActions[$action]; |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + /** |
| 69 | + * Get an appropriate Action subclass for the given action |
| 70 | + * @param $action String |
| 71 | + * @param $page Article |
| 72 | + * @return Action|false|null false if the action is disabled, null |
| 73 | + * if it is not recognised |
| 74 | + */ |
| 75 | + public final static function factory( $action, Article $page ){ |
| 76 | + $class = self::getClass( $action ); |
| 77 | + if( $class ){ |
| 78 | + $obj = new $class( $page ); |
| 79 | + return $obj; |
| 80 | + } |
| 81 | + return null; |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * Check if a given action is recognised, even if it's disabled |
| 86 | + * |
| 87 | + * @param $name String: name of an action |
| 88 | + * @return Bool |
| 89 | + */ |
| 90 | + public final static function exists( $name ) { |
| 91 | + return self::getClass( $name ) !== null; |
| 92 | + } |
| 93 | + |
| 94 | + /** |
| 95 | + * Get the RequestContext in use here |
| 96 | + * @return RequestContext |
| 97 | + */ |
| 98 | + protected final function getContext(){ |
| 99 | + if( $this->context instanceof RequestContext ){ |
| 100 | + return $this->context; |
| 101 | + } |
| 102 | + return $this->page->getContext(); |
| 103 | + } |
| 104 | + |
| 105 | + /** |
| 106 | + * Get the WebRequest being used for this instance |
| 107 | + * |
| 108 | + * @return WebRequest |
| 109 | + */ |
| 110 | + protected final function getRequest() { |
| 111 | + return $this->getContext()->request; |
| 112 | + } |
| 113 | + |
| 114 | + /** |
| 115 | + * Get the OutputPage being used for this instance |
| 116 | + * |
| 117 | + * @return OutputPage |
| 118 | + */ |
| 119 | + protected final function getOutput() { |
| 120 | + return $this->getContext()->output; |
| 121 | + } |
| 122 | + |
| 123 | + /** |
| 124 | + * Shortcut to get the skin being used for this instance |
| 125 | + * |
| 126 | + * @return User |
| 127 | + */ |
| 128 | + protected final function getUser() { |
| 129 | + return $this->getContext()->user; |
| 130 | + } |
| 131 | + |
| 132 | + /** |
| 133 | + * Shortcut to get the skin being used for this instance |
| 134 | + * |
| 135 | + * @return Skin |
| 136 | + */ |
| 137 | + protected final function getSkin() { |
| 138 | + return $this->getContext()->skin; |
| 139 | + } |
| 140 | + |
| 141 | + /** |
| 142 | + * Shortcut to get the Title object from the page |
| 143 | + * @return Title |
| 144 | + */ |
| 145 | + protected final function getTitle(){ |
| 146 | + return $this->page->getTitle(); |
| 147 | + } |
| 148 | + |
| 149 | + /** |
| 150 | + * Protected constructor: use Action::factory( $action, $page ) to actually build |
| 151 | + * these things in the real world |
| 152 | + * @param Article $page |
| 153 | + */ |
| 154 | + protected function __construct( Article $page ){ |
| 155 | + $this->page = $page; |
| 156 | + } |
| 157 | + |
| 158 | + /** |
| 159 | + * Return the name of the action this object responds to |
| 160 | + * @return String lowercase |
| 161 | + */ |
| 162 | + public abstract function getName(); |
| 163 | + |
| 164 | + /** |
| 165 | + * Get the permission required to perform this action. Often, but not always, |
| 166 | + * the same as the action name |
| 167 | + */ |
| 168 | + public abstract function getRestriction(); |
| 169 | + |
| 170 | + /** |
| 171 | + * Checks if the given user (identified by an object) can perform this action. Can be |
| 172 | + * overridden by sub-classes with more complicated permissions schemes. Failures here |
| 173 | + * must throw subclasses of ErrorPageError |
| 174 | + * |
| 175 | + * @param $user User: the user to check, or null to use the context user |
| 176 | + * @throws ErrorPageError |
| 177 | + */ |
| 178 | + protected function checkCanExecute( User $user ) { |
| 179 | + if( $this->requiresWrite() && wfReadOnly() ){ |
| 180 | + throw new ReadOnlyError(); |
| 181 | + } |
| 182 | + |
| 183 | + if( $this->getRestriction() !== null && !$user->isAllowed( $this->getRestriction() ) ){ |
| 184 | + throw new PermissionsError( $this->getRestriction() ); |
| 185 | + } |
| 186 | + |
| 187 | + if( $this->requiresUnblock() && $user->isBlocked() ){ |
| 188 | + $block = $user->mBlock; |
| 189 | + throw new UserBlockedError( $block ); |
| 190 | + } |
| 191 | + } |
| 192 | + |
| 193 | + /** |
| 194 | + * Whether this action requires the wiki not to be locked |
| 195 | + * @return Bool |
| 196 | + */ |
| 197 | + public function requiresWrite(){ |
| 198 | + return true; |
| 199 | + } |
| 200 | + |
| 201 | + /** |
| 202 | + * Whether this action can still be executed by a blocked user |
| 203 | + * @return Bool |
| 204 | + */ |
| 205 | + public function requiresUnblock(){ |
| 206 | + return true; |
| 207 | + } |
| 208 | + |
| 209 | + /** |
| 210 | + * Set output headers for noindexing etc. This function will not be called through |
| 211 | + * the execute() entry point, so only put UI-related stuff in here. |
| 212 | + */ |
| 213 | + protected function setHeaders() { |
| 214 | + $out = $this->getOutput(); |
| 215 | + $out->setRobotPolicy( "noindex,nofollow" ); |
| 216 | + $out->setPageTitle( $this->getTitle()->getPrefixedText() ); |
| 217 | + $this->getOutput()->setSubtitle( $this->getDescription() ); |
| 218 | + $out->setArticleRelated( true ); |
| 219 | + } |
| 220 | + |
| 221 | + /** |
| 222 | + * Returns the name that goes in the \<h1\> page title |
| 223 | + * |
| 224 | + * Derived classes can override this, but usually it is easier to keep the |
| 225 | + * default behaviour. Messages can be added at run-time, see |
| 226 | + * MessageCache.php. |
| 227 | + * |
| 228 | + * @return String |
| 229 | + */ |
| 230 | + protected function getDescription() { |
| 231 | + return wfMsg( strtolower( $this->getName() ) ); |
| 232 | + } |
| 233 | + |
| 234 | + /** |
| 235 | + * The basic pattern for actions is to display some sort of HTMLForm UI, maybe with |
| 236 | + * some stuff underneath (history etc); to do some processing on submission of that |
| 237 | + * form (delete, protect, etc) and to do something exciting on 'success', be that |
| 238 | + * display something new or redirect to somewhere. Some actions have more exotic |
| 239 | + * behaviour, but that's what subclassing is for :D |
| 240 | + */ |
| 241 | + public function show(){ |
| 242 | + $this->setHeaders(); |
| 243 | + |
| 244 | + // This will throw exceptions if there's a problem |
| 245 | + $this->checkCanExecute( $this->getUser() ); |
| 246 | + |
| 247 | + $form = $this->getForm(); |
| 248 | + if( $form instanceof HTMLForm ){ |
| 249 | + if( $form->show() ){ |
| 250 | + $this->onSuccess(); |
| 251 | + } |
| 252 | + } else { |
| 253 | + // You're using the wrong type of Action |
| 254 | + throw new MWException( "Action::getFormFields() must produce a form. Use GetAction if you don't want one." ); |
| 255 | + } |
| 256 | + } |
| 257 | + |
| 258 | + /** |
| 259 | + * Execute the action in a silent fashion: do not display anything or release any errors. |
| 260 | + * @param $data Array values that would normally be in the POST request |
| 261 | + * @param $captureErrors Bool whether to catch exceptions and just return false |
| 262 | + * @return Bool whether execution was successful |
| 263 | + */ |
| 264 | + public function execute( array $data = null, $captureErrors = true ){ |
| 265 | + try { |
| 266 | + // Set a new context so output doesn't leak. |
| 267 | + $this->context = clone $this->page->getContext(); |
| 268 | + |
| 269 | + // This will throw exceptions if there's a problem |
| 270 | + $this->checkCanExecute( $this->getUser() ); |
| 271 | + |
| 272 | + $form = $this->getForm(); |
| 273 | + if( $form instanceof HTMLForm ){ |
| 274 | + // Great, so there's a form. Ignore it and go straight to the submission callback |
| 275 | + $fields = array(); |
| 276 | + foreach( $this->fields as $key => $params ){ |
| 277 | + if( isset( $data[$key] ) ){ |
| 278 | + $fields[$key] = $data[$key]; |
| 279 | + } elseif( isset( $params['default'] ) ) { |
| 280 | + $fields[$key] = $params['default']; |
| 281 | + } else { |
| 282 | + $fields[$key] = null; |
| 283 | + } |
| 284 | + } |
| 285 | + $status = $this->onSubmit( $fields ); |
| 286 | + if( $status === true ){ |
| 287 | + // This might do permanent stuff |
| 288 | + $this->onSuccess(); |
| 289 | + return true; |
| 290 | + } else { |
| 291 | + return false; |
| 292 | + } |
| 293 | + } else { |
| 294 | + // You're using the wrong type of Action |
| 295 | + throw new MWException( "Action::getFormFields() must produce a form. Use GetAction if you don't want one." ); |
| 296 | + } |
| 297 | + } |
| 298 | + catch ( ErrorPageError $e ){ |
| 299 | + if( $captureErrors ){ |
| 300 | + return false; |
| 301 | + } else { |
| 302 | + throw $e; |
| 303 | + } |
| 304 | + } |
| 305 | + } |
| 306 | + |
| 307 | + /** |
| 308 | + * Get an HTMLForm descriptor array, or false if you don't want a form |
| 309 | + * @return Array |
| 310 | + */ |
| 311 | + protected abstract function getFormFields(); |
| 312 | + |
| 313 | + /** |
| 314 | + * Add pre- or post-text to the form |
| 315 | + * @return String |
| 316 | + */ |
| 317 | + protected function preText(){ return ''; } |
| 318 | + protected function postText(){ return ''; } |
| 319 | + |
| 320 | + /** |
| 321 | + * Play with the HTMLForm if you need to more substantially |
| 322 | + * @param &$form HTMLForm |
| 323 | + */ |
| 324 | + protected function alterForm( HTMLForm &$form ){} |
| 325 | + |
| 326 | + /** |
| 327 | + * Get the HTMLForm to control behaviour |
| 328 | + * @return HTMLForm|null |
| 329 | + */ |
| 330 | + protected function getForm(){ |
| 331 | + $this->fields = $this->getFormFields(); |
| 332 | + |
| 333 | + // Give hooks a chance to alter the form, adding extra fields or text etc |
| 334 | + wfRunHooks( 'ActionModifyFormFields', array( $this->getName(), &$this->fields, $this->page ) ); |
| 335 | + |
| 336 | + if( $this->fields === false ){ |
| 337 | + return null; |
| 338 | + } |
| 339 | + |
| 340 | + $form = new HTMLForm( $this->fields, $this->getContext() ); |
| 341 | + $form->setSubmitCallback( array( $this, 'onSubmit' ) ); |
| 342 | + $form->addHiddenField( 'action', $this->getName() ); |
| 343 | + |
| 344 | + $form->addPreText( $this->preText() ); |
| 345 | + $form->addPostText( $this->postText() ); |
| 346 | + $this->alterForm( $form ); |
| 347 | + |
| 348 | + // Give hooks a chance to alter the form, adding extra fields or text etc |
| 349 | + wfRunHooks( 'ActionBeforeFormDisplay', array( $this->getName(), &$form, $this->page ) ); |
| 350 | + |
| 351 | + return $form; |
| 352 | + } |
| 353 | + |
| 354 | + /** |
| 355 | + * Process the form on POST submission. If you return false from getFormFields(), |
| 356 | + * this will obviously never be reached. If you don't want to do anything with the |
| 357 | + * form, just return false here |
| 358 | + * @param $data Array |
| 359 | + * @return Bool|Array true for success, false for didn't-try, array of errors on failure |
| 360 | + */ |
| 361 | + public abstract function onSubmit( $data ); |
| 362 | + |
| 363 | + /** |
| 364 | + * Do something exciting on successful processing of the form. This might be to show |
| 365 | + * a confirmation message (watch, rollback, etc) or to redirect somewhere else (edit, |
| 366 | + * protect, etc). |
| 367 | + */ |
| 368 | + public abstract function onSuccess(); |
| 369 | + |
| 370 | +} |
| 371 | + |
| 372 | +/** |
| 373 | + * Actions generally fall into two groups: the show-a-form-then-do-something-with-the-input |
| 374 | + * format (protect, delete, move, etc), and the just-do-something format (watch, rollback, |
| 375 | + * patrol, etc). |
| 376 | + */ |
| 377 | +abstract class FormlessAction extends Action { |
| 378 | + |
| 379 | + /** |
| 380 | + * Show something on GET request. This is displayed as the postText() of the HTMLForm |
| 381 | + * if there is one; you can always use alterForm() to add pre text if you need it. If |
| 382 | + * you call addPostText() from alterForm() as well as overriding this function, you |
| 383 | + * might get strange ordering. |
| 384 | + * @return String|null will be added to the HTMLForm if present, or just added to the |
| 385 | + * output if not. Return null to not add anything |
| 386 | + */ |
| 387 | + public abstract function onView(); |
| 388 | + |
| 389 | + /** |
| 390 | + * We don't want an HTMLForm |
| 391 | + */ |
| 392 | + protected function getFormFields(){ |
| 393 | + return false; |
| 394 | + } |
| 395 | + |
| 396 | + public function onSubmit( $data ){ |
| 397 | + return false; |
| 398 | + } |
| 399 | + |
| 400 | + public function onSuccess(){ |
| 401 | + return false; |
| 402 | + } |
| 403 | + |
| 404 | + public function show(){ |
| 405 | + $this->setHeaders(); |
| 406 | + |
| 407 | + // This will throw exceptions if there's a problem |
| 408 | + $this->checkCanExecute( $this->getUser() ); |
| 409 | + $this->getOutput()->addHTML( $this->onView() ); |
| 410 | + } |
| 411 | + |
| 412 | + /** |
| 413 | + * Execute the action silently, not giving any output. Since these actions don't have |
| 414 | + * forms, they probably won't have any data, but some (eg rollback) may do |
| 415 | + * @param $data Array values that would normally be in the GET request |
| 416 | + * @param $captureErrors Bool whether to catch exceptions and just return false |
| 417 | + * @return Bool whether execution was successful |
| 418 | + */ |
| 419 | + public function execute( array $data = null, $captureErrors = true){ |
| 420 | + try { |
| 421 | + // Set a new context so output doesn't leak. |
| 422 | + $this->context = clone $this->page->getContext(); |
| 423 | + if( is_array( $data ) ){ |
| 424 | + $this->context->setRequest( new FauxRequest( $data, false ) ); |
| 425 | + } |
| 426 | + |
| 427 | + // This will throw exceptions if there's a problem |
| 428 | + $this->checkCanExecute( $this->getUser() ); |
| 429 | + |
| 430 | + $this->onView(); |
| 431 | + return true; |
| 432 | + } |
| 433 | + catch ( ErrorPageError $e ){ |
| 434 | + if( $captureErrors ){ |
| 435 | + return false; |
| 436 | + } else { |
| 437 | + throw $e; |
| 438 | + } |
| 439 | + } |
| 440 | + } |
| 441 | +} |
\ No newline at end of file |
Property changes on: trunk/phase3/includes/Action.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 442 | + native |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -998,8 +998,9 @@ |
999 | 999 | 'unexpected' => 'Unexpected value: "$1"="$2".', |
1000 | 1000 | 'formerror' => 'Error: could not submit form', |
1001 | 1001 | 'badarticleerror' => 'This action cannot be performed on this page.', |
1002 | | -'cannotdelete' => 'The page or file "$1" could not be deleted. |
1003 | | -It may have already been deleted by someone else.', |
| 1002 | +'cannotdelete' => 'The page or file "$1" could not be deleted. It may have already been deleted by someone else. The deletion log is provided below for convenience. |
| 1003 | + |
| 1004 | +$2', |
1004 | 1005 | 'badtitle' => 'Bad title', |
1005 | 1006 | 'badtitletext' => 'The requested page title was invalid, empty, or an incorrectly linked inter-language or inter-wiki title. |
1006 | 1007 | It may contain one or more characters which cannot be used in titles.', |
— | — | @@ -2783,7 +2784,7 @@ |
2784 | 2785 | 'delete-confirm' => 'Delete "$1"', |
2785 | 2786 | 'delete-backlink' => '← $1', # only translate this message to other languages if you have to change it |
2786 | 2787 | 'delete-legend' => 'Delete', |
2787 | | -'historywarning' => "'''Warning:''' The page you are about to delete has a history with approximately $1 {{PLURAL:$1|revision|revisions}}:", |
| 2788 | +'historywarning' => "'''Warning:''' The page you are about to delete has a $2 with approximately $1 {{PLURAL:$1|revision|revisions}}:", |
2788 | 2789 | 'confirmdeletetext' => 'You are about to delete a page along with all of its history. |
2789 | 2790 | Please confirm that you intend to do this, that you understand the consequences, and that you are doing this in accordance with [[{{MediaWiki:Policy-url}}|the policy]].', |
2790 | 2791 | 'actioncomplete' => 'Action complete', |
Index: trunk/extensions/LiquidThreads/LiquidThreads.php |
— | — | @@ -118,7 +118,7 @@ |
119 | 119 | $wgHooks['ArticleDeleteComplete'][] = 'LqtDeletionController::onArticleDeleteComplete'; |
120 | 120 | $wgHooks['ArticleRevisionUndeleted'][] = 'LqtDeletionController::onArticleRevisionUndeleted'; |
121 | 121 | $wgHooks['ArticleUndelete'][] = 'LqtDeletionController::onArticleUndelete'; |
122 | | -$wgHooks['ArticleConfirmDelete'][] = 'LqtDeletionController::onArticleConfirmDelete'; |
| 122 | +$wgHooks['ActionBeforeFormDisplay'][] = 'LqtDeletionController::onActionBeforeFormDisplay'; |
123 | 123 | $wgHooks['ArticleDelete'][] = 'LqtDeletionController::onArticleDelete'; |
124 | 124 | |
125 | 125 | // Moving |
Index: trunk/extensions/LiquidThreads/classes/DeletionController.php |
— | — | @@ -94,22 +94,27 @@ |
95 | 95 | return true; |
96 | 96 | } |
97 | 97 | |
98 | | - static function onArticleConfirmDelete( $article, $out, &$reason ) { |
99 | | - if ( $article->getTitle()->getNamespace() != NS_LQT_THREAD ) { |
| 98 | + static function onActionBeforeFormDisplay( $action, HTMLForm &$form, $page ) { |
| 99 | + if( $action != 'delete' ){ |
100 | 100 | return true; |
101 | 101 | } |
102 | 102 | |
103 | | - $thread = Threads::withRoot( $article ); |
| 103 | + if ( $page->getTitle()->getNamespace() != NS_LQT_THREAD ) { |
| 104 | + return true; |
| 105 | + } |
104 | 106 | |
| 107 | + $thread = Threads::withRoot( $page ); |
| 108 | + |
105 | 109 | if ( !$thread ) { |
106 | 110 | return true; |
107 | 111 | } |
108 | 112 | |
109 | 113 | if ( $thread->isTopmostThread() && count( $thread->replies() ) ) { |
110 | | - $out->wrapWikiMsg( |
111 | | - '<strong>$1</strong>', |
112 | | - 'lqt-delete-parent-warning' |
113 | | - ); |
| 114 | + $form->addHeaderText( Html::rawElement( |
| 115 | + 'strong', |
| 116 | + array(), |
| 117 | + wfMessage( 'lqt-delete-parent-warning' )->parse() |
| 118 | + ) ); |
114 | 119 | } |
115 | 120 | |
116 | 121 | return true; |
Index: trunk/extensions/LiquidThreads/classes/Thread.php |
— | — | @@ -112,7 +112,7 @@ |
113 | 113 | NewMessages::writeMessageStateForUpdatedThread( $thread, $change_type, $wgUser ); |
114 | 114 | |
115 | 115 | if ( $wgUser->getOption( 'lqt-watch-threads', false ) ) { |
116 | | - $thread->topmostThread()->root()->doWatch(); |
| 116 | + Action::factory( 'watch', $thread->topmostThread()->root() )->execute(); |
117 | 117 | } |
118 | 118 | |
119 | 119 | return $thread; |
Index: trunk/extensions/MultilingualLiquidThreads/LiquidThreads/LiquidThreads.php |
— | — | @@ -70,7 +70,7 @@ |
71 | 71 | $wgHooks['ArticleDeleteComplete'][] = 'LqtDeletionController::onArticleDeleteComplete'; |
72 | 72 | $wgHooks['ArticleRevisionUndeleted'][] = 'LqtDeletionController::onArticleRevisionUndeleted'; |
73 | 73 | $wgHooks['ArticleUndelete'][] = 'LqtDeletionController::onArticleUndelete'; |
74 | | -$wgHooks['ArticleConfirmDelete'][] = 'LqtDeletionController::onArticleConfirmDelete'; |
| 74 | +$wgHooks['ActionBeforeFormDisplay'][] = 'LqtDeletionController::onActionBeforeFormDisplay'; |
75 | 75 | $wgHooks['ArticleDelete'][] = 'LqtDeletionController::onArticleDelete'; |
76 | 76 | |
77 | 77 | // Moving |
Index: trunk/extensions/MultilingualLiquidThreads/LiquidThreads/classes/DeletionController.php |
— | — | @@ -93,20 +93,25 @@ |
94 | 94 | return true; |
95 | 95 | } |
96 | 96 | |
97 | | - static function onArticleConfirmDelete( $article, $out, &$reason ) { |
98 | | - if ( $article->getTitle()->getNamespace() != NS_LQT_THREAD ) { |
| 97 | + static function onActionBeforeFormDisplay( $action, HTMLForm &$form, $page ) { |
| 98 | + if( $action != 'delete' ){ |
99 | 99 | return true; |
100 | 100 | } |
101 | 101 | |
102 | | - $thread = Threads::withRoot( $article ); |
| 102 | + if ( $page->getTitle()->getNamespace() != NS_LQT_THREAD ) { |
| 103 | + return true; |
| 104 | + } |
103 | 105 | |
| 106 | + $thread = Threads::withRoot( $page ); |
| 107 | + |
104 | 108 | if ( !$thread ) return true; |
105 | 109 | |
106 | 110 | if ( $thread->isTopmostThread() && count( $thread->replies() ) ) { |
107 | | - $out->wrapWikiMsg( |
108 | | - '<strong>$1</strong>', |
109 | | - 'lqt-delete-parent-warning' |
110 | | - ); |
| 111 | + $form->addHeaderText( Html::rawElement( |
| 112 | + 'strong', |
| 113 | + array(), |
| 114 | + wfMessage( 'lqt-delete-parent-warning' )->parse() |
| 115 | + ) ); |
111 | 116 | } |
112 | 117 | |
113 | 118 | return true; |
Index: trunk/extensions/MultilingualLiquidThreads/LiquidThreads/classes/Thread.php |
— | — | @@ -113,7 +113,7 @@ |
114 | 114 | NewMessages::writeMessageStateForUpdatedThread( $thread, $change_type, $wgUser ); |
115 | 115 | |
116 | 116 | if ( $wgUser->getOption( 'lqt-watch-threads', false ) ) { |
117 | | - $thread->topmostThread()->root()->doWatch(); |
| 117 | + Action::factory( 'watch', $thread->topmostThread()->root() )->execute(); |
118 | 118 | } |
119 | 119 | |
120 | 120 | return $thread; |
Index: trunk/extensions/PureWikiDeletion/PureWikiDeletion.php |
— | — | @@ -104,8 +104,7 @@ |
105 | 105 | return false; |
106 | 106 | } |
107 | 107 | if ( $summary == wfMsgForContent( 'autosumm-blank' ) ) { |
108 | | - $hasHistory = false; |
109 | | - $summary = $article->generateReason( $hasHistory ); |
| 108 | + $summary = DeleteAction::getAutoReason( $article ); |
110 | 109 | } |
111 | 110 | } else { |
112 | 111 | $dbr = wfGetDB( DB_SLAVE ); |
Index: trunk/extensions/PureWikiDeletion/PureWikiDeletion.hooks.php |
— | — | @@ -55,8 +55,7 @@ |
56 | 56 | $blankRevId = $revision->getId(); |
57 | 57 | if ( $text == "" ) { |
58 | 58 | if ( $summary == wfMsgForContent( 'autosumm-blank' ) ) { |
59 | | - $hasHistory = false; |
60 | | - $summary = $article->generateReason( $hasHistory ); |
| 59 | + $summary = DeleteAction::getAutoReason( $article ); |
61 | 60 | } |
62 | 61 | $dbw = wfGetDB( DB_MASTER ); |
63 | 62 | $blank_row = array( |
Index: trunk/extensions/MetavidWiki/includes/articlepages/MV_DataPage.php |
— | — | @@ -61,18 +61,18 @@ |
62 | 62 | } |
63 | 63 | |
64 | 64 | if ( $confirm ) { |
65 | | - $this->doDelete( $reason ); |
| 65 | + $this->doDeleteArticle( $reason ); |
66 | 66 | if ( $wgRequest->getCheck( 'wpWatch' ) ) { |
67 | | - $this->doWatch(); |
| 67 | + Action::factory( 'watch', $this )->execute(); |
68 | 68 | } elseif ( $this->mTitle->userIsWatching() ) { |
69 | | - $this->doUnwatch(); |
| 69 | + Action::factory( 'watch', $this )->execute(); |
70 | 70 | } |
71 | 71 | return; |
72 | 72 | } |
73 | 73 | |
74 | 74 | // Generate deletion reason |
75 | 75 | $hasHistory = false; |
76 | | - $reason = $this->generateReason( $hasHistory ); |
| 76 | + $reason = DeleteAction::getAutoReason( $this ); |
77 | 77 | |
78 | 78 | // If the page has a history, insert a warning |
79 | 79 | if ( $hasHistory && !$confirm ) { |
Index: trunk/extensions/ReplaceText/ReplaceTextJob.php |
— | — | @@ -42,8 +42,7 @@ |
43 | 43 | $create_redirect = $this->params['create_redirect']; |
44 | 44 | $this->title->moveTo( $new_title, true, $reason, $create_redirect ); |
45 | 45 | if ( $this->params['watch_page'] ) { |
46 | | - $article = new Article( $new_title ); |
47 | | - $article->doWatch(); |
| 46 | + Action::factory( 'watch', new Article( $new_title ) )->execute(); |
48 | 47 | } |
49 | 48 | $wgUser = $actual_user; |
50 | 49 | } else { |