MediaWiki
REL1_22
|
00001 <?php 00033 class RevDel_RevisionList extends RevDel_List { 00034 var $currentRevId; 00035 00036 public function getType() { 00037 return 'revision'; 00038 } 00039 00040 public static function getRelationType() { 00041 return 'rev_id'; 00042 } 00043 00044 public static function getRestriction() { 00045 return 'deleterevision'; 00046 } 00047 00048 public static function getRevdelConstant() { 00049 return Revision::DELETED_TEXT; 00050 } 00051 00052 public static function suggestTarget( $target, array $ids ) { 00053 $rev = Revision::newFromId( $ids[0] ); 00054 return $rev ? $rev->getTitle() : $target; 00055 } 00056 00061 public function doQuery( $db ) { 00062 $ids = array_map( 'intval', $this->ids ); 00063 $live = $db->select( 00064 array( 'revision', 'page', 'user' ), 00065 array_merge( Revision::selectFields(), Revision::selectUserFields() ), 00066 array( 00067 'rev_page' => $this->title->getArticleID(), 00068 'rev_id' => $ids, 00069 ), 00070 __METHOD__, 00071 array( 'ORDER BY' => 'rev_id DESC' ), 00072 array( 00073 'page' => Revision::pageJoinCond(), 00074 'user' => Revision::userJoinCond() ) 00075 ); 00076 00077 if ( $live->numRows() >= count( $ids ) ) { 00078 // All requested revisions are live, keeps things simple! 00079 return $live; 00080 } 00081 00082 // Check if any requested revisions are available fully deleted. 00083 $archived = $db->select( array( 'archive' ), '*', 00084 array( 00085 'ar_rev_id' => $ids 00086 ), 00087 __METHOD__, 00088 array( 'ORDER BY' => 'ar_rev_id DESC' ) 00089 ); 00090 00091 if ( $archived->numRows() == 0 ) { 00092 return $live; 00093 } elseif ( $live->numRows() == 0 ) { 00094 return $archived; 00095 } else { 00096 // Combine the two! Whee 00097 $rows = array(); 00098 foreach ( $live as $row ) { 00099 $rows[$row->rev_id] = $row; 00100 } 00101 foreach ( $archived as $row ) { 00102 $rows[$row->ar_rev_id] = $row; 00103 } 00104 krsort( $rows ); 00105 return new FakeResultWrapper( array_values( $rows ) ); 00106 } 00107 } 00108 00109 public function newItem( $row ) { 00110 if ( isset( $row->rev_id ) ) { 00111 return new RevDel_RevisionItem( $this, $row ); 00112 } elseif ( isset( $row->ar_rev_id ) ) { 00113 return new RevDel_ArchivedRevisionItem( $this, $row ); 00114 } else { 00115 // This shouldn't happen. :) 00116 throw new MWException( 'Invalid row type in RevDel_RevisionList' ); 00117 } 00118 } 00119 00120 public function getCurrent() { 00121 if ( is_null( $this->currentRevId ) ) { 00122 $dbw = wfGetDB( DB_MASTER ); 00123 $this->currentRevId = $dbw->selectField( 00124 'page', 'page_latest', $this->title->pageCond(), __METHOD__ ); 00125 } 00126 return $this->currentRevId; 00127 } 00128 00129 public function getSuppressBit() { 00130 return Revision::DELETED_RESTRICTED; 00131 } 00132 00133 public function doPreCommitUpdates() { 00134 $this->title->invalidateCache(); 00135 return Status::newGood(); 00136 } 00137 00138 public function doPostCommitUpdates() { 00139 $this->title->purgeSquid(); 00140 // Extensions that require referencing previous revisions may need this 00141 wfRunHooks( 'ArticleRevisionVisibilitySet', array( &$this->title ) ); 00142 return Status::newGood(); 00143 } 00144 } 00145 00149 class RevDel_RevisionItem extends RevDel_Item { 00150 var $revision; 00151 00152 public function __construct( $list, $row ) { 00153 parent::__construct( $list, $row ); 00154 $this->revision = new Revision( $row ); 00155 } 00156 00157 public function getIdField() { 00158 return 'rev_id'; 00159 } 00160 00161 public function getTimestampField() { 00162 return 'rev_timestamp'; 00163 } 00164 00165 public function getAuthorIdField() { 00166 return 'rev_user'; 00167 } 00168 00169 public function getAuthorNameField() { 00170 return 'user_name'; // see Revision::selectUserFields() 00171 } 00172 00173 public function canView() { 00174 return $this->revision->userCan( Revision::DELETED_RESTRICTED, $this->list->getUser() ); 00175 } 00176 00177 public function canViewContent() { 00178 return $this->revision->userCan( Revision::DELETED_TEXT, $this->list->getUser() ); 00179 } 00180 00181 public function getBits() { 00182 return $this->revision->getVisibility(); 00183 } 00184 00185 public function setBits( $bits ) { 00186 $dbw = wfGetDB( DB_MASTER ); 00187 // Update revision table 00188 $dbw->update( 'revision', 00189 array( 'rev_deleted' => $bits ), 00190 array( 00191 'rev_id' => $this->revision->getId(), 00192 'rev_page' => $this->revision->getPage(), 00193 'rev_deleted' => $this->getBits() 00194 ), 00195 __METHOD__ 00196 ); 00197 if ( !$dbw->affectedRows() ) { 00198 // Concurrent fail! 00199 return false; 00200 } 00201 // Update recentchanges table 00202 $dbw->update( 'recentchanges', 00203 array( 00204 'rc_deleted' => $bits, 00205 'rc_patrolled' => 1 00206 ), 00207 array( 00208 'rc_this_oldid' => $this->revision->getId(), // condition 00209 // non-unique timestamp index 00210 'rc_timestamp' => $dbw->timestamp( $this->revision->getTimestamp() ), 00211 ), 00212 __METHOD__ 00213 ); 00214 return true; 00215 } 00216 00217 public function isDeleted() { 00218 return $this->revision->isDeleted( Revision::DELETED_TEXT ); 00219 } 00220 00221 public function isHideCurrentOp( $newBits ) { 00222 return ( $newBits & Revision::DELETED_TEXT ) 00223 && $this->list->getCurrent() == $this->getId(); 00224 } 00225 00231 protected function getRevisionLink() { 00232 $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate( 00233 $this->revision->getTimestamp(), $this->list->getUser() ) ); 00234 00235 if ( $this->isDeleted() && !$this->canViewContent() ) { 00236 return $date; 00237 } 00238 return Linker::linkKnown( 00239 $this->list->title, 00240 $date, 00241 array(), 00242 array( 00243 'oldid' => $this->revision->getId(), 00244 'unhide' => 1 00245 ) 00246 ); 00247 } 00248 00254 protected function getDiffLink() { 00255 if ( $this->isDeleted() && !$this->canViewContent() ) { 00256 return $this->list->msg( 'diff' )->escaped(); 00257 } else { 00258 return Linker::linkKnown( 00259 $this->list->title, 00260 $this->list->msg( 'diff' )->escaped(), 00261 array(), 00262 array( 00263 'diff' => $this->revision->getId(), 00264 'oldid' => 'prev', 00265 'unhide' => 1 00266 ) 00267 ); 00268 } 00269 } 00270 00271 public function getHTML() { 00272 $difflink = $this->list->msg( 'parentheses' ) 00273 ->rawParams( $this->getDiffLink() )->escaped(); 00274 $revlink = $this->getRevisionLink(); 00275 $userlink = Linker::revUserLink( $this->revision ); 00276 $comment = Linker::revComment( $this->revision ); 00277 if ( $this->isDeleted() ) { 00278 $revlink = "<span class=\"history-deleted\">$revlink</span>"; 00279 } 00280 return "<li>$difflink $revlink $userlink $comment</li>"; 00281 } 00282 } 00283 00287 class RevDel_ArchiveList extends RevDel_RevisionList { 00288 public function getType() { 00289 return 'archive'; 00290 } 00291 00292 public static function getRelationType() { 00293 return 'ar_timestamp'; 00294 } 00295 00300 public function doQuery( $db ) { 00301 $timestamps = array(); 00302 foreach ( $this->ids as $id ) { 00303 $timestamps[] = $db->timestamp( $id ); 00304 } 00305 return $db->select( 'archive', '*', 00306 array( 00307 'ar_namespace' => $this->title->getNamespace(), 00308 'ar_title' => $this->title->getDBkey(), 00309 'ar_timestamp' => $timestamps 00310 ), 00311 __METHOD__, 00312 array( 'ORDER BY' => 'ar_timestamp DESC' ) 00313 ); 00314 } 00315 00316 public function newItem( $row ) { 00317 return new RevDel_ArchiveItem( $this, $row ); 00318 } 00319 00320 public function doPreCommitUpdates() { 00321 return Status::newGood(); 00322 } 00323 00324 public function doPostCommitUpdates() { 00325 return Status::newGood(); 00326 } 00327 } 00328 00332 class RevDel_ArchiveItem extends RevDel_RevisionItem { 00333 public function __construct( $list, $row ) { 00334 RevDel_Item::__construct( $list, $row ); 00335 $this->revision = Revision::newFromArchiveRow( $row, 00336 array( 'page' => $this->list->title->getArticleID() ) ); 00337 } 00338 00339 public function getIdField() { 00340 return 'ar_timestamp'; 00341 } 00342 00343 public function getTimestampField() { 00344 return 'ar_timestamp'; 00345 } 00346 00347 public function getAuthorIdField() { 00348 return 'ar_user'; 00349 } 00350 00351 public function getAuthorNameField() { 00352 return 'ar_user_text'; 00353 } 00354 00355 public function getId() { 00356 # Convert DB timestamp to MW timestamp 00357 return $this->revision->getTimestamp(); 00358 } 00359 00360 public function setBits( $bits ) { 00361 $dbw = wfGetDB( DB_MASTER ); 00362 $dbw->update( 'archive', 00363 array( 'ar_deleted' => $bits ), 00364 array( 00365 'ar_namespace' => $this->list->title->getNamespace(), 00366 'ar_title' => $this->list->title->getDBkey(), 00367 // use timestamp for index 00368 'ar_timestamp' => $this->row->ar_timestamp, 00369 'ar_rev_id' => $this->row->ar_rev_id, 00370 'ar_deleted' => $this->getBits() 00371 ), 00372 __METHOD__ ); 00373 return (bool)$dbw->affectedRows(); 00374 } 00375 00376 protected function getRevisionLink() { 00377 $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate( 00378 $this->revision->getTimestamp(), $this->list->getUser() ) ); 00379 00380 if ( $this->isDeleted() && !$this->canViewContent() ) { 00381 return $date; 00382 } 00383 00384 return Linker::link( 00385 SpecialPage::getTitleFor( 'Undelete' ), 00386 $date, 00387 array(), 00388 array( 00389 'target' => $this->list->title->getPrefixedText(), 00390 'timestamp' => $this->revision->getTimestamp() 00391 ) 00392 ); 00393 } 00394 00395 protected function getDiffLink() { 00396 if ( $this->isDeleted() && !$this->canViewContent() ) { 00397 return $this->list->msg( 'diff' )->escaped(); 00398 } 00399 00400 return Linker::link( 00401 SpecialPage::getTitleFor( 'Undelete' ), 00402 $this->list->msg( 'diff' )->escaped(), 00403 array(), 00404 array( 00405 'target' => $this->list->title->getPrefixedText(), 00406 'diff' => 'prev', 00407 'timestamp' => $this->revision->getTimestamp() 00408 ) 00409 ); 00410 } 00411 } 00412 00417 class RevDel_ArchivedRevisionItem extends RevDel_ArchiveItem { 00418 public function __construct( $list, $row ) { 00419 RevDel_Item::__construct( $list, $row ); 00420 00421 $this->revision = Revision::newFromArchiveRow( $row, 00422 array( 'page' => $this->list->title->getArticleID() ) ); 00423 } 00424 00425 public function getIdField() { 00426 return 'ar_rev_id'; 00427 } 00428 00429 public function getId() { 00430 return $this->revision->getId(); 00431 } 00432 00433 public function setBits( $bits ) { 00434 $dbw = wfGetDB( DB_MASTER ); 00435 $dbw->update( 'archive', 00436 array( 'ar_deleted' => $bits ), 00437 array( 'ar_rev_id' => $this->row->ar_rev_id, 00438 'ar_deleted' => $this->getBits() 00439 ), 00440 __METHOD__ ); 00441 return (bool)$dbw->affectedRows(); 00442 } 00443 } 00444 00448 class RevDel_FileList extends RevDel_List { 00449 public function getType() { 00450 return 'oldimage'; 00451 } 00452 00453 public static function getRelationType() { 00454 return 'oi_archive_name'; 00455 } 00456 00457 public static function getRestriction() { 00458 return 'deleterevision'; 00459 } 00460 00461 public static function getRevdelConstant() { 00462 return File::DELETED_FILE; 00463 } 00464 00465 var $storeBatch, $deleteBatch, $cleanupBatch; 00466 00471 public function doQuery( $db ) { 00472 $archiveNames = array(); 00473 foreach ( $this->ids as $timestamp ) { 00474 $archiveNames[] = $timestamp . '!' . $this->title->getDBkey(); 00475 } 00476 return $db->select( 00477 'oldimage', 00478 OldLocalFile::selectFields(), 00479 array( 00480 'oi_name' => $this->title->getDBkey(), 00481 'oi_archive_name' => $archiveNames 00482 ), 00483 __METHOD__, 00484 array( 'ORDER BY' => 'oi_timestamp DESC' ) 00485 ); 00486 } 00487 00488 public function newItem( $row ) { 00489 return new RevDel_FileItem( $this, $row ); 00490 } 00491 00492 public function clearFileOps() { 00493 $this->deleteBatch = array(); 00494 $this->storeBatch = array(); 00495 $this->cleanupBatch = array(); 00496 } 00497 00498 public function doPreCommitUpdates() { 00499 $status = Status::newGood(); 00500 $repo = RepoGroup::singleton()->getLocalRepo(); 00501 if ( $this->storeBatch ) { 00502 $status->merge( $repo->storeBatch( $this->storeBatch, FileRepo::OVERWRITE_SAME ) ); 00503 } 00504 if ( !$status->isOK() ) { 00505 return $status; 00506 } 00507 if ( $this->deleteBatch ) { 00508 $status->merge( $repo->deleteBatch( $this->deleteBatch ) ); 00509 } 00510 if ( !$status->isOK() ) { 00511 // Running cleanupDeletedBatch() after a failed storeBatch() with the DB already 00512 // modified (but destined for rollback) causes data loss 00513 return $status; 00514 } 00515 if ( $this->cleanupBatch ) { 00516 $status->merge( $repo->cleanupDeletedBatch( $this->cleanupBatch ) ); 00517 } 00518 return $status; 00519 } 00520 00521 public function doPostCommitUpdates() { 00522 global $wgUseSquid; 00523 $file = wfLocalFile( $this->title ); 00524 $file->purgeCache(); 00525 $file->purgeDescription(); 00526 $purgeUrls = array(); 00527 foreach ( $this->ids as $timestamp ) { 00528 $archiveName = $timestamp . '!' . $this->title->getDBkey(); 00529 $file->purgeOldThumbnails( $archiveName ); 00530 $purgeUrls[] = $file->getArchiveUrl( $archiveName ); 00531 } 00532 if ( $wgUseSquid ) { 00533 // purge full images from cache 00534 SquidUpdate::purge( $purgeUrls ); 00535 } 00536 return Status::newGood(); 00537 } 00538 00539 public function getSuppressBit() { 00540 return File::DELETED_RESTRICTED; 00541 } 00542 } 00543 00547 class RevDel_FileItem extends RevDel_Item { 00548 00552 var $file; 00553 00554 public function __construct( $list, $row ) { 00555 parent::__construct( $list, $row ); 00556 $this->file = RepoGroup::singleton()->getLocalRepo()->newFileFromRow( $row ); 00557 } 00558 00559 public function getIdField() { 00560 return 'oi_archive_name'; 00561 } 00562 00563 public function getTimestampField() { 00564 return 'oi_timestamp'; 00565 } 00566 00567 public function getAuthorIdField() { 00568 return 'oi_user'; 00569 } 00570 00571 public function getAuthorNameField() { 00572 return 'oi_user_text'; 00573 } 00574 00575 public function getId() { 00576 $parts = explode( '!', $this->row->oi_archive_name ); 00577 return $parts[0]; 00578 } 00579 00580 public function canView() { 00581 return $this->file->userCan( File::DELETED_RESTRICTED, $this->list->getUser() ); 00582 } 00583 00584 public function canViewContent() { 00585 return $this->file->userCan( File::DELETED_FILE, $this->list->getUser() ); 00586 } 00587 00588 public function getBits() { 00589 return $this->file->getVisibility(); 00590 } 00591 00592 public function setBits( $bits ) { 00593 # Queue the file op 00594 # @todo FIXME: Move to LocalFile.php 00595 if ( $this->isDeleted() ) { 00596 if ( $bits & File::DELETED_FILE ) { 00597 # Still deleted 00598 } else { 00599 # Newly undeleted 00600 $key = $this->file->getStorageKey(); 00601 $srcRel = $this->file->repo->getDeletedHashPath( $key ) . $key; 00602 $this->list->storeBatch[] = array( 00603 $this->file->repo->getVirtualUrl( 'deleted' ) . '/' . $srcRel, 00604 'public', 00605 $this->file->getRel() 00606 ); 00607 $this->list->cleanupBatch[] = $key; 00608 } 00609 } elseif ( $bits & File::DELETED_FILE ) { 00610 # Newly deleted 00611 $key = $this->file->getStorageKey(); 00612 $dstRel = $this->file->repo->getDeletedHashPath( $key ) . $key; 00613 $this->list->deleteBatch[] = array( $this->file->getRel(), $dstRel ); 00614 } 00615 00616 # Do the database operations 00617 $dbw = wfGetDB( DB_MASTER ); 00618 $dbw->update( 'oldimage', 00619 array( 'oi_deleted' => $bits ), 00620 array( 00621 'oi_name' => $this->row->oi_name, 00622 'oi_timestamp' => $this->row->oi_timestamp, 00623 'oi_deleted' => $this->getBits() 00624 ), 00625 __METHOD__ 00626 ); 00627 return (bool)$dbw->affectedRows(); 00628 } 00629 00630 public function isDeleted() { 00631 return $this->file->isDeleted( File::DELETED_FILE ); 00632 } 00633 00639 protected function getLink() { 00640 $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate( 00641 $this->file->getTimestamp(), $this->list->getUser() ) ); 00642 00643 if ( !$this->isDeleted() ) { 00644 # Regular files... 00645 return Html::rawElement( 'a', array( 'href' => $this->file->getUrl() ), $date ); 00646 } 00647 00648 # Hidden files... 00649 if ( !$this->canViewContent() ) { 00650 $link = $date; 00651 } else { 00652 $link = Linker::link( 00653 SpecialPage::getTitleFor( 'Revisiondelete' ), 00654 $date, 00655 array(), 00656 array( 00657 'target' => $this->list->title->getPrefixedText(), 00658 'file' => $this->file->getArchiveName(), 00659 'token' => $this->list->getUser()->getEditToken( 00660 $this->file->getArchiveName() ) 00661 ) 00662 ); 00663 } 00664 return '<span class="history-deleted">' . $link . '</span>'; 00665 } 00670 protected function getUserTools() { 00671 if ( $this->file->userCan( Revision::DELETED_USER, $this->list->getUser() ) ) { 00672 $link = Linker::userLink( $this->file->user, $this->file->user_text ) . 00673 Linker::userToolLinks( $this->file->user, $this->file->user_text ); 00674 } else { 00675 $link = $this->list->msg( 'rev-deleted-user' )->escaped(); 00676 } 00677 if ( $this->file->isDeleted( Revision::DELETED_USER ) ) { 00678 return '<span class="history-deleted">' . $link . '</span>'; 00679 } 00680 return $link; 00681 } 00682 00689 protected function getComment() { 00690 if ( $this->file->userCan( File::DELETED_COMMENT, $this->list->getUser() ) ) { 00691 $block = Linker::commentBlock( $this->file->description ); 00692 } else { 00693 $block = ' ' . $this->list->msg( 'rev-deleted-comment' )->escaped(); 00694 } 00695 if ( $this->file->isDeleted( File::DELETED_COMMENT ) ) { 00696 return "<span class=\"history-deleted\">$block</span>"; 00697 } 00698 return $block; 00699 } 00700 00701 public function getHTML() { 00702 $data = 00703 $this->list->msg( 'widthheight' )->numParams( 00704 $this->file->getWidth(), $this->file->getHeight() )->text() . 00705 ' (' . $this->list->msg( 'nbytes' )->numParams( $this->file->getSize() )->text() . ')'; 00706 00707 return '<li>' . $this->getLink() . ' ' . $this->getUserTools() . ' ' . 00708 $data . ' ' . $this->getComment() . '</li>'; 00709 } 00710 } 00711 00715 class RevDel_ArchivedFileList extends RevDel_FileList { 00716 public function getType() { 00717 return 'filearchive'; 00718 } 00719 00720 public static function getRelationType() { 00721 return 'fa_id'; 00722 } 00723 00728 public function doQuery( $db ) { 00729 $ids = array_map( 'intval', $this->ids ); 00730 return $db->select( 00731 'filearchive', 00732 ArchivedFile::selectFields(), 00733 array( 00734 'fa_name' => $this->title->getDBkey(), 00735 'fa_id' => $ids 00736 ), 00737 __METHOD__, 00738 array( 'ORDER BY' => 'fa_id DESC' ) 00739 ); 00740 } 00741 00742 public function newItem( $row ) { 00743 return new RevDel_ArchivedFileItem( $this, $row ); 00744 } 00745 } 00746 00750 class RevDel_ArchivedFileItem extends RevDel_FileItem { 00751 public function __construct( $list, $row ) { 00752 RevDel_Item::__construct( $list, $row ); 00753 $this->file = ArchivedFile::newFromRow( $row ); 00754 } 00755 00756 public function getIdField() { 00757 return 'fa_id'; 00758 } 00759 00760 public function getTimestampField() { 00761 return 'fa_timestamp'; 00762 } 00763 00764 public function getAuthorIdField() { 00765 return 'fa_user'; 00766 } 00767 00768 public function getAuthorNameField() { 00769 return 'fa_user_text'; 00770 } 00771 00772 public function getId() { 00773 return $this->row->fa_id; 00774 } 00775 00776 public function setBits( $bits ) { 00777 $dbw = wfGetDB( DB_MASTER ); 00778 $dbw->update( 'filearchive', 00779 array( 'fa_deleted' => $bits ), 00780 array( 00781 'fa_id' => $this->row->fa_id, 00782 'fa_deleted' => $this->getBits(), 00783 ), 00784 __METHOD__ 00785 ); 00786 return (bool)$dbw->affectedRows(); 00787 } 00788 00789 protected function getLink() { 00790 $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate( 00791 $this->file->getTimestamp(), $this->list->getUser() ) ); 00792 00793 # Hidden files... 00794 if ( !$this->canViewContent() ) { 00795 $link = $date; 00796 } else { 00797 $undelete = SpecialPage::getTitleFor( 'Undelete' ); 00798 $key = $this->file->getKey(); 00799 $link = Linker::link( $undelete, $date, array(), 00800 array( 00801 'target' => $this->list->title->getPrefixedText(), 00802 'file' => $key, 00803 'token' => $this->list->getUser()->getEditToken( $key ) 00804 ) 00805 ); 00806 } 00807 if ( $this->isDeleted() ) { 00808 $link = '<span class="history-deleted">' . $link . '</span>'; 00809 } 00810 return $link; 00811 } 00812 } 00813 00817 class RevDel_LogList extends RevDel_List { 00818 public function getType() { 00819 return 'logging'; 00820 } 00821 00822 public static function getRelationType() { 00823 return 'log_id'; 00824 } 00825 00826 public static function getRestriction() { 00827 return 'deletelogentry'; 00828 } 00829 00830 public static function getRevdelConstant() { 00831 return LogPage::DELETED_ACTION; 00832 } 00833 00834 public static function suggestTarget( $target, array $ids ) { 00835 $result = wfGetDB( DB_SLAVE )->select( 'logging', 00836 'log_type', 00837 array( 'log_id' => $ids ), 00838 __METHOD__, 00839 array( 'DISTINCT' ) 00840 ); 00841 if ( $result->numRows() == 1 ) { 00842 // If there's only one type, the target can be set to include it. 00843 return SpecialPage::getTitleFor( 'Log', $result->current()->log_type ); 00844 } 00845 return SpecialPage::getTitleFor( 'Log' ); 00846 } 00847 00852 public function doQuery( $db ) { 00853 $ids = array_map( 'intval', $this->ids ); 00854 return $db->select( 'logging', '*', 00855 array( 'log_id' => $ids ), 00856 __METHOD__, 00857 array( 'ORDER BY' => 'log_id DESC' ) 00858 ); 00859 } 00860 00861 public function newItem( $row ) { 00862 return new RevDel_LogItem( $this, $row ); 00863 } 00864 00865 public function getSuppressBit() { 00866 return Revision::DELETED_RESTRICTED; 00867 } 00868 00869 public function getLogAction() { 00870 return 'event'; 00871 } 00872 00873 public function getLogParams( $params ) { 00874 return array( 00875 implode( ',', $params['ids'] ), 00876 "ofield={$params['oldBits']}", 00877 "nfield={$params['newBits']}" 00878 ); 00879 } 00880 } 00881 00885 class RevDel_LogItem extends RevDel_Item { 00886 public function getIdField() { 00887 return 'log_id'; 00888 } 00889 00890 public function getTimestampField() { 00891 return 'log_timestamp'; 00892 } 00893 00894 public function getAuthorIdField() { 00895 return 'log_user'; 00896 } 00897 00898 public function getAuthorNameField() { 00899 return 'log_user_text'; 00900 } 00901 00902 public function canView() { 00903 return LogEventsList::userCan( $this->row, Revision::DELETED_RESTRICTED, $this->list->getUser() ); 00904 } 00905 00906 public function canViewContent() { 00907 return true; // none 00908 } 00909 00910 public function getBits() { 00911 return $this->row->log_deleted; 00912 } 00913 00914 public function setBits( $bits ) { 00915 $dbw = wfGetDB( DB_MASTER ); 00916 $dbw->update( 'recentchanges', 00917 array( 00918 'rc_deleted' => $bits, 00919 'rc_patrolled' => 1 00920 ), 00921 array( 00922 'rc_logid' => $this->row->log_id, 00923 'rc_timestamp' => $this->row->log_timestamp // index 00924 ), 00925 __METHOD__ 00926 ); 00927 $dbw->update( 'logging', 00928 array( 'log_deleted' => $bits ), 00929 array( 00930 'log_id' => $this->row->log_id, 00931 'log_deleted' => $this->getBits() 00932 ), 00933 __METHOD__ 00934 ); 00935 return (bool)$dbw->affectedRows(); 00936 } 00937 00938 public function getHTML() { 00939 $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate( 00940 $this->row->log_timestamp, $this->list->getUser() ) ); 00941 $title = Title::makeTitle( $this->row->log_namespace, $this->row->log_title ); 00942 $formatter = LogFormatter::newFromRow( $this->row ); 00943 $formatter->setContext( $this->list->getContext() ); 00944 $formatter->setAudience( LogFormatter::FOR_THIS_USER ); 00945 00946 // Log link for this page 00947 $loglink = Linker::link( 00948 SpecialPage::getTitleFor( 'Log' ), 00949 $this->list->msg( 'log' )->escaped(), 00950 array(), 00951 array( 'page' => $title->getPrefixedText() ) 00952 ); 00953 $loglink = $this->list->msg( 'parentheses' )->rawParams( $loglink )->escaped(); 00954 // User links and action text 00955 $action = $formatter->getActionText(); 00956 // Comment 00957 $comment = $this->list->getLanguage()->getDirMark() . Linker::commentBlock( $this->row->log_comment ); 00958 if ( LogEventsList::isDeleted( $this->row, LogPage::DELETED_COMMENT ) ) { 00959 $comment = '<span class="history-deleted">' . $comment . '</span>'; 00960 } 00961 00962 return "<li>$loglink $date $action $comment</li>"; 00963 } 00964 }