MediaWiki  REL1_24
RevDelList.php
Go to the documentation of this file.
00001 <?php
00028 abstract class RevDelList extends RevisionListBase {
00029     function __construct( IContextSource $context, Title $title, array $ids ) {
00030         parent::__construct( $context, $title );
00031         $this->ids = $ids;
00032     }
00033 
00040     public static function getRelationType() {
00041         return null;
00042     }
00043 
00050     public static function getRestriction() {
00051         return null;
00052     }
00053 
00060     public static function getRevdelConstant() {
00061         return null;
00062     }
00063 
00072     public static function suggestTarget( $target, array $ids ) {
00073         return $target;
00074     }
00075 
00087     public function setVisibility( $params ) {
00088         $bitPars = $params['value'];
00089         $comment = $params['comment'];
00090         $perItemStatus = isset( $params['perItemStatus'] ) ? $params['perItemStatus'] : false;
00091 
00092         $this->res = false;
00093         $dbw = wfGetDB( DB_MASTER );
00094         $this->doQuery( $dbw );
00095         $dbw->begin( __METHOD__ );
00096         $status = Status::newGood();
00097         $missing = array_flip( $this->ids );
00098         $this->clearFileOps();
00099         $idsForLog = array();
00100         $authorIds = $authorIPs = array();
00101 
00102         if ( $perItemStatus ) {
00103             $status->itemStatuses = array();
00104         }
00105 
00106         // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed
00107         for ( $this->reset(); $this->current(); $this->next() ) {
00108             // @codingStandardsIgnoreEnd
00109             $item = $this->current();
00110             unset( $missing[$item->getId()] );
00111 
00112             if ( $perItemStatus ) {
00113                 $itemStatus = Status::newGood();
00114                 $status->itemStatuses[$item->getId()] = $itemStatus;
00115             } else {
00116                 $itemStatus = $status;
00117             }
00118 
00119             $oldBits = $item->getBits();
00120             // Build the actual new rev_deleted bitfield
00121             $newBits = RevisionDeleter::extractBitfield( $bitPars, $oldBits );
00122 
00123             if ( $oldBits == $newBits ) {
00124                 $itemStatus->warning( 'revdelete-no-change', $item->formatDate(), $item->formatTime() );
00125                 $status->failCount++;
00126                 continue;
00127             } elseif ( $oldBits == 0 && $newBits != 0 ) {
00128                 $opType = 'hide';
00129             } elseif ( $oldBits != 0 && $newBits == 0 ) {
00130                 $opType = 'show';
00131             } else {
00132                 $opType = 'modify';
00133             }
00134 
00135             if ( $item->isHideCurrentOp( $newBits ) ) {
00136                 // Cannot hide current version text
00137                 $itemStatus->error( 'revdelete-hide-current', $item->formatDate(), $item->formatTime() );
00138                 $status->failCount++;
00139                 continue;
00140             }
00141             if ( !$item->canView() ) {
00142                 // Cannot access this revision
00143                 $msg = ( $opType == 'show' ) ?
00144                     'revdelete-show-no-access' : 'revdelete-modify-no-access';
00145                 $itemStatus->error( $msg, $item->formatDate(), $item->formatTime() );
00146                 $status->failCount++;
00147                 continue;
00148             }
00149             // Cannot just "hide from Sysops" without hiding any fields
00150             if ( $newBits == Revision::DELETED_RESTRICTED ) {
00151                 $itemStatus->warning( 'revdelete-only-restricted', $item->formatDate(), $item->formatTime() );
00152                 $status->failCount++;
00153                 continue;
00154             }
00155 
00156             // Update the revision
00157             $ok = $item->setBits( $newBits );
00158 
00159             if ( $ok ) {
00160                 $idsForLog[] = $item->getId();
00161                 $status->successCount++;
00162                 if ( $item->getAuthorId() > 0 ) {
00163                     $authorIds[] = $item->getAuthorId();
00164                 } elseif ( IP::isIPAddress( $item->getAuthorName() ) ) {
00165                     $authorIPs[] = $item->getAuthorName();
00166                 }
00167             } else {
00168                 $itemStatus->error( 'revdelete-concurrent-change', $item->formatDate(), $item->formatTime() );
00169                 $status->failCount++;
00170             }
00171         }
00172 
00173         // Handle missing revisions
00174         foreach ( $missing as $id => $unused ) {
00175             if ( $perItemStatus ) {
00176                 $status->itemStatuses[$id] = Status::newFatal( 'revdelete-modify-missing', $id );
00177             } else {
00178                 $status->error( 'revdelete-modify-missing', $id );
00179             }
00180             $status->failCount++;
00181         }
00182 
00183         if ( $status->successCount == 0 ) {
00184             $dbw->rollback( __METHOD__ );
00185             return $status;
00186         }
00187 
00188         // Save success count
00189         $successCount = $status->successCount;
00190 
00191         // Move files, if there are any
00192         $status->merge( $this->doPreCommitUpdates() );
00193         if ( !$status->isOK() ) {
00194             // Fatal error, such as no configured archive directory
00195             $dbw->rollback( __METHOD__ );
00196             return $status;
00197         }
00198 
00199         // Log it
00200         $this->updateLog( array(
00201             'title' => $this->title,
00202             'count' => $successCount,
00203             'newBits' => $newBits,
00204             'oldBits' => $oldBits,
00205             'comment' => $comment,
00206             'ids' => $idsForLog,
00207             'authorIds' => $authorIds,
00208             'authorIPs' => $authorIPs
00209         ) );
00210         $dbw->commit( __METHOD__ );
00211 
00212         // Clear caches
00213         $status->merge( $this->doPostCommitUpdates() );
00214         return $status;
00215     }
00216 
00221     function reloadFromMaster() {
00222         $dbw = wfGetDB( DB_MASTER );
00223         $this->res = $this->doQuery( $dbw );
00224     }
00225 
00238     protected function updateLog( $params ) {
00239         // Get the URL param's corresponding DB field
00240         $field = RevisionDeleter::getRelationType( $this->getType() );
00241         if ( !$field ) {
00242             throw new MWException( "Bad log URL param type!" );
00243         }
00244         // Put things hidden from sysops in the oversight log
00245         if ( ( $params['newBits'] | $params['oldBits'] ) & $this->getSuppressBit() ) {
00246             $logType = 'suppress';
00247         } else {
00248             $logType = 'delete';
00249         }
00250         // Add params for effected page and ids
00251         $logParams = $this->getLogParams( $params );
00252         // Actually add the deletion log entry
00253         $log = new LogPage( $logType );
00254         $logid = $log->addEntry( $this->getLogAction(), $params['title'],
00255             $params['comment'], $logParams, $this->getUser() );
00256         // Allow for easy searching of deletion log items for revision/log items
00257         $log->addRelations( $field, $params['ids'], $logid );
00258         $log->addRelations( 'target_author_id', $params['authorIds'], $logid );
00259         $log->addRelations( 'target_author_ip', $params['authorIPs'], $logid );
00260     }
00261 
00266     public function getLogAction() {
00267         return 'revision';
00268     }
00269 
00275     public function getLogParams( $params ) {
00276         return array(
00277             $this->getType(),
00278             implode( ',', $params['ids'] ),
00279             "ofield={$params['oldBits']}",
00280             "nfield={$params['newBits']}"
00281         );
00282     }
00283 
00288     public function clearFileOps() {
00289     }
00290 
00296     public function doPreCommitUpdates() {
00297         return Status::newGood();
00298     }
00299 
00305     public function doPostCommitUpdates() {
00306         return Status::newGood();
00307     }
00308 
00312     abstract public function getSuppressBit();
00313 }