populateLogSearch.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /**
  3. * Makes the required database updates for populating the
  4. * log_search table retroactively
  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 along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. * http://www.gnu.org/copyleft/gpl.html
  20. *
  21. * @file
  22. * @ingroup Maintenance
  23. */
  24. require_once __DIR__ . '/Maintenance.php';
  25. /**
  26. * Maintenance script that makes the required database updates for populating the
  27. * log_search table retroactively
  28. *
  29. * @ingroup Maintenance
  30. */
  31. class PopulateLogSearch extends LoggedUpdateMaintenance {
  32. private static $tableMap = [
  33. 'rev' => 'revision',
  34. 'fa' => 'filearchive',
  35. 'oi' => 'oldimage',
  36. 'ar' => 'archive'
  37. ];
  38. public function __construct() {
  39. parent::__construct();
  40. $this->addDescription( 'Migrate log params to new table and index for searching' );
  41. $this->setBatchSize( 100 );
  42. }
  43. protected function getUpdateKey() {
  44. return 'populate log_search';
  45. }
  46. protected function updateSkippedMessage() {
  47. return 'log_search table already populated.';
  48. }
  49. protected function doDBUpdates() {
  50. $db = $this->getDB( DB_MASTER );
  51. if ( !$db->tableExists( 'log_search' ) ) {
  52. $this->error( "log_search does not exist" );
  53. return false;
  54. }
  55. $start = $db->selectField( 'logging', 'MIN(log_id)', false, __FUNCTION__ );
  56. if ( !$start ) {
  57. $this->output( "Nothing to do.\n" );
  58. return true;
  59. }
  60. $end = $db->selectField( 'logging', 'MAX(log_id)', false, __FUNCTION__ );
  61. # Do remaining chunk
  62. $end += $this->mBatchSize - 1;
  63. $blockStart = $start;
  64. $blockEnd = $start + $this->mBatchSize - 1;
  65. $delTypes = [ 'delete', 'suppress' ]; // revisiondelete types
  66. while ( $blockEnd <= $end ) {
  67. $this->output( "...doing log_id from $blockStart to $blockEnd\n" );
  68. $cond = "log_id BETWEEN $blockStart AND $blockEnd";
  69. $res = $db->select( 'logging', '*', $cond, __FUNCTION__ );
  70. foreach ( $res as $row ) {
  71. // RevisionDelete logs - revisions
  72. if ( LogEventsList::typeAction( $row, $delTypes, 'revision' ) ) {
  73. $params = LogPage::extractParams( $row->log_params );
  74. // Param format: <urlparam> <item CSV> [<ofield> <nfield>]
  75. if ( count( $params ) < 2 ) {
  76. continue; // bad row?
  77. }
  78. $field = RevisionDeleter::getRelationType( $params[0] );
  79. // B/C, the params may start with a title key (<title> <urlparam> <CSV>)
  80. if ( $field == null ) {
  81. array_shift( $params ); // remove title param
  82. $field = RevisionDeleter::getRelationType( $params[0] );
  83. if ( $field == null ) {
  84. $this->output( "Invalid param type for {$row->log_id}\n" );
  85. continue; // skip this row
  86. } else {
  87. // Clean up the row...
  88. $db->update( 'logging',
  89. [ 'log_params' => implode( ',', $params ) ],
  90. [ 'log_id' => $row->log_id ] );
  91. }
  92. }
  93. $items = explode( ',', $params[1] );
  94. $log = new LogPage( $row->log_type );
  95. // Add item relations...
  96. $log->addRelations( $field, $items, $row->log_id );
  97. // Determine what table to query...
  98. $prefix = substr( $field, 0, strpos( $field, '_' ) ); // db prefix
  99. if ( !isset( self::$tableMap[$prefix] ) ) {
  100. continue; // bad row?
  101. }
  102. $table = self::$tableMap[$prefix];
  103. $userField = $prefix . '_user';
  104. $userTextField = $prefix . '_user_text';
  105. // Add item author relations...
  106. $userIds = $userIPs = [];
  107. $sres = $db->select( $table,
  108. [ $userField, $userTextField ],
  109. [ $field => $items ]
  110. );
  111. foreach ( $sres as $srow ) {
  112. if ( $srow->$userField > 0 ) {
  113. $userIds[] = intval( $srow->$userField );
  114. } elseif ( $srow->$userTextField != '' ) {
  115. $userIPs[] = $srow->$userTextField;
  116. }
  117. }
  118. // Add item author relations...
  119. $log->addRelations( 'target_author_id', $userIds, $row->log_id );
  120. $log->addRelations( 'target_author_ip', $userIPs, $row->log_id );
  121. } elseif ( LogEventsList::typeAction( $row, $delTypes, 'event' ) ) {
  122. // RevisionDelete logs - log events
  123. $params = LogPage::extractParams( $row->log_params );
  124. // Param format: <item CSV> [<ofield> <nfield>]
  125. if ( count( $params ) < 1 ) {
  126. continue; // bad row
  127. }
  128. $items = explode( ',', $params[0] );
  129. $log = new LogPage( $row->log_type );
  130. // Add item relations...
  131. $log->addRelations( 'log_id', $items, $row->log_id );
  132. // Add item author relations...
  133. $userIds = $userIPs = [];
  134. $sres = $db->select( 'logging',
  135. [ 'log_user', 'log_user_text' ],
  136. [ 'log_id' => $items ]
  137. );
  138. foreach ( $sres as $srow ) {
  139. if ( $srow->log_user > 0 ) {
  140. $userIds[] = intval( $srow->log_user );
  141. } elseif ( IP::isIPAddress( $srow->log_user_text ) ) {
  142. $userIPs[] = $srow->log_user_text;
  143. }
  144. }
  145. $log->addRelations( 'target_author_id', $userIds, $row->log_id );
  146. $log->addRelations( 'target_author_ip', $userIPs, $row->log_id );
  147. }
  148. }
  149. $blockStart += $this->mBatchSize;
  150. $blockEnd += $this->mBatchSize;
  151. wfWaitForSlaves();
  152. }
  153. $this->output( "Done populating log_search table.\n" );
  154. return true;
  155. }
  156. }
  157. $maintClass = "PopulateLogSearch";
  158. require_once RUN_MAINTENANCE_IF_MAIN;