mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo
synced 2024-11-28 01:30:15 +00:00
Merge "Moderate notifications"
This commit is contained in:
commit
95f829a3b7
3
Echo.php
3
Echo.php
|
@ -83,6 +83,9 @@ $wgHooks['ParserTestTables'][] = 'EchoHooks::onParserTestTables';
|
|||
$wgHooks['EmailUserComplete'][] = 'EchoHooks::onEmailUserComplete';
|
||||
$wgHooks['LoginFormValidErrorMessages'][] = 'EchoHooks::onLoginFormValidErrorMessages';
|
||||
$wgHooks['OutputPageCheckLastModified'][] = 'EchoHooks::onOutputPageCheckLastModified';
|
||||
$wgHooks['ArticleDeleteComplete'][] = 'EchoHooks::onArticleDeleteComplete';
|
||||
$wgHooks['ArticleUndelete'][] = 'EchoHooks::onArticleUndelete';
|
||||
|
||||
|
||||
// Extension:UserMerge support
|
||||
$wgHooks['UserMergeAccountFields'][] = 'EchoHooks::onUserMergeAccountFields';
|
||||
|
|
24
Hooks.php
24
Hooks.php
|
@ -721,12 +721,14 @@ class EchoHooks {
|
|||
continue;
|
||||
}
|
||||
|
||||
$linkFromPageId = $linksUpdate->mTitle->getArticleId();
|
||||
EchoEvent::create( array(
|
||||
'type' => 'page-linked',
|
||||
'title' => $title,
|
||||
'agent' => $user,
|
||||
'extra' => array(
|
||||
'link-from-page-id' => $linksUpdate->mTitle->getArticleId(),
|
||||
'target-page' => $linkFromPageId,
|
||||
'link-from-page-id' => $linkFromPageId,
|
||||
'revid' => $revid,
|
||||
)
|
||||
) );
|
||||
|
@ -1304,4 +1306,24 @@ class EchoHooks {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static function onArticleDeleteComplete( WikiPage &$article, User &$user, $reason, $articleId, Content $content = null, LogEntry $logEntry ) {
|
||||
\DeferredUpdates::addCallableUpdate( function () use ( $articleId ) {
|
||||
$eventMapper = new EchoEventMapper();
|
||||
$eventIds = $eventMapper->fetchIdsByPage( $articleId );
|
||||
EchoModerationController::moderate( $eventIds, true );
|
||||
} );
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function onArticleUndelete( Title $title, $create, $comment, $oldPageId ) {
|
||||
if ( $create ) {
|
||||
\DeferredUpdates::addCallableUpdate( function () use ( $oldPageId ) {
|
||||
$eventMapper = new EchoEventMapper();
|
||||
$eventIds = $eventMapper->fetchIdsByPage( $oldPageId );
|
||||
EchoModerationController::moderate( $eventIds, false );
|
||||
} );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ $wgAutoloadClasses += [
|
|||
'EchoContainmentList' => __DIR__ . '/includes/ContainmentSet.php',
|
||||
'EchoContainmentSet' => __DIR__ . '/includes/ContainmentSet.php',
|
||||
'EchoDataOutputFormatter' => __DIR__ . '/includes/DataOutputFormatter.php',
|
||||
'EchoDeferredMarkAsReadUpdate' => __DIR__ . '/includes/DeferredMarkAsReadUpdate.php',
|
||||
'EchoDeferredMarkAsDeletedUpdate' => __DIR__ . '/includes/DeferredMarkAsDeletedUpdate.php',
|
||||
'EchoDiffGroup' => __DIR__ . '/includes/DiffParser.php',
|
||||
'EchoDiffParser' => __DIR__ . '/includes/DiffParser.php',
|
||||
'EchoDiffParserTest' => __DIR__ . '/tests/phpunit/DiffParserTest.php',
|
||||
|
|
|
@ -136,7 +136,7 @@ class EchoDataOutputFormatter {
|
|||
$formatted = self::formatNotification( $event, $user, $format, $lang );
|
||||
if ( $formatted === false ) {
|
||||
// Can't display it, so mark it as read
|
||||
EchoDeferredMarkAsReadUpdate::add( $event, $user );
|
||||
EchoDeferredMarkAsDeletedUpdate::add( $event );
|
||||
return false;
|
||||
}
|
||||
$output['*'] = $formatted;
|
||||
|
|
72
includes/DeferredMarkAsDeletedUpdate.php
Normal file
72
includes/DeferredMarkAsDeletedUpdate.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
|
||||
/**
|
||||
* Mark event notifications as deleted at the end of a request. Used to queue up
|
||||
* individual events to mark due to formatting failures.
|
||||
*/
|
||||
class EchoDeferredMarkAsDeletedUpdate implements DeferrableUpdate {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $events = array();
|
||||
|
||||
/**
|
||||
* @param EchoEvent $event
|
||||
*/
|
||||
public static function add( EchoEvent $event ) {
|
||||
static $update;
|
||||
if ( $update === null ) {
|
||||
$update = new self();
|
||||
DeferredUpdates::addUpdate( $update );
|
||||
}
|
||||
$update->addInternal( $event );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EchoEvent $event
|
||||
*/
|
||||
private function addInternal( EchoEvent $event ) {
|
||||
$this->events[] = $event;
|
||||
}
|
||||
|
||||
private function filterEventsWithTitleDbLag() {
|
||||
return array_filter(
|
||||
$this->events,
|
||||
function ( EchoEvent $event ) {
|
||||
if ( !$event->getTitle() && $event->getTitle( true ) ) {
|
||||
// It is very likely this event was found
|
||||
// unreaderable because of slave lag.
|
||||
// Do not moderate it at this time.
|
||||
LoggerFactory::getInstance( 'Echo' )->debug(
|
||||
'EchoDeferredMarkAsDeletedUpdate: Event {eventId} was found unrenderable but its associated title exists on Master. Skipping.',
|
||||
array(
|
||||
'eventId' => $event->getId(),
|
||||
'title' => $event->getTitle()->getPrefixedText(),
|
||||
)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks all queued notifications as read.
|
||||
* Satisfies DeferrableUpdate interface
|
||||
*/
|
||||
public function doUpdate() {
|
||||
$events = $this->filterEventsWithTitleDbLag();
|
||||
|
||||
$eventIds = array_map(
|
||||
function ( EchoEvent $event ) {
|
||||
return $event->getId();
|
||||
},
|
||||
$events
|
||||
);
|
||||
|
||||
EchoModerationController::moderate( $eventIds, true );
|
||||
$this->events = array();
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Mark event notifications as read at the end of a request. Used to queue up
|
||||
* individual events to mark due to formatting failures or other uses.
|
||||
*/
|
||||
class EchoDeferredMarkAsReadUpdate implements DeferrableUpdate {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $events = array();
|
||||
|
||||
/**
|
||||
* @param EchoEvent $event
|
||||
* @param User $user
|
||||
*/
|
||||
public static function add( EchoEvent $event, User $user ) {
|
||||
static $update;
|
||||
if ( $update === null ) {
|
||||
$update = new self();
|
||||
DeferredUpdates::addUpdate( $update );
|
||||
}
|
||||
$update->addInternal( $event, $user );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EchoEvent $event
|
||||
* @param User $user
|
||||
*/
|
||||
private function addInternal( EchoEvent $event, User $user ) {
|
||||
$uid = $user->getId();
|
||||
if ( isset( $this->events[$uid] ) ) {
|
||||
$this->events[$uid]['eventIds'][] = $event->getId();
|
||||
} else {
|
||||
$this->events[$uid] = array(
|
||||
'user' => $user,
|
||||
'eventIds' => array( $event->getId() ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark's all queue'd notifications as read.
|
||||
* Satisfies DeferrableUpdate interface
|
||||
*/
|
||||
public function doUpdate() {
|
||||
foreach ( $this->events as $data ) {
|
||||
MWEchoNotifUser::newFromUser( $data['user'] )->markRead( $data['eventIds'] );
|
||||
}
|
||||
$this->events = array();
|
||||
}
|
||||
}
|
|
@ -381,21 +381,6 @@ class EchoNotificationController {
|
|||
return $notify->getIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Event has failed to format for the given user. Mark it as read so
|
||||
* we do not continue to notify them about this broken event.
|
||||
*
|
||||
* @param EchoEvent $event
|
||||
* @param User $user
|
||||
*/
|
||||
protected static function failFormatting( EchoEvent $event, $user ) {
|
||||
// FIXME: The only issue is that the badge count won't be up to date
|
||||
// till you refresh the page. Probably we could do this in the browser
|
||||
// so that if the formatting is empty and the notif is unread, put it
|
||||
// in the auto-mark-read APIs
|
||||
EchoDeferredMarkAsReadUpdate::add( $event, $user );
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL. Must be public to be callable by the php error handling methods.
|
||||
*
|
||||
|
|
|
@ -174,6 +174,52 @@ class EchoEventMapper extends EchoAbstractMapper {
|
|||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch events associated with a page
|
||||
*
|
||||
* @param int $pageId
|
||||
* @return EchoEvent[] Events
|
||||
*/
|
||||
public function fetchByPage( $pageId ) {
|
||||
$events = array();
|
||||
|
||||
$dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
|
||||
$res = $dbr->select(
|
||||
array( 'echo_event', 'echo_target_page' ),
|
||||
array( 'echo_event.*' ),
|
||||
array(
|
||||
'etp_page' => $pageId
|
||||
),
|
||||
__METHOD__,
|
||||
array( 'GROUP BY' => 'etp_event' ),
|
||||
array( 'echo_target_page' => array( 'JOIN', 'event_id=etp_event' ) )
|
||||
);
|
||||
if ( $res ) {
|
||||
foreach ( $res as $row ) {
|
||||
$events[] = EchoEvent::newFromRow( $row );
|
||||
}
|
||||
}
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch event IDs associated with a page
|
||||
*
|
||||
* @param int $pageId
|
||||
* @return int[] Event IDs
|
||||
*/
|
||||
public function fetchIdsByPage( $pageId ) {
|
||||
$events = $this->fetchByPage( $pageId );
|
||||
$eventIds = array_map(
|
||||
function ( EchoEvent $event ) {
|
||||
return $event->getId();
|
||||
},
|
||||
$events
|
||||
);
|
||||
return $eventIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch events unread by a user and associated with a page
|
||||
*
|
||||
|
|
|
@ -392,7 +392,7 @@ class EchoNotificationMapper extends EchoAbstractMapper {
|
|||
|
||||
$res = $dbr->select(
|
||||
array( 'echo_notification' ),
|
||||
array( 'userId' => 'notification_user' ),
|
||||
array( 'userId' => 'DISTINCT notification_user' ),
|
||||
array(
|
||||
'notification_event' => $eventIds
|
||||
),
|
||||
|
|
|
@ -465,9 +465,10 @@ class EchoEvent extends EchoAbstractEntity implements Bundleable {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Title|null
|
||||
* @param bool $fromMaster
|
||||
* @return null|Title
|
||||
*/
|
||||
public function getTitle() {
|
||||
public function getTitle( $fromMaster = false ) {
|
||||
if ( $this->title ) {
|
||||
return $this->title;
|
||||
} elseif ( $this->pageId ) {
|
||||
|
@ -477,7 +478,7 @@ class EchoEvent extends EchoAbstractEntity implements Bundleable {
|
|||
return $this->title = $title;
|
||||
}
|
||||
|
||||
return $this->title = Title::newFromID( $this->pageId );
|
||||
return $this->title = Title::newFromID( $this->pageId, $fromMaster ? Title::GAID_FOR_UPDATE : 0 );
|
||||
} elseif ( isset( $this->extra['page_title'], $this->extra['page_namespace'] ) ) {
|
||||
return $this->title = Title::makeTitleSafe(
|
||||
$this->extra['page_namespace'],
|
||||
|
|
Loading…
Reference in a new issue