r35213 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r35212‎ | r35213 | r35214 >
Date:01:11, 23 May 2008
Author:simetrical
Status:old
Tags:
Comment:
Re-commit cleaned-up version of r33565 (move subpages along with page).
* Move subpages checkbox is not shown unless the current page or its talk page actually has subpages.
* Move subpages checkbox is shown if subpages are disabled for the current namespace, provided that the talk page has subpages (but then it has no effect unless the "move talk" box is also checked).
* Unnecessary ampersands expunged, superfluous ternary operators excised.
* Crazy 1=0 query removed.
* Limit of maximum number of pages to move at once added (default 1000).

One niggling annoyance is that if the maximum number of pages is hit due to the base page having too many subpages, the talk page probably won't be moved due to the order that results are returned, which is kind of unexpected. Also, make sure the queries don't cause MySQL 4 to explode -- MySQL sometimes has problems with OR, especially older versions. Other than that, should be production-ready, I think.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/SpecialMovepage.php (modified) (history)
  • /trunk/phase3/includes/Title.php (modified) (history)
  • /trunk/phase3/languages/messages/MessagesEn.php (modified) (history)
  • /trunk/phase3/maintenance/language/messages.inc (modified) (history)

Diff [purge]

Index: trunk/phase3/RELEASE-NOTES
@@ -45,6 +45,8 @@
4646 displayed on the recent changes special pages.
4747 * The "createpage" permission is no longer required when uploading if the target
4848 image page already exists.
 49+* $wgMaximumMovedPages restricts the number of pages that can be moved at once
 50+ (default 1000) with the new subpage-move functionality of Special:Movepage.
4951
5052 === New features in 1.13 ===
5153
@@ -121,6 +123,7 @@
122124 * AutoAuthenticate hook renamed to UserLoadFromSession
123125 * (bug 13232) importScript(), importStylesheet() funcs available to custom JS
124126 * (bug 13095) Search by first letters or digits in [[Special:Categories]]
 127+* Users moving a page can now move all subpages automatically as well
125128
126129 === Bug fixes in 1.13 ===
127130
Index: trunk/phase3/includes/Title.php
@@ -1503,6 +1503,34 @@
15041504 }
15051505
15061506 /**
 1507+ * Does this have subpages? (Warning, usually requires an extra DB query.)
 1508+ * @return bool
 1509+ */
 1510+ public function hasSubpages() {
 1511+ global $wgNamespacesWithSubpages;
 1512+
 1513+ if( !isset( $wgNamespacesWithSubpages[$this->mNamespace] ) ) {
 1514+ # Duh
 1515+ return false;
 1516+ }
 1517+
 1518+ # We dynamically add a member variable for the purpose of this method
 1519+ # alone to cache the result. There's no point in having it hanging
 1520+ # around uninitialized in every Title object; therefore we only add it
 1521+ # if needed and don't declare it statically.
 1522+ if( isset( $this->mHasSubpages ) ) {
 1523+ return $this->mHasSubpages;
 1524+ }
 1525+
 1526+ $db = wfGetDB( DB_SLAVE );
 1527+ return $this->mHasSubpages = (bool)$db->selectField( 'page', '1',
 1528+ "page_namespace = {$this->mNamespace} AND page_title LIKE '"
 1529+ . $db->escapeLike( $this->mDbkeyform ) . "/%'",
 1530+ __METHOD__
 1531+ );
 1532+ }
 1533+
 1534+ /**
15071535 * Could this page contain custom CSS or JavaScript, based
15081536 * on the title?
15091537 *
Index: trunk/phase3/includes/SpecialMovepage.php
@@ -30,9 +30,7 @@
3131
3232 $f = new MovePageForm( $par );
3333
34 - if ( 'success' == $action ) {
35 - $f->showSuccess();
36 - } else if ( 'submit' == $action && $wgRequest->wasPosted()
 34+ if ( 'submit' == $action && $wgRequest->wasPosted()
3735 && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
3836 $f->doSubmit();
3937 } else {
@@ -46,7 +44,7 @@
4745 */
4846 class MovePageForm {
4947 var $oldTitle, $newTitle, $reason; # Text input
50 - var $moveTalk, $deleteAndMove;
 48+ var $moveTalk, $deleteAndMove, $moveSubpages;
5149
5250 private $watch = false;
5351
@@ -61,12 +59,13 @@
6260 } else {
6361 $this->moveTalk = $wgRequest->getBool( 'wpMovetalk', true );
6462 }
 63+ $this->moveSubpages = $wgRequest->getBool( 'wpMovesubpages', false );
6564 $this->deleteAndMove = $wgRequest->getBool( 'wpDeleteAndMove' ) && $wgRequest->getBool( 'wpConfirm' );
6665 $this->watch = $wgRequest->getCheck( 'wpWatch' );
6766 }
6867
6968 function showForm( $err, $hookErr = '' ) {
70 - global $wgOut, $wgUser;
 69+ global $wgOut, $wgUser, $wgNamespacesWithSubpages;
7170
7271 $ot = Title::newFromURL( $this->oldTitle );
7372 if( is_null( $ot ) ) {
@@ -180,7 +179,7 @@
181180 </tr>"
182181 );
183182
184 - if ( $considerTalk ) {
 183+ if( $considerTalk ) {
185184 $wgOut->addHTML( "
186185 <tr>
187186 <td></td>
@@ -191,6 +190,26 @@
192191 );
193192 }
194193
 194+ if( $ot->hasSubpages() || $ot->getTalkPage()->hasSubpages() ) {
 195+ $wgOut->addHTML( "
 196+ <tr>
 197+ <td></td>
 198+ <td class=\"mw-input\">" .
 199+ Xml::checkLabel( wfMsgHtml(
 200+ $ot->hasSubpages()
 201+ ? 'move-subpages'
 202+ : 'move-talk-subpages'
 203+ ),
 204+ 'wpMovesubpages', 'wpMovesubpages',
 205+ # Don't check the box if we only have talk subpages to
 206+ # move and we aren't moving the talk page.
 207+ $this->moveSubpages && ($ot->hasSubpages() || $this->moveTalk)
 208+ ) .
 209+ "</td>
 210+ </tr>"
 211+ );
 212+ }
 213+
195214 $watchChecked = $this->watch || $wgUser->getBoolOption( 'watchmoves' ) || $ot->userIsWatching();
196215 $wgOut->addHTML( "
197216 <tr>
@@ -266,79 +285,119 @@
267286
268287 wfRunHooks( 'SpecialMovepageAfterMove', array( &$this , &$ot , &$nt ) ) ;
269288
270 - # Move the talk page if relevant, if it exists, and if we've been told to
271 - $ott = $ot->getTalkPage();
272 - if( $ott->exists() ) {
273 - if( $this->moveTalk && !$ot->isTalkPage() && !$nt->isTalkPage() ) {
274 - $ntt = $nt->getTalkPage();
 289+ $wgOut->setPagetitle( wfMsg( 'pagemovedsub' ) );
275290
276 - # Attempt the move
277 - $error = $ott->moveTo( $ntt, true, $this->reason );
278 - if ( $error === true ) {
279 - $talkmoved = 1;
280 - wfRunHooks( 'SpecialMovepageAfterMove', array( &$this , &$ott , &$ntt ) );
281 - } else {
282 - $talkmoved = $error;
283 - }
 291+ $oldUrl = $ot->getFullUrl( 'redirect=no' );
 292+ $newUrl = $nt->getFullUrl();
 293+ $oldText = $ot->getPrefixedText();
 294+ $newText = $nt->getPrefixedText();
 295+ $oldLink = "<span class='plainlinks'>[$oldUrl $oldText]</span>";
 296+ $newLink = "<span class='plainlinks'>[$newUrl $newText]</span>";
 297+
 298+ $wgOut->addWikiMsg( 'movepage-moved', $oldLink, $newLink, $oldText, $newText );
 299+
 300+ # Now we move extra pages we've been asked to move: subpages and talk
 301+ # pages. First, if the old page or the new page is a talk page, we
 302+ # can't move any talk pages: cancel that.
 303+ if( $ot->isTalkPage() || $nt->isTalkPage() ) {
 304+ $this->moveTalk = false;
 305+ }
 306+
 307+ # Next make a list of id's. This might be marginally less efficient
 308+ # than a more direct method, but this is not a highly performance-cri-
 309+ # tical code path and readable code is more important here.
 310+ #
 311+ # Note: this query works nicely on MySQL 5, but the optimizer in MySQL
 312+ # 4 might get confused. If so, consider rewriting as a UNION.
 313+ $dbr = wfGetDB( DB_SLAVE );
 314+ if( $this->moveSubpages ) {
 315+ $conds = array(
 316+ 'page_title LIKE '.$dbr->addQuotes( $dbr->escapeLike( $ot->getDBkey() ) . '/%' )
 317+ .' OR page_title = ' . $dbr->addQuotes( $ot->getDBkey() )
 318+ );
 319+ if( $this->moveTalk ) {
 320+ $conds['page_namespace'] = array( $ot->getNamespace(),
 321+ MWNamespace::getTalk($ot->getNamespace()) );
284322 } else {
285 - # Stay silent on the subject of talk.
286 - $talkmoved = '';
 323+ $conds['page_namespace'] = $ot->getNamespace();
287324 }
288325 } else {
289 - $talkmoved = 'notalkpage';
 326+ if( $this->moveTalk ) {
 327+ $conds = array(
 328+ 'page_namespace' => MWNamespace::getTalk($ot->getNamespace()),
 329+ 'page_title' => $ot->getDBKey()
 330+ );
 331+ } else {
 332+ # Skip the query
 333+ $conds = null;
 334+ }
290335 }
291336
292 - # Deal with watches
293 - if( $this->watch ) {
294 - $wgUser->addWatch( $ot );
295 - $wgUser->addWatch( $nt );
296 - } else {
297 - $wgUser->removeWatch( $ot );
298 - $wgUser->removeWatch( $nt );
 337+ if( !is_null( $conds ) ) {
 338+ $extrapages = $dbr->select(
 339+ 'page',
 340+ array( 'page_id', 'page_namespace', 'page_title' ),
 341+ $conds,
 342+ __METHOD__
 343+ );
299344 }
300345
301 - # Give back result to user.
302 - $titleObj = SpecialPage::getTitleFor( 'Movepage' );
303 - $success = $titleObj->getFullURL(
304 - 'action=success&oldtitle=' . wfUrlencode( $ot->getPrefixedText() ) .
305 - '&newtitle=' . wfUrlencode( $nt->getPrefixedText() ) .
306 - '&talkmoved='.$talkmoved );
 346+ global $wgMaximumMovedPages, $wgLang;
 347+ $extraOutput = array();
 348+ $skin = $wgUser->getSkin();
 349+ $count = 1;
 350+ foreach( $extrapages as $row ) {
 351+ if( $row->page_id == $ot->getArticleId() ) {
 352+ # Already did this one.
 353+ continue;
 354+ }
307355
308 - $wgOut->redirect( $success );
309 - }
 356+ $oldPage = Title::newFromRow( $row );
 357+ $newPageName = preg_replace(
 358+ '#^'.preg_quote( $ot->getDBKey(), '#' ).'#',
 359+ $nt->getDBKey(),
 360+ $oldPage->getDBKey()
 361+ );
 362+ # The following line is an atrocious hack. Kill it with fire.
 363+ $newNs = $nt->getNamespace() + ($oldPage->getNamespace() & 1);
 364+ $newPage = Title::makeTitle( $newNs, $newPageName );
310365
311 - function showSuccess() {
312 - global $wgOut, $wgRequest, $wgUser;
 366+ # This was copy-pasted from Renameuser, bleh.
 367+ if ( $newPage->exists() && !$oldPage->isValidMoveTarget( $newPage ) ) {
 368+ $link = $skin->makeKnownLinkObj( $newPage );
 369+ $extraOutput []= wfMsgHtml( 'movepage-page-exists', $link );
 370+ } else {
 371+ $success = $oldPage->moveTo( $newPage, true, $this->reason );
 372+ if( $success === true ) {
 373+ $oldLink = $skin->makeKnownLinkObj( $oldPage, '', 'redirect=no' );
 374+ $newLink = $skin->makeKnownLinkObj( $newPage );
 375+ $extraOutput []= wfMsgHtml( 'movepage-page-moved', $oldLink, $newLink );
 376+ } else {
 377+ $oldLink = $skin->makeKnownLinkObj( $oldPage );
 378+ $newLink = $skin->makeLinkObj( $newPage );
 379+ $extraOutput []= wfMsgHtml( 'movepage-page-unmoved', $oldLink, $newLink );
 380+ }
 381+ }
313382
314 - $old = Title::newFromText( $wgRequest->getVal( 'oldtitle' ) );
315 - $new = Title::newFromText( $wgRequest->getVal( 'newtitle' ) );
 383+ ++$count;
 384+ if( $count >= $wgMaximumMovedPages ) {
 385+ $extraOutput []= wfMsgHtml( 'movepage-max-pages', $wgLang->formatNum( $wgMaximumMovedPages ) );
 386+ break;
 387+ }
 388+ }
316389
317 - if( is_null( $old ) || is_null( $new ) ) {
318 - throw new ErrorPageError( 'badtitle', 'badtitletext' );
 390+ if( $extraOutput !== array() ) {
 391+ $wgOut->addHTML( "<ul>\n<li>" . implode( "</li>\n<li>", $extraOutput ) . "</li>\n</ul>" );
319392 }
320393
321 - $wgOut->setPagetitle( wfMsg( 'pagemovedsub' ) );
322 -
323 - $talkmoved = $wgRequest->getVal( 'talkmoved' );
324 - $oldUrl = $old->getFullUrl( 'redirect=no' );
325 - $newUrl = $new->getFullUrl();
326 - $oldText = $old->getPrefixedText();
327 - $newText = $new->getPrefixedText();
328 - $oldLink = "<span class='plainlinks'>[$oldUrl $oldText]</span>";
329 - $newLink = "<span class='plainlinks'>[$newUrl $newText]</span>";
330 -
331 - $s = wfMsgNoTrans( 'movepage-moved', $oldLink, $newLink, $oldText, $newText );
332 -
333 - if ( $talkmoved == 1 ) {
334 - $s .= "\n\n" . wfMsgNoTrans( 'talkpagemoved' );
335 - } elseif( 'articleexists' == $talkmoved ) {
336 - $s .= "\n\n" . wfMsgNoTrans( 'talkexists' );
 394+ # Deal with watches (we don't watch subpages)
 395+ if( $this->watch ) {
 396+ $wgUser->addWatch( $ot );
 397+ $wgUser->addWatch( $nt );
337398 } else {
338 - if( !$old->isTalkPage() && $talkmoved != 'notalkpage' ) {
339 - $s .= "\n\n" . wfMsgNoTrans( 'talkpagenotmoved', wfMsgNoTrans( $talkmoved ) );
340 - }
 399+ $wgUser->removeWatch( $ot );
 400+ $wgUser->removeWatch( $nt );
341401 }
342 - $wgOut->addWikiText( $s );
343402 }
344403
345404 function showLogFragment( $title, &$out ) {
Index: trunk/phase3/includes/DefaultSettings.php
@@ -3159,18 +3159,17 @@
31603160 );
31613161
31623162 /**
3163 - * Hooks that are used for outputting exceptions
3164 - * Format is:
3165 - * $wgExceptionHooks[] = $funcname
 3163+ * Hooks that are used for outputting exceptions. Format is:
 3164+ * $wgExceptionHooks[] = $funcname
31663165 * or:
3167 - * $wgExceptionHooks[] = array( $class, $funcname )
 3166+ * $wgExceptionHooks[] = array( $class, $funcname )
31683167 * Hooks should return strings or false
31693168 */
31703169 $wgExceptionHooks = array();
31713170
31723171 /**
3173 - * Page property link table invalidation lists.
3174 - * Should only be set by extensions.
 3172+ * Page property link table invalidation lists. Should only be set by exten-
 3173+ * sions.
31753174 */
31763175 $wgPagePropLinkInvalidations = array(
31773176 'hiddencat' => 'categorylinks',
@@ -3183,22 +3182,27 @@
31843183 $wgMaxRedirectLinksRetrieved = 500;
31853184
31863185 /**
3187 - * Maximum number of calls to expensive parser functions
3188 - * such as PAGESINCATEGORY.
 3186+ * Maximum number of calls per parse to expensive parser functions such as
 3187+ * PAGESINCATEGORY.
31893188 */
31903189 $wgExpensiveParserFunctionLimit = 100;
31913190
31923191 /**
 3192+ * Maximum number of pages to move at once when moving subpages with a page.
 3193+ */
 3194+$wgMaximumMovedPages = 1000;
 3195+
 3196+/**
31933197 * Array of namespaces to generate a sitemap for when the
3194 - * maintenance/generateSitemap.php script is run, or false
3195 - * if one is to be generated for all namespaces.
 3198+ * maintenance/generateSitemap.php script is run, or false if one is to be ge-
 3199+ * nerated for all namespaces.
31963200 */
31973201 $wgSitemapNamespaces = false;
31983202
31993203
32003204 /**
3201 - * If user doesn't specify any edit summary when making a an edit,
3202 - * MediaWiki will try to automatically create one. This feature can
3203 - * be disabled by setting this variable false.
 3205+ * If user doesn't specify any edit summary when making a an edit, MediaWiki
 3206+ * will try to automatically create one. This feature can be disabled by set-
 3207+ * ting this variable false.
32043208 */
3205 -$wgUseAutomaticEditSummaries = true;
\ No newline at end of file
 3209+$wgUseAutomaticEditSummaries = true;
Index: trunk/phase3/languages/messages/MessagesEn.php
@@ -2426,8 +2426,12 @@
24272427 Please merge them manually.'''",
24282428 'movedto' => 'moved to',
24292429 'movetalk' => 'Move associated talk page',
2430 -'talkpagemoved' => 'The corresponding talk page was also moved.',
2431 -'talkpagenotmoved' => 'The corresponding talk page was <strong>not</strong> moved.',
 2430+'move-subpages' => 'Move all subpages, if applicable',
 2431+'move-talk-subpages' => 'Move all subpages of talk page, if applicable',
 2432+'movepage-page-exists' => 'The page $1 already exists and cannot be automatically overwritten.',
 2433+'movepage-page-moved' => 'The page $1 has been moved to $2.',
 2434+'movepage-page-unmoved' => 'The page $1 could not be moved to $2.',
 2435+'movepage-max-pages' => 'The maximum of $1 pages has been moved and no more will be moved automatically.',
24322436 '1movedto2' => '[[$1]] moved to [[$2]]',
24332437 '1movedto2_redir' => '[[$1]] moved to [[$2]] over redirect',
24342438 'movelogpage' => 'Move log',
Index: trunk/phase3/maintenance/language/messages.inc
@@ -1659,8 +1659,12 @@
16601660 'talkexists',
16611661 'movedto',
16621662 'movetalk',
1663 - 'talkpagemoved',
1664 - 'talkpagenotmoved',
 1663+ 'move-subpages',
 1664+ 'move-talk-subpages',
 1665+ 'movepage-page-exists',
 1666+ 'movepage-page-unmoved',
 1667+ 'movepage-page-moved',
 1668+ 'movepage-max-pages',
16651669 '1movedto2',
16661670 '1movedto2_redir',
16671671 'movelogpage',

Follow-up revisions

RevisionCommit summaryAuthorDate
r35253restore movepage-page-moved from r35213, seems to have been removed by some s...brion21:11, 23 May 2008

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r33565Users moving a page can now have all subpages automatically moved as well. D...simetrical20:40, 18 April 2008

Status & tagging log