From 78b7613eb989c38f6df12322e42e995c5f6e13d0 Mon Sep 17 00:00:00 2001 From: Lens0021 Date: Thu, 27 May 2021 09:56:15 +0900 Subject: [PATCH] Use AbuseFilterShouldFilterAction hook for Flow actions (#17) * Use AbuseFilterShouldFilterAction hook for Flow actions (#16) * Use AbuseFilter hook for Flow actions * build: Add AbuseFileter as a dependency * Add a type check for UUID * Do not ruin Flow\Tests\Api\Api*Test (cherry picked from commit da9123b73e2f9aa540b17c2e047288fb6c602b9c) * Remove links syntax from Flow topic titles (cherry picked from commit 7892b54fcd67879a991ef23d777951b04525ef8d) * Reflect breaking changes of AbuseFilter for MW1.36 * Cleanup phpcs errors * Fix Phan errors * Fix failed phpcs tests --- .github/workflows/dependencies | 1 + .phan/config.php | 2 + composer.lock | 191 +++++++++++++++++++++++++++------ extension.json | 1 + includes/Core.php | 14 ++- includes/Hooks.php | 118 +++++++++++++++++++- 6 files changed, 285 insertions(+), 42 deletions(-) diff --git a/.github/workflows/dependencies b/.github/workflows/dependencies index df3ca38..5399f9d 100644 --- a/.github/workflows/dependencies +++ b/.github/workflows/dependencies @@ -1 +1,2 @@ +AbuseFilter Flow diff --git a/.phan/config.php b/.phan/config.php index 0fbea97..68663c3 100644 --- a/.phan/config.php +++ b/.phan/config.php @@ -5,6 +5,7 @@ $cfg['directory_list'] = array_merge( $cfg['directory_list'], [ + '../../extensions/AbuseFilter', '../../extensions/Flow', ] @@ -13,6 +14,7 @@ $cfg['exclude_analysis_directory_list'] = array_merge( $cfg['exclude_analysis_directory_list'], [ + '../../extensions/AbuseFilter', '../../extensions/Flow', ] ); diff --git a/composer.lock b/composer.lock index 217607d..448de6a 100644 --- a/composer.lock +++ b/composer.lock @@ -9,16 +9,16 @@ "packages-dev": [ { "name": "composer/semver", - "version": "3.2.4", + "version": "3.2.5", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464" + "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", - "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", + "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9", + "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9", "shasum": "" }, "require": { @@ -67,6 +67,11 @@ "validation", "versioning" ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.2.5" + }, "funding": [ { "url": "https://packagist.com", @@ -81,7 +86,7 @@ "type": "tidelift" } ], - "time": "2020-11-13T08:59:24+00:00" + "time": "2021-05-24T12:41:47+00:00" }, { "name": "composer/spdx-licenses", @@ -141,6 +146,11 @@ "spdx", "validator" ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/spdx-licenses/issues", + "source": "https://github.com/composer/spdx-licenses/tree/1.5.5" + }, "funding": [ { "url": "https://packagist.com", @@ -159,16 +169,16 @@ }, { "name": "composer/xdebug-handler", - "version": "1.4.5", + "version": "1.4.6", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "f28d44c286812c714741478d968104c5e604a1d4" + "reference": "f27e06cd9675801df441b3656569b328e04aa37c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f28d44c286812c714741478d968104c5e604a1d4", - "reference": "f28d44c286812c714741478d968104c5e604a1d4", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f27e06cd9675801df441b3656569b328e04aa37c", + "reference": "f27e06cd9675801df441b3656569b328e04aa37c", "shasum": "" }, "require": { @@ -176,7 +186,8 @@ "psr/log": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "autoload": { @@ -199,6 +210,11 @@ "Xdebug", "performance" ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/1.4.6" + }, "funding": [ { "url": "https://packagist.com", @@ -213,7 +229,7 @@ "type": "tidelift" } ], - "time": "2020-11-13T08:04:11+00:00" + "time": "2021-03-25T17:01:18+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -254,6 +270,10 @@ } ], "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", + "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.0" + }, "time": "2021-01-10T17:48:47+00:00" }, { @@ -301,6 +321,9 @@ "codesniffer", "mediawiki" ], + "support": { + "source": "https://github.com/wikimedia/mediawiki-tools-codesniffer/tree/v36.0.0" + }, "time": "2021-04-29T02:21:21+00:00" }, { @@ -348,6 +371,10 @@ ], "description": "Standard MediaWiki phan configuration", "homepage": "https://www.mediawiki.org/wiki/Continuous_integration/Phan", + "support": { + "issues": "https://github.com/wikimedia/mediawiki-tools-phan/issues", + "source": "https://github.com/wikimedia/mediawiki-tools-phan/tree/0.10.6" + }, "time": "2020-12-14T15:30:53+00:00" }, { @@ -394,6 +421,9 @@ ], "description": "Removes executable bit from files that shouldn't be executable", "homepage": "https://www.mediawiki.org/wiki/MinusX", + "support": { + "source": "https://github.com/wikimedia/mediawiki-tools-minus-x/tree/1.1.1" + }, "time": "2021-01-06T01:11:18+00:00" }, { @@ -458,6 +488,12 @@ "static", "taint" ], + "support": { + "irc": "irc://freenode.net/wikimedia-dev", + "issues": "https://phabricator.wikimedia.org/maniphest/task/edit/form/1/?projects=securitycheckplugin", + "source": "https://phabricator.wikimedia.org/diffusion/MTPS/", + "wiki": "https://www.mediawiki.org/wiki/SecurityCheckPlugin" + }, "time": "2020-12-14T11:11:43+00:00" }, { @@ -499,6 +535,10 @@ } ], "description": "Tolerant PHP-to-AST parser designed for IDE usage scenarios", + "support": { + "issues": "https://github.com/microsoft/tolerant-php-parser/issues", + "source": "https://github.com/microsoft/tolerant-php-parser/tree/v0.0.23" + }, "time": "2020-09-13T17:29:12+00:00" }, { @@ -545,6 +585,11 @@ } ], "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/master" + }, "time": "2020-04-16T18:48:43+00:00" }, { @@ -618,6 +663,10 @@ "php", "static" ], + "support": { + "issues": "https://github.com/phan/phan/issues", + "source": "https://github.com/phan/phan/tree/3.2.6" + }, "time": "2020-11-27T19:39:49+00:00" }, { @@ -663,6 +712,10 @@ "email": "jakub.onderka@gmail.com" } ], + "support": { + "issues": "https://github.com/php-parallel-lint/PHP-Console-Color/issues", + "source": "https://github.com/php-parallel-lint/PHP-Console-Color/tree/master" + }, "time": "2020-05-14T05:47:14+00:00" }, { @@ -712,6 +765,10 @@ } ], "description": "Highlight PHP code in terminal", + "support": { + "issues": "https://github.com/php-parallel-lint/PHP-Console-Highlighter/issues", + "source": "https://github.com/php-parallel-lint/PHP-Console-Highlighter/tree/master" + }, "time": "2020-05-13T07:37:49+00:00" }, { @@ -765,6 +822,10 @@ ], "description": "This tool check syntax of PHP files about 20x faster than serial check.", "homepage": "https://github.com/php-parallel-lint/PHP-Parallel-Lint", + "support": { + "issues": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/issues", + "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/v1.3.0" + }, "time": "2021-04-07T14:42:48+00:00" }, { @@ -814,6 +875,10 @@ "reflection", "static analysis" ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, "time": "2020-06-27T09:03:43+00:00" }, { @@ -866,6 +931,10 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + }, "time": "2020-09-03T19:13:55+00:00" }, { @@ -911,6 +980,10 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" + }, "time": "2020-09-17T18:55:26+00:00" }, { @@ -955,20 +1028,24 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, "time": "2021-03-05T17:36:06+00:00" }, { "name": "psr/log", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { @@ -992,7 +1069,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", @@ -1002,7 +1079,10 @@ "psr", "psr-3" ], - "time": "2020-03-23T09:12:05+00:00" + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" }, { "name": "sabre/event", @@ -1063,6 +1143,11 @@ "reactor", "signal" ], + "support": { + "forum": "https://groups.google.com/group/sabredav-discuss", + "issues": "https://github.com/sabre-io/event/issues", + "source": "https://github.com/fruux/sabre-event" + }, "time": "2020-10-03T11:02:22+00:00" }, { @@ -1114,20 +1199,25 @@ "phpcs", "standards" ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, "time": "2021-04-09T00:54:41+00:00" }, { "name": "symfony/console", - "version": "v5.2.6", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d" + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/35f039df40a3b335ebf310f244cb242b3a83ac8d", - "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d", + "url": "https://api.github.com/repos/symfony/console/zipball/864568fdc0208b3eba3638b6000b69d2386e6768", + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768", "shasum": "" }, "require": { @@ -1194,6 +1284,9 @@ "console", "terminal" ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.2.8" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1208,7 +1301,7 @@ "type": "tidelift" } ], - "time": "2021-03-28T09:42:18+00:00" + "time": "2021-05-11T15:45:21+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1270,6 +1363,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1348,6 +1444,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1429,6 +1528,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1506,6 +1608,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1582,6 +1687,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1662,6 +1770,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1680,21 +1791,21 @@ }, { "name": "symfony/service-contracts", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1" + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", "shasum": "" }, "require": { "php": ">=7.2.5", - "psr/container": "^1.0" + "psr/container": "^1.1" }, "suggest": { "symfony/service-implementation": "" @@ -1702,7 +1813,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -1738,6 +1849,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1752,20 +1866,20 @@ "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2021-04-01T10:43:52+00:00" }, { "name": "symfony/string", - "version": "v5.2.6", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572" + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", - "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", + "url": "https://api.github.com/repos/symfony/string/zipball/01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", "shasum": "" }, "require": { @@ -1818,6 +1932,9 @@ "utf-8", "utf8" ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.2.8" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1832,7 +1949,7 @@ "type": "tidelift" } ], - "time": "2021-03-17T17:12:15+00:00" + "time": "2021-05-10T14:56:10+00:00" }, { "name": "webmozart/assert", @@ -1886,6 +2003,10 @@ "check", "validate" ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.10.0" + }, "time": "2021-03-09T10:59:23+00:00" } ], @@ -1896,5 +2017,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/extension.json b/extension.json index 4c57249..3300701 100644 --- a/extension.json +++ b/extension.json @@ -15,6 +15,7 @@ "DiscordNotifications": ["i18n"] }, "Hooks": { + "AbuseFilterShouldFilterAction": "main", "AfterImportPage": "main", "APIFlowAfterExecute": "MediaWiki\\Extension\\DiscordNotifications\\Hooks::onAPIFlowAfterExecute", "ArticleDeleteComplete": "main", diff --git a/includes/Core.php b/includes/Core.php index a59cb15..5470ede 100644 --- a/includes/Core.php +++ b/includes/Core.php @@ -208,11 +208,17 @@ public static function msg( $key, ...$params ) { } /** - * @param string $uuid - * @return string + * @param string|UUID $uuid + * @return string Text of the title for given UUID. If not found, empty string will be returned. */ - public static function flowUUIDToTitleText( string $uuid ) { - $uuid = UUID::create( $uuid ); + public static function flowUUIDToTitleText( $uuid ) { + if ( is_string( $uuid ) ) { + $uuid = strtolower( $uuid ); + $uuid = UUID::create( $uuid ); + } + if ( !( $uuid instanceof UUID ) ) { + return ''; + } $collection = \Flow\Collection\PostCollection::newFromId( $uuid ); $revision = $collection->getLastRevision(); return $revision->getContent( 'topic-title-plaintext' ); diff --git a/includes/Hooks.php b/includes/Hooks.php index bb6d1ea..d31daf3 100644 --- a/includes/Hooks.php +++ b/includes/Hooks.php @@ -6,12 +6,17 @@ use Config; use Exception; use ExtensionRegistry; +use Flow\Conversion\Utils; +use MediaWiki\Extension\AbuseFilter\AbuseFilterServices; +use MediaWiki\Extension\AbuseFilter\Variables\VariableHolder; use MediaWiki\MediaWikiServices; use SpecialPage; use Title; +use User; class Hooks implements \MediaWiki\Auth\Hook\LocalUserCreatedHook, + \MediaWiki\Extension\AbuseFilter\Hooks\AbuseFilterShouldFilterActionHook, \MediaWiki\Hook\AfterImportPageHook, \MediaWiki\Hook\BlockIpCompleteHook, \MediaWiki\Hook\PageMoveCompleteHook, @@ -35,9 +40,7 @@ class Hooks implements /** * @param Config $config */ - public function __construct( - Config $config - ) { + public function __construct( Config $config ) { $this->config = $config; $this->core = new Core(); } @@ -338,6 +341,14 @@ public static function onAPIFlowAfterExecute( APIBase $module ) { return; } + # self::APIFlowAfterExecute() is used instead of this if available. + if ( ExtensionRegistry::getInstance()->isLoaded( 'Abuse Filter' ) + && in_array( $action, [ 'new-topic', 'edit-header', 'edit-post', 'edit-title', 'edit-topic-summary', + 'reply' ] ) + ) { + return; + } + global $wgUser; switch ( $action ) { case 'edit-header': @@ -423,6 +434,107 @@ public static function onAPIFlowAfterExecute( APIBase $module ) { $core->pushDiscordNotify( $message, $wgUser, 'flow' ); } + /** + * self::APIFlowAfterExecute() is not triggered if the browser of the user does not support JavaScript. + * To avoid that cases, we use this AbuseFilter hook if the extension is loaded. + * @param VariableHolder $vars + * @param Title $title Title object target of the action + * @param User $user User object performer of the action + * @param array &$skipReasons Array of reasons why the action should be skipped + * @return bool|void True or no return value to continue or false to abort + */ + public function onAbuseFilterShouldFilterAction( + VariableHolder $vars, + Title $title, + User $user, + array &$skipReasons + ) { + global $wgDiscordNotificationsActions; + + if ( !$wgDiscordNotificationsActions['flow'] || !ExtensionRegistry::getInstance()->isLoaded( 'Flow' ) ) { + return; + } + + if ( Core::titleIsExcluded( $title ) ) { + return; + } + + // Avoid AbuseFilterConsequences test failures + if ( defined( 'MW_PHPUNIT_TEST' ) ) { + return; + } + + $userLink = LinkRenderer::getDiscordUserText( $user ); + $action = $vars->getComputedVariable( 'action' )->data; + $pageTitleText = $vars->getComputedVariable( 'page_title' )->data; + $boardPrefixedTitleText = $vars->getComputedVariable( 'board_prefixedtitle' )->data; + $pagePrefixedTitleText = $vars->getComputedVariable( 'page_prefixedtitle' )->data; + $boardTitle = Title::newFromText( $boardPrefixedTitleText ); + $pageTitle = Title::newFromText( $pagePrefixedTitleText ); + + // Skip notifications if the reply is the first, in fact non a "re"-ply. + // The first reply is a content of the topic. + if ( $action == 'reply' && $boardTitle == $pageTitle ) { + return; + } + + $core = new Core(); + switch ( $action ) { + case 'new-post': + $newWikitext = $vars->getVars()['new_wikitext']; + $titleText = $newWikitext->getParameters()['revision']->getPostId()->getAlphadecimal(); + $title = Title::newFromText( $titleText, NS_TOPIC ); + $varManager = AbuseFilterServices::getVariablesManager(); + $topicText = $varManager->getVar( $vars, 'new_wikitext' )->toString(); + $topicText = Utils::convert( 'topic-title-wikitext', 'topic-title-plaintext', $topicText, $title ); + + $msg = Core::msg( 'discordnotifications-flow-new-topic', + $userLink, + LinkRenderer::makeLink( $title->getFullUrl(), $topicText ), + LinkRenderer::makeLink( $boardTitle->getFullUrl(), $boardPrefixedTitleText ) + ); + break; + case 'edit-post': + $msg = Core::msg( 'discordnotifications-flow-edit-post', + $userLink, + LinkRenderer::makeLink( $pageTitle->getFullUrl(), + Core::flowUUIDToTitleText( $pageTitleText ) ) + # TODO use LinkRenderer::makeLink( $boardTitle->getFullUrl(), $boardPrefixedTitleText ) + ); + break; + case 'reply': + $msg = Core::msg( 'discordnotifications-flow-reply', + $userLink, + LinkRenderer::makeLink( $pageTitle->getFullUrl(), + Core::flowUUIDToTitleText( $pageTitleText ) ) + # TODO use LinkRenderer::makeLink( $boardTitle->getFullUrl(), $boardPrefixedTitleText ) + ); + break; + case 'edit-title': + $varManager = AbuseFilterServices::getVariablesManager(); + $newWikitext = $varManager->getVar( $vars, 'new_wikitext' )->toString(); + $msg = Core::msg( 'discordnotifications-flow-edit-title', + $userLink, + # TODO use $oldWikitext + LinkRenderer::makeLink( $boardTitle->getFullUrl(), $boardPrefixedTitleText ), + LinkRenderer::makeLink( $pageTitle->getFullUrl(), $newWikitext ) + ); + break; + case 'create-topic-summary': + case 'edit-topic-summary': + $msg = Core::msg( 'discordnotifications-flow-edit-header', + $userLink, + LinkRenderer::makeLink( $pageTitle->getFullUrl(), + Core::flowUUIDToTitleText( $pageTitleText ) ) + # TODO use LinkRenderer::makeLink( $boardTitle->getFullUrl(), $boardPrefixedTitleText ) + ); + break; + default: + return; + } + $core->pushDiscordNotify( $msg, $user, 'flow' ); + } + /** * @inheritDoc */