Merge "Create HookRunner class and the hook handler interfaces"

This commit is contained in:
jenkins-bot 2023-08-16 05:26:06 +00:00 committed by Gerrit Code Review
commit 078788f411
20 changed files with 428 additions and 23 deletions

View file

@ -15,7 +15,7 @@
"license-name": "MIT",
"type": "specialpage",
"requires": {
"MediaWiki": ">= 1.40.0"
"MediaWiki": ">= 1.41.0"
},
"APIMetaModules": {
"notifications": {

View file

@ -12,6 +12,7 @@ use EchoServices;
use InvalidArgumentException;
use Iterator;
use MapCacheLRU;
use MediaWiki\Extension\Notifications\Hooks\HookRunner;
use MediaWiki\Extension\Notifications\Iterator\FilteredSequentialIterator;
use MediaWiki\Extension\Notifications\Jobs\NotificationDeleteJob;
use MediaWiki\Extension\Notifications\Jobs\NotificationJob;
@ -128,7 +129,7 @@ class NotificationController {
$userIds = [];
$userIdsCount = 0;
$services = MediaWikiServices::getInstance();
$hookContainer = $services->getHookContainer();
$hookRunner = new HookRunner( $services->getHookContainer() );
$userOptionsLookup = $services->getUserOptionsLookup();
/** @var bool|null $hasMinorRevision */
$hasMinorRevision = null;
@ -147,7 +148,7 @@ class NotificationController {
$userNotifyTypes = array_diff( $userNotifyTypes, [ 'email' ] );
}
}
$hookContainer->run( 'EchoGetNotificationTypes', [ $user, $event, &$userNotifyTypes ] );
$hookRunner->onEchoGetNotificationTypes( $user, $event, $userNotifyTypes );
// types such as web, email, etc
foreach ( $userNotifyTypes as $type ) {
@ -489,8 +490,8 @@ class NotificationController {
// Hook for injecting more users.
// @deprecated
$users = [];
MediaWikiServices::getInstance()->getHookContainer()->run( 'EchoGetDefaultNotifiedUsers', [ $event, &$users ] );
// @phan-suppress-next-line PhanImpossibleCondition May be set by hook
( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )
->onEchoGetDefaultNotifiedUsers( $event, $users );
if ( $users ) {
$notify->add( $users );
}

View file

@ -1,5 +1,6 @@
<?php
use MediaWiki\Extension\Notifications\Hooks\HookRunner;
use MediaWiki\Extension\Notifications\Model\Event;
use MediaWiki\MediaWikiServices;
use MediaWiki\Revision\RevisionRecord;
@ -177,7 +178,8 @@ abstract class EchoDiscussionParser {
// Allow extensions to generate more events for a revision, and de-duplicate
// against the standard events created above.
$services->getHookContainer()->run( 'EchoGetEventsForRevision', [ &$events, $revision, $isRevert ] );
( new HookRunner( $services->getHookContainer() ) )
->onEchoGetEventsForRevision( $events, $revision, $isRevert );
// Create events
foreach ( $events as $event ) {

View file

@ -26,6 +26,7 @@ use MediaWiki\DAO\WikiAwareEntity;
use MediaWiki\Extension\Notifications\Controller\ModerationController;
use MediaWiki\Extension\Notifications\Controller\NotificationController;
use MediaWiki\Extension\Notifications\Formatters\EchoEventPresentationModel;
use MediaWiki\Extension\Notifications\Hooks\HookRunner;
use MediaWiki\Extension\Notifications\Mapper\EventMapper;
use MediaWiki\Extension\Notifications\Mapper\NotificationMapper;
use MediaWiki\Extension\Notifications\Model\Event;
@ -197,8 +198,8 @@ class Hooks implements
$wgEnableUserEmail;
// allow extensions to define their own event
MediaWikiServices::getInstance()->getHookContainer()->run( 'BeforeCreateEchoEvent',
[ &$wgEchoNotifications, &$wgEchoNotificationCategories, &$wgEchoNotificationIcons ] );
( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )->onBeforeCreateEchoEvent(
$wgEchoNotifications, $wgEchoNotificationCategories, $wgEchoNotificationIcons );
// Only allow mention status notifications when enabled
if ( !$wgEchoMentionStatusNotifications ) {
@ -644,7 +645,7 @@ class Hooks implements
/**
* Handler for EchoAbortEmailNotification hook
* @param User $user
* @param UserIdentity $user
* @param Event $event
* @return bool true - send email, false - do not send email
*/
@ -1090,8 +1091,8 @@ class Hooks implements
if (
$mytalk &&
self::shouldDisplayTalkAlert( $user, $title ) &&
MediaWikiServices::getInstance()
->getHookContainer()->run( 'BeforeDisplayOrangeAlert', [ $user, $title ] )
( new HookRunner( MediaWikiServices::getInstance()
->getHookContainer() ) )->onBeforeDisplayOrangeAlert( $user, $title )
) {
// Create new talk alert inheriting from the talk link data.
$links['notifications']['talk-alert'] = array_merge(
@ -1263,7 +1264,8 @@ class Hooks implements
// notifications for talk page messages, disable the new messages alert.
if ( $user->isRegistered()
&& isset( $wgEchoNotifications['edit-user-talk'] )
&& MediaWikiServices::getInstance()->getHookContainer()->run( 'EchoCanAbortNewMessagesAlert' )
&& ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )
->onEchoCanAbortNewMessagesAlert()
) {
// hide new messages alert
return false;

View file

@ -0,0 +1,26 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "BeforeCreateEchoEvent" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface BeforeCreateEchoEventHook {
/**
* Called on setup of Echo extension
*
* @param array &$notifications To expand $wgEchoNnotifications
* @param array &$notificationCategories To expand $wgEchoNotificationCategories
* @param array &$notificationIcons To expand $wgEchoNotificationIcons
* @return bool|void True or no return value to continue or false to abort
*/
public function onBeforeCreateEchoEvent(
array &$notifications,
array &$notificationCategories,
array &$notificationIcons
);
}

View file

@ -0,0 +1,22 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Title\Title;
use User;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "BeforeDisplayOrangeAlert" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface BeforeDisplayOrangeAlertHook {
/**
* @param User $user
* @param Title $title
* @return bool|void True or no return value to continue or false to abort
*/
public function onBeforeDisplayOrangeAlert( User $user, Title $title );
}

View file

@ -0,0 +1,20 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Extension\Notifications\Model\Event;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "BeforeEchoEventInsert" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface BeforeEchoEventInsertHook {
/**
* @param Event $event
* @return bool|void True or no return value to continue or false to abort
*/
public function onBeforeEchoEventInsert( Event $event );
}

View file

@ -0,0 +1,22 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Extension\Notifications\Model\Event;
use MediaWiki\User\UserIdentity;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "EchoAbortEmailNotification" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface EchoAbortEmailNotificationHook {
/**
* @param UserIdentity $user
* @param Event $event
* @return bool|void True or no return value to continue or false to abort
*/
public function onEchoAbortEmailNotification( UserIdentity $user, Event $event );
}

View file

@ -0,0 +1,17 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "EchoCanAbortNewMessagesAlert" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface EchoCanAbortNewMessagesAlertHook {
/**
* @return bool|void True or no return value to continue or false to abort
*/
public function onEchoCanAbortNewMessagesAlert();
}

View file

@ -0,0 +1,20 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Extension\Notifications\Model\Notification;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "EchoCreateNotificationComplete" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface EchoCreateNotificationCompleteHook {
/**
* @param Notification $notification
* @return bool|void True or no return value to continue or false to abort
*/
public function onEchoCreateNotificationComplete( Notification $notification );
}

View file

@ -0,0 +1,21 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Extension\Notifications\Model\Event;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "EchoGetBundleRules" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface EchoGetBundleRulesHook {
/**
* @param Event $event
* @param string &$bundleKey
* @return bool|void True or no return value to continue or false to abort
*/
public function onEchoGetBundleRules( Event $event, string &$bundleKey );
}

View file

@ -0,0 +1,22 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Extension\Notifications\Model\Event;
use User;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "EchoGetDefaultNotifiedUsers" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface EchoGetDefaultNotifiedUsersHook {
/**
* @param Event $event
* @param User[] &$users
* @return bool|void True or no return value to continue or false to abort
*/
public function onEchoGetDefaultNotifiedUsers( Event $event, array &$users );
}

View file

@ -0,0 +1,22 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Revision\RevisionRecord;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "EchoGetEventsForRevision" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface EchoGetEventsForRevisionHook {
/**
* @param array &$events List of event info arrays
* @param RevisionRecord $revision
* @param bool $isRevert
* @return bool|void True or no return value to continue or false to abort
*/
public function onEchoGetEventsForRevision( array &$events, RevisionRecord $revision, bool $isRevert );
}

View file

@ -0,0 +1,23 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Extension\Notifications\Model\Event;
use User;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "EchoGetNotificationTypes" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface EchoGetNotificationTypesHook {
/**
* @param User $user
* @param Event $event
* @param string[] &$userNotifyTypes
* @return bool|void True or no return value to continue or false to abort
*/
public function onEchoGetNotificationTypes( User $user, Event $event, array &$userNotifyTypes );
}

View file

@ -0,0 +1,20 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Extension\Notifications\Model\Event;
/**
* This is a hook handler interface, see docs/Hooks.md in core.
* Use the hook name "EventInsertComplete" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup Hooks
*/
interface EventInsertCompleteHook {
/**
* @param Event $event
* @return bool|void True or no return value to continue or false to abort
*/
public function onEventInsertComplete( Event $event );
}

View file

@ -0,0 +1,148 @@
<?php
namespace MediaWiki\Extension\Notifications\Hooks;
use MediaWiki\Extension\Notifications\Model\Event;
use MediaWiki\Extension\Notifications\Model\Notification;
use MediaWiki\HookContainer\HookContainer;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Title\Title;
use MediaWiki\User\UserIdentity;
use User;
/**
* This is a hook runner class, see docs/Hooks.md in core.
* @internal
*/
class HookRunner implements
BeforeCreateEchoEventHook,
BeforeDisplayOrangeAlertHook,
BeforeEchoEventInsertHook,
EchoAbortEmailNotificationHook,
EchoCanAbortNewMessagesAlertHook,
EchoCreateNotificationCompleteHook,
EchoGetBundleRulesHook,
EchoGetDefaultNotifiedUsersHook,
EchoGetEventsForRevisionHook,
EchoGetNotificationTypesHook,
EventInsertCompleteHook
{
private HookContainer $hookContainer;
public function __construct( HookContainer $hookContainer ) {
$this->hookContainer = $hookContainer;
}
/**
* @inheritDoc
*/
public function onBeforeCreateEchoEvent(
array &$notifications,
array &$notificationCategories,
array &$notificationIcons
) {
return $this->hookContainer->run(
'BeforeCreateEchoEvent',
[ &$notifications, &$notificationCategories, &$notificationIcons ]
);
}
/**
* @inheritDoc
*/
public function onBeforeDisplayOrangeAlert( User $user, Title $title ) {
return $this->hookContainer->run(
'BeforeDisplayOrangeAlert',
[ $user, $title ]
);
}
/**
* @inheritDoc
*/
public function onBeforeEchoEventInsert( Event $event ) {
return $this->hookContainer->run(
'BeforeEchoEventInsert',
[ $event ]
);
}
/**
* @inheritDoc
*/
public function onEchoAbortEmailNotification( UserIdentity $user, Event $event ) {
return $this->hookContainer->run(
'EchoAbortEmailNotification',
[ $user, $event ]
);
}
/**
* @inheritDoc
*/
public function onEchoCanAbortNewMessagesAlert() {
return $this->hookContainer->run(
'EchoCanAbortNewMessagesAlert'
);
}
/**
* @inheritDoc
*/
public function onEchoCreateNotificationComplete( Notification $notification ) {
return $this->hookContainer->run(
'EchoCreateNotificationComplete',
[ $notification ]
);
}
/**
* @inheritDoc
*/
public function onEchoGetBundleRules( Event $event, string &$bundleKey ) {
return $this->hookContainer->run(
'EchoGetBundleRules',
[ $event, &$bundleKey ]
);
}
/**
* @inheritDoc
*/
public function onEchoGetDefaultNotifiedUsers( Event $event, array &$users ) {
return $this->hookContainer->run(
'EchoGetDefaultNotifiedUsers',
[ $event, &$users ]
);
}
/**
* @inheritDoc
*/
public function onEchoGetEventsForRevision( array &$events, RevisionRecord $revision, bool $isRevert ) {
return $this->hookContainer->run(
'EchoGetEventsForRevision',
[ &$events, $revision, $isRevert ]
);
}
/**
* @inheritDoc
*/
public function onEchoGetNotificationTypes( User $user, Event $event, array &$userNotifyTypes ) {
return $this->hookContainer->run(
'EchoGetNotificationTypes',
[ $user, $event, &$userNotifyTypes ]
);
}
/**
* @inheritDoc
*/
public function onEventInsertComplete( Event $event ) {
return $this->hookContainer->run(
'EventInsertComplete',
[ $event ]
);
}
}

View file

@ -7,6 +7,7 @@ use EchoServices;
use Exception;
use InvalidArgumentException;
use MediaWiki\Extension\Notifications\Controller\NotificationController;
use MediaWiki\Extension\Notifications\Hooks\HookRunner;
use MediaWiki\Extension\Notifications\Mapper\EventMapper;
use MediaWiki\Extension\Notifications\Mapper\TargetPageMapper;
use MediaWiki\Logger\LoggerFactory;
@ -190,15 +191,15 @@ class Event extends AbstractEntity implements Bundleable {
}
}
$hookContainer = $services->getHookContainer();
if ( !$hookContainer->run( 'BeforeEchoEventInsert', [ $obj ] ) ) {
$hookRunner = new HookRunner( $services->getHookContainer() );
if ( !$hookRunner->onBeforeEchoEventInsert( $obj ) ) {
return false;
}
// @Todo - Database insert logic should not be inside the model
$obj->insert();
$hookContainer->run( 'EventInsertComplete', [ $obj ] );
$hookRunner->onEventInsertComplete( $obj );
global $wgEchoUseJobQueue;

View file

@ -4,6 +4,7 @@ namespace MediaWiki\Extension\Notifications\Model;
use Bundleable;
use InvalidArgumentException;
use MediaWiki\Extension\Notifications\Hooks\HookRunner;
use MediaWiki\Extension\Notifications\Mapper\NotificationMapper;
use MediaWiki\MediaWikiServices;
use MWEchoNotifUser;
@ -106,14 +107,13 @@ class Notification extends AbstractEntity implements Bundleable {
$notifMapper = new NotificationMapper();
$services = MediaWikiServices::getInstance();
$hookContainer = $services->getHookContainer();
$hookRunner = new HookRunner( $services->getHookContainer() );
// Get the bundle key for this event if web bundling is enabled
$bundleKey = '';
if ( !empty( $wgEchoNotifications[$this->event->getType()]['bundle']['web'] ) ) {
$hookContainer->run( 'EchoGetBundleRules', [ $this->event, &$bundleKey ] );
$hookRunner->onEchoGetBundleRules( $this->event, $bundleKey );
}
// @phan-suppress-next-line PhanImpossibleCondition May be set by hook
if ( $bundleKey ) {
$hash = md5( $bundleKey );
$this->bundleHash = $hash;
@ -134,7 +134,7 @@ class Notification extends AbstractEntity implements Bundleable {
$services->getTalkPageNotificationManager()
->setUserHasNewMessages( $this->user );
}
$hookContainer->run( 'EchoCreateNotificationComplete', [ $this ] );
$hookRunner->onEchoCreateNotificationComplete( $this );
}
/**

View file

@ -2,6 +2,7 @@
use MediaWiki\Extension\Notifications\Formatters\EchoHtmlEmailFormatter;
use MediaWiki\Extension\Notifications\Formatters\EchoPlainTextEmailFormatter;
use MediaWiki\Extension\Notifications\Hooks\HookRunner;
use MediaWiki\Extension\Notifications\Model\Event;
use MediaWiki\Extension\Notifications\Model\Notification;
use MediaWiki\MediaWikiServices;
@ -52,9 +53,9 @@ class EchoNotifier {
return false;
}
$hookContainer = $services->getHookContainer();
$hookRunner = new HookRunner( $services->getHookContainer() );
// Final check on whether to send email for this user & event
if ( !$hookContainer->run( 'EchoAbortEmailNotification', [ $user, $event ] ) ) {
if ( !$hookRunner->onEchoAbortEmailNotification( $user, $event ) ) {
return false;
}
@ -74,9 +75,8 @@ class EchoNotifier {
if ( !empty( $wgEchoNotifications[$event->getType()]['bundle']['web'] ) ||
!empty( $wgEchoNotifications[$event->getType()]['bundle']['email'] )
) {
$hookContainer->run( 'EchoGetBundleRules', [ $event, &$bundleString ] );
$hookRunner->onEchoGetBundleRules( $event, $bundleString );
}
// @phan-suppress-next-line PhanImpossibleCondition May be set by hook
if ( $bundleString ) {
$bundleHash = md5( $bundleString );
}

View file

@ -0,0 +1,16 @@
<?php
namespace MediaWiki\Extension\Notifications\Tests\Unit;
use MediaWiki\Extension\Notifications\Hooks\HookRunner;
use MediaWiki\Tests\HookContainer\HookRunnerTestBase;
/**
* @covers \MediaWiki\Extension\Notifications\Hooks\HookRunner
*/
class HookRunnerTest extends HookRunnerTestBase {
public static function provideHookRunners() {
yield HookRunner::class => [ HookRunner::class ];
}
}