updateRestrictions.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. /**
  3. * Makes the required database updates for Special:ProtectedPages
  4. * to show all protected pages, even ones before the page restrictions
  5. * schema change. All remaining page_restriction column values are moved
  6. * to the new table.
  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 along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21. * http://www.gnu.org/copyleft/gpl.html
  22. *
  23. * @file
  24. * @ingroup Maintenance
  25. */
  26. require_once __DIR__ . '/Maintenance.php';
  27. /**
  28. * Maintenance script that updates page_restrictions table from
  29. * old page_restriction column.
  30. *
  31. * @ingroup Maintenance
  32. */
  33. class UpdateRestrictions extends Maintenance {
  34. public function __construct() {
  35. parent::__construct();
  36. $this->addDescription( 'Updates page_restrictions table from old page_restriction column' );
  37. $this->setBatchSize( 1000 );
  38. }
  39. public function execute() {
  40. $db = $this->getDB( DB_MASTER );
  41. $batchSize = $this->getBatchSize();
  42. if ( !$db->tableExists( 'page_restrictions' ) ) {
  43. $this->fatalError( "page_restrictions table does not exist" );
  44. }
  45. $start = $db->selectField( 'page', 'MIN(page_id)', '', __METHOD__ );
  46. if ( !$start ) {
  47. $this->fatalError( "Nothing to do." );
  48. }
  49. $end = $db->selectField( 'page', 'MAX(page_id)', '', __METHOD__ );
  50. # Do remaining chunk
  51. $end += $batchSize - 1;
  52. $blockStart = $start;
  53. $blockEnd = $start + $batchSize - 1;
  54. $encodedExpiry = 'infinity';
  55. while ( $blockEnd <= $end ) {
  56. $this->output( "...doing page_id from $blockStart to $blockEnd out of $end\n" );
  57. $cond = "page_id BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd .
  58. " AND page_restrictions !=''";
  59. $res = $db->select(
  60. 'page',
  61. [ 'page_id', 'page_namespace', 'page_restrictions' ],
  62. $cond,
  63. __METHOD__
  64. );
  65. $batch = [];
  66. foreach ( $res as $row ) {
  67. $oldRestrictions = [];
  68. foreach ( explode( ':', trim( $row->page_restrictions ) ) as $restrict ) {
  69. $temp = explode( '=', trim( $restrict ) );
  70. // Make sure we are not settings restrictions to ""
  71. if ( count( $temp ) == 1 && $temp[0] ) {
  72. // old old format should be treated as edit/move restriction
  73. $oldRestrictions["edit"] = trim( $temp[0] );
  74. $oldRestrictions["move"] = trim( $temp[0] );
  75. } elseif ( $temp[1] ) {
  76. $oldRestrictions[$temp[0]] = trim( $temp[1] );
  77. }
  78. }
  79. # Clear invalid columns
  80. if ( $row->page_namespace == NS_MEDIAWIKI ) {
  81. $db->update( 'page', [ 'page_restrictions' => '' ],
  82. [ 'page_id' => $row->page_id ], __FUNCTION__ );
  83. $this->output( "...removed dead page_restrictions column for page {$row->page_id}\n" );
  84. }
  85. # Update restrictions table
  86. foreach ( $oldRestrictions as $action => $restrictions ) {
  87. $batch[] = [
  88. 'pr_page' => $row->page_id,
  89. 'pr_type' => $action,
  90. 'pr_level' => $restrictions,
  91. 'pr_cascade' => 0,
  92. 'pr_expiry' => $encodedExpiry
  93. ];
  94. }
  95. }
  96. # We use insert() and not replace() as Article.php replaces
  97. # page_restrictions with '' when protected in the restrictions table
  98. if ( count( $batch ) ) {
  99. $ok = $db->deadlockLoop( [ $db, 'insert' ], 'page_restrictions',
  100. $batch, __FUNCTION__, [ 'IGNORE' ] );
  101. if ( !$ok ) {
  102. throw new MWException( "Deadlock loop failed wtf :(" );
  103. }
  104. }
  105. $blockStart += $batchSize - 1;
  106. $blockEnd += $batchSize - 1;
  107. wfWaitForSlaves();
  108. }
  109. $this->output( "...removing dead rows from page_restrictions\n" );
  110. // Kill any broken rows from previous imports
  111. $db->delete( 'page_restrictions', [ 'pr_level' => '' ] );
  112. // Kill other invalid rows
  113. $db->deleteJoin(
  114. 'page_restrictions',
  115. 'page',
  116. 'pr_page',
  117. 'page_id',
  118. [ 'page_namespace' => NS_MEDIAWIKI ]
  119. );
  120. $this->output( "...Done!\n" );
  121. }
  122. }
  123. $maintClass = UpdateRestrictions::class;
  124. require_once RUN_MAINTENANCE_IF_MAIN;