jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/344564 )
Change subject: Update Wikibase for cherry-picks ...................................................................... Update Wikibase for cherry-picks Change-Id: I7614cfbd94dc66e5d64824295f6ed2e07743a44a Contains: f69807ed631b63a28441085be7878883650896d1 Contains: 9609b2470ca9259b53ecae3bc20505445101150f --- M composer.lock M extensions/Wikibase/client/WikibaseClient.hooks.php M extensions/Wikibase/client/WikibaseClient.php M extensions/Wikibase/client/i18n/en.json M extensions/Wikibase/client/i18n/qqq.json M extensions/Wikibase/client/includes/Hooks/ChangesListSpecialPageHookHandlers.php A extensions/Wikibase/client/includes/Hooks/MagicWordHookHandlers.php M extensions/Wikibase/client/includes/Modules/SiteModule.php M extensions/Wikibase/client/tests/phpunit/includes/Hooks/ChangesListSpecialPageHookHandlersTest.php A extensions/Wikibase/client/tests/phpunit/includes/Hooks/MagicWordHookHandlersTest.php M extensions/Wikibase/client/tests/phpunit/includes/Modules/SiteModuleTest.php M vendor/composer/autoload_classmap.php M vendor/composer/installed.json 13 files changed, 573 insertions(+), 227 deletions(-) Approvals: Catrope: Looks good to me, approved jenkins-bot: Verified diff --git a/composer.lock b/composer.lock index 033a9e8..3c91bb6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,6 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "dd86aee3beb782d317e3ed1f91182856", "content-hash": "2491321b315e555939b9ee918a3949fa", "packages": [ { @@ -1436,12 +1435,12 @@ "source": { "type": "git", "url": "https://github.com/wikimedia/mediawiki-extensions-Wikibase.git", - "reference": "2755a3431f5a763b634c2c46d034ad34796631e0" + "reference": "9609b2470ca9259b53ecae3bc20505445101150f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/2755a3431f5a763b634c2c46d034ad34796631e0", - "reference": "2755a3431f5a763b634c2c46d034ad34796631e0", + "url": "https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/9609b2470ca9259b53ecae3bc20505445101150f", + "reference": "9609b2470ca9259b53ecae3bc20505445101150f", "shasum": "" }, "require": { @@ -1515,7 +1514,7 @@ "wikibaserepo", "wikidata" ], - "time": "2017-03-21 03:19:45" + "time": "2017-03-23 23:32:11" }, { "name": "wikibase/wikimedia-badges", diff --git a/extensions/Wikibase/client/WikibaseClient.hooks.php b/extensions/Wikibase/client/WikibaseClient.hooks.php index 11528de..6611903 100644 --- a/extensions/Wikibase/client/WikibaseClient.hooks.php +++ b/extensions/Wikibase/client/WikibaseClient.hooks.php @@ -342,52 +342,6 @@ } /** - * Register the magic word. - * - * @param string[] &$aCustomVariableIds - * - * @return bool - */ - public static function onMagicWordwgVariableIDs( &$aCustomVariableIds ) { - $aCustomVariableIds[] = 'noexternallanglinks'; - $aCustomVariableIds[] = 'wbreponame'; - - return true; - } - - /** - * Apply the magic word. - * - * @param Parser &$parser - * @param array &$cache - * @param string &$magicWordId - * @param string &$ret - * - * @return bool - */ - public static function onParserGetVariableValueSwitch( Parser &$parser, &$cache, &$magicWordId, &$ret ) { - if ( $magicWordId === 'noexternallanglinks' ) { - NoLangLinkHandler::handle( $parser, '*' ); - } elseif ( $magicWordId === 'wbreponame' ) { - // @todo factor out, with tests - $wikibaseClient = WikibaseClient::getDefaultInstance(); - $settings = $wikibaseClient->getSettings(); - $repoSiteName = $settings->getSetting( 'repoSiteName' ); - - $message = new Message( $repoSiteName ); - - if ( $message->exists() ) { - $lang = $parser->getTargetLanguage(); - $ret = $message->inLanguage( $lang )->parse(); - } else { - $ret = $repoSiteName; - } - } - - return true; - } - - /** * Adds the Entity ID of the corresponding Wikidata item in action=info * * @param IContextSource $context @@ -496,16 +450,28 @@ } /** - * These hooks should only be run if we use the Echo extension + * Do special hook registrations. These are affected by ordering issues and/or + * conditional on another extension being registered. * * @see https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExtensionFunctions */ public static function onExtensionLoad() { global $wgHooks; + + // These hooks should only be run if we use the Echo extension if ( class_exists( EchoEvent::class ) ) { $wgHooks['UserGetDefaultOptions'][] = EchoNotificationsHandlers::class . '::onUserGetDefaultOptions'; $wgHooks['WikibaseHandleChange'][] = EchoNotificationsHandlers::class . '::onWikibaseHandleChange'; } + + // This is in onExtensionLoad to ensure we register our + // ChangesListSpecialPageStructuredFilters after ORES's. + // + // However, ORES is not required. + // + // recent changes / watchlist hooks + $wgHooks['ChangesListSpecialPageStructuredFilters'][] = + '\Wikibase\Client\Hooks\ChangesListSpecialPageHookHandlers::onChangesListSpecialPageStructuredFilters'; } } diff --git a/extensions/Wikibase/client/WikibaseClient.php b/extensions/Wikibase/client/WikibaseClient.php index 07df902..efeeeda 100644 --- a/extensions/Wikibase/client/WikibaseClient.php +++ b/extensions/Wikibase/client/WikibaseClient.php @@ -119,8 +119,6 @@ $wgHooks['SidebarBeforeOutput'][] = '\Wikibase\Client\Hooks\SidebarHookHandlers::onSidebarBeforeOutput'; $wgHooks['ParserFirstCallInit'][] = '\Wikibase\ClientHooks::onParserFirstCallInit'; - $wgHooks['MagicWordwgVariableIDs'][] = '\Wikibase\ClientHooks::onMagicWordwgVariableIDs'; - $wgHooks['ParserGetVariableValueSwitch'][] = '\Wikibase\ClientHooks::onParserGetVariableValueSwitch'; $wgHooks['SkinTemplateOutputPageBeforeExec'][] = '\Wikibase\Client\Hooks\SkinTemplateOutputPageBeforeExecHandler::onSkinTemplateOutputPageBeforeExec'; $wgHooks['SpecialMovepageAfterMove'][] = '\Wikibase\Client\Hooks\MovePageNotice::onSpecialMovepageAfterMove'; @@ -162,9 +160,13 @@ } // recent changes / watchlist hooks - $wgHooks['ChangesListSpecialPageFilters'][] = '\Wikibase\Client\Hooks\ChangesListSpecialPageHookHandlers::onChangesListSpecialPageFilters'; $wgHooks['ChangesListSpecialPageQuery'][] = '\Wikibase\Client\Hooks\ChangesListSpecialPageHookHandlers::onChangesListSpecialPageQuery'; + // magic words + $wgHooks['MagicWordwgVariableIDs'][] = '\Wikibase\Client\Hooks\MagicWordHookHandlers::onMagicWordwgVariableIDs'; + $wgHooks['ParserGetVariableValueSwitch'][] = '\Wikibase\Client\Hooks\MagicWordHookHandlers::onParserGetVariableValueSwitch'; + $wgHooks['ResourceLoaderJqueryMsgModuleMagicWords'][] = '\Wikibase\Client\Hooks\MagicWordHookHandlers::onResourceLoaderJqueryMsgModuleMagicWords'; + // update hooks $wgHooks['LoadExtensionSchemaUpdates'][] = '\Wikibase\Client\Usage\Sql\SqlUsageTrackerSchemaUpdater::onSchemaUpdate'; diff --git a/extensions/Wikibase/client/i18n/en.json b/extensions/Wikibase/client/i18n/en.json index 5c7c152..565b5ae 100644 --- a/extensions/Wikibase/client/i18n/en.json +++ b/extensions/Wikibase/client/i18n/en.json @@ -75,6 +75,12 @@ "wikibase-rc-show-wikidata-pref": "Show {{WBREPONAME}} edits in recent changes", "wikibase-rc-wikibase-edit-letter": "D", "wikibase-rc-wikibase-edit-title": "{{WBREPONAME}} edit", + "wikibase-rcfilters-hide-wikibase-label": "{{WBREPONAME}} edits", + "wikibase-rcfilters-hide-wikibase-description": "Edits that originate on {{WBREPONAME}}.", + "wikibase-rcfilters-hide-wikibase-conflicts-ores": "This filter conflicts with one or more Contribution Quality or User Intent filters. Quality and Intent predictions are not available for {{WBREPONAME}} edits.", + "wikibase-rcfilters-hide-wikibase-conflicts-ores-global": "The \"{{WBREPONAME}} edits\" filter is conflicting with one or more Contribution Quality or User Intent filters. Quality and Intent predictions are not available for {{WBREPONAME}} edits. The conflicting filters are marked in the Active Filters area, above.", + "wikibase-rcfilters-damaging-conflicts-hide-wikibase": "Contribution Quality predictions are not available for certain types of change, so this filter conflicts with the following Type of Change {{PLURAL:$2|filter|filters}}: $1", + "wikibase-rcfilters-goodfaith-conflicts-hide-wikibase": "User Intent predictions are not available for certain types of change, so this filter conflicts with the following Type of Change {{PLURAL:$2|filter|filters}}: $1", "wikibase-replicationnote": "Please notice that it can take several minutes until the changes are visible on all wikis.", "wikibase-watchlist-show-changes-pref": "Show {{WBREPONAME}} edits in your watchlist", "wikibase-error-deserialize-error": "Failed to deserialize data.", diff --git a/extensions/Wikibase/client/i18n/qqq.json b/extensions/Wikibase/client/i18n/qqq.json index 5c7d7a7..91f05e2 100644 --- a/extensions/Wikibase/client/i18n/qqq.json +++ b/extensions/Wikibase/client/i18n/qqq.json @@ -86,6 +86,12 @@ "wikibase-rc-show-wikidata-pref": "Option in the recent changes section of preferences to show wikibase changes by default in recent changes.", "wikibase-rc-wikibase-edit-letter": "Very short form of \"'''wikidata edit'''\". Used in [[Special:RecentChanges]] and [[Special:Watchlist]].\n\nSee also:\n* {{msg-mw|Newpageletter}}\n* {{msg-mw|Minoreditletter}}\n* {{msg-mw|Boteditletter}}\n* {{msg-mw|Unpatrolledletter}}", "wikibase-rc-wikibase-edit-title": "Tooltip for {{msg-mw|wikibase-rc-wikibase-edit-letter}}.\n\nSee also:\n* {{msg-mw|Recentchanges-label-newpage}}\n* {{msg-mw|Recentchanges-label-minor}}\n* {{msg-mw|Recentchanges-label-bot}}\n* {{msg-mw|Recentchanges-label-unpatrolled}}\n{{Identical|Edit}}", + "wikibase-rcfilters-hide-wikibase-label": "Label for 'Wikidata edits' filter on ChangesList pages (such as RecentChanges)", + "wikibase-rcfilters-hide-wikibase-description": "Description for 'Wikidata edits' filter on ChangesList pages (such as RecentChanges)", + "wikibase-rcfilters-hide-wikibase-conflicts-ores": "Tooltip shown when hovering over a 'Wikidata edits' filter tag, when a ORES filter is also selected.\n* 'Contribution quality' is based on {{msg-mw|Ores-rcfilters-damaging-title}}.\n* 'User intent' is based on {{msg-mw|Ores-rcfilters-goodfaith-title}}.", + "wikibase-rcfilters-hide-wikibase-conflicts-ores-global": "Message shown in the result area when both an ORES filter and the 'Wikidata edits' filter are selected. This indicates that no results will be shown because propagated Wikidata edits do not have ORES scores available.\n\n* \"Wikidata edits\" is {{msg-mw|wikibase-rcfilters-hide-wikibase-label}}.\n* \"Contribution quality\" is based on {{msg-mw|Ores-rcfilters-damaging-title}}.\n* \"User intent\" is based on {{msg-mw|Ores-rcfilters-goodfaith-title}}.\n* \"Active Filters\" is based on {{msg-mw|rcfilters-activefilters}}.", + "wikibase-rcfilters-damaging-conflicts-hide-wikibase": "Tooltip shown when hovering over a 'Contribution quality predictions' filter tag, when the 'Wikidata edits' filter is selected and there is a conflict. Propagated Wikidata edits do not have ORES scores avaialble. Parameters:\n* $1 - Comma-separated string of selected Type of Change filters, e.g. \"Wikidata edits\"\n* $2 - Count of selected Type of Change filters, for PLURAL", + "wikibase-rcfilters-goodfaith-conflicts-hide-wikibase": "Tooltip shown when hovering over a 'User intent predictions' filter tag, when the 'Wikidata edits' filter is selected and there is a conflict. 'Wikidata edits' are not scored by ORES. Parameters:\n* $1 - Comma-separated string of selected Type of Change filters, e.g. \"Wikidata edits\"\n* $2 - Count of selected Type of Change filters, for PLURAL", "wikibase-replicationnote": "Note telling the user that it can take a few minutes until the made changes are visible on all wikis.\nPreceded by message {{msg-mw|Wikibase-linkitem-success-link}}", "wikibase-watchlist-show-changes-pref": "Option in the watchlist section of preferences to always show wikibase edits by default in the watchlist. Appears as a checkbox in the same list with options such as:\n* {{msg-mw|tog-watchdefault}}\n* {{msg-mw|tog-watchmoves}}\nAnd so on.", "wikibase-error-deserialize-error": "Generic error when invalid (undeserializable) data has been given.", diff --git a/extensions/Wikibase/client/includes/Hooks/ChangesListSpecialPageHookHandlers.php b/extensions/Wikibase/client/includes/Hooks/ChangesListSpecialPageHookHandlers.php index 55460ba..b1f525e 100644 --- a/extensions/Wikibase/client/includes/Hooks/ChangesListSpecialPageHookHandlers.php +++ b/extensions/Wikibase/client/includes/Hooks/ChangesListSpecialPageHookHandlers.php @@ -2,9 +2,12 @@ namespace Wikibase\Client\Hooks; +use ChangesListBooleanFilter; use ChangesListSpecialPage; +use ExtensionRegistry; use FormOptions; use IContextSource; +use IDatabase; use MediaWiki\MediaWikiServices; use RequestContext; use User; @@ -113,29 +116,26 @@ /** * Modifies recent changes and watchlist options to show a toggle for Wikibase changes - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ChangesListSpecialPageFilters + * @see https://www.mediawiki.org/wiki/Manual:Hooks/ChangesListSpecialPageStructuredFilters * * @param ChangesListSpecialPage $specialPage - * @param array &$filters * * @return bool */ - public static function onChangesListSpecialPageFilters( - ChangesListSpecialPage $specialPage, - array &$filters + public static function onChangesListSpecialPageStructuredFilters( + ChangesListSpecialPage $specialPage ) { $hookHandler = self::getInstance( $specialPage->getContext(), $specialPage->getName() ); - $hookHandler->addFilterIfEnabled( $filters ); + $hookHandler->addFilterIfEnabled( $specialPage ); return true; } /** - * Modifies watchlist and recent changes query to include external changes * @see https://www.mediawiki.org/wiki/Manual:Hooks/ChangesListSpecialPageQuery * * @param string $specialPageName @@ -162,83 +162,113 @@ $specialPageName ); - $conds = $hookHandler->addWikibaseConditions( $conds, $opts ); + $hookHandler->addWikibaseConditionsIfFilterUnavailable( $conds ); return true; } - /** - * @param array &$filters - */ - public function addFilterIfEnabled( array &$filters ) { - if ( $this->hasWikibaseChangesEnabled() ) { - $filterName = $this->getFilterName(); + // This is separate so hasWikibaseChangesEnabled can be mocked - // the toggle needs to be the inverse to invoke the inverse display status. - // e.g. if Wikibase changes currently hidden, then when the user - // clicks the toggle, then Wikibase changes are displayed. - $filters[$filterName] = array( - 'msg' => 'wikibase-rc-hide-wikidata', - 'default' => !$this->hasWikibaseChangesDisplayed() + /** + * This is used to force-hide Wikibase changes if hasWikibaseChangesEnabled returns + * false. The user will not even see the option in that case. + * + * @param array &$conds + */ + protected function addWikibaseConditionsIfFilterUnavailable( array &$conds ) { + if ( !$this->hasWikibaseChangesEnabled() ) { + // Force-hide if hasWikibaseChangesEnabled is false + // The user-facing hideWikibase is handled by + // ChangesListSpecialPageStructuredFilters and connected code. + $this->addWikibaseConditions( + $this->loadBalancer->getConnection( DB_REPLICA ), + $conds ); } } /** - * @param array &$conds - * @param FormOptions $opts - * - * @return array + * @param ChangesListSpecialPage $specialPage */ - public function addWikibaseConditions( array &$conds, FormOptions $opts ) { - if ( $this->shouldHideWikibaseChanges( $opts ) ) { - $dbr = $this->loadBalancer->getConnection( DB_REPLICA ); - $conds[] = 'rc_source != ' . $dbr->addQuotes( RecentChangeFactory::SRC_WIKIBASE ); - $this->loadBalancer->reuseConnection( $dbr ); + public function addFilterIfEnabled( ChangesListSpecialPage $specialPage ) { + // The *user-facing* filter is only registered if external changes + // are enabled, and the user does not have enhanced recent changes. + // + // If the user-facing filter is not registered, it's always *hidden*. + // (See ChangesListSpecialPageQuery). + if ( $this->hasWikibaseChangesEnabled() ) { + $this->addFilter( $specialPage ); } - - return $conds; } /** - * @param FormOptions $opts - * - * @return boolean + * @param ChangesListSpecialPage $specialPage */ - private function shouldHideWikibaseChanges( FormOptions $opts ) { - if ( !$this->hasWikibaseChangesEnabled() ) { - return true; - } - + protected function addFilter( ChangesListSpecialPage $specialPage ) { $filterName = $this->getFilterName(); + $changeTypeGroup = $specialPage->getFilterGroup( 'changeType' ); - if ( !$opts->offsetExists( $filterName ) ) { - return true; + $specialPage->getOutput()->addModules( 'wikibase.client.jqueryMsg' ); + + $wikidataFilter = new ChangesListBooleanFilter( [ + 'name' => $filterName, + 'group' => $changeTypeGroup, + 'priority' => -4, + 'label' => 'wikibase-rcfilters-hide-wikibase-label', + 'description' => 'wikibase-rcfilters-hide-wikibase-description', + 'showHide' => 'wikibase-rc-hide-wikidata', + // If the preference is enabled, then don't hide Wikidata edits + 'default' => !$this->hasShowWikibaseEditsPrefEnabled(), + 'queryCallable' => function ( $specialClassName, $ctx, $dbr, &$tables, &$fields, + &$conds, &$query_options, &$join_conds ) { + $this->addWikibaseConditions( $dbr, $conds ); + }, + 'cssClassSuffix' => 'src-mw-wikibase', + 'isRowApplicableCallable' => function ( $ctx, $rc ) { + return $rc->getAttribute( 'rc_source' ) === RecentChangeFactory::SRC_WIKIBASE; + } + ] ); + + $extensionRegistry = ExtensionRegistry::getInstance(); + + if ( $extensionRegistry->isLoaded( 'ORES' ) ) { + $damagingGroup = $specialPage->getFilterGroup( 'damaging' ); + if ( $damagingGroup ) { + $wikidataFilter->conflictsWith( + $damagingGroup, + 'wikibase-rcfilters-hide-wikibase-conflicts-ores-global', + 'wikibase-rcfilters-hide-wikibase-conflicts-ores', + 'wikibase-rcfilters-damaging-conflicts-hide-wikibase' + ); + } + + $goodfaithGroup = $specialPage->getFilterGroup( 'goodfaith' ); + if ( $goodfaithGroup ) { + $wikidataFilter->conflictsWith( + $goodfaithGroup, + 'wikibase-rcfilters-hide-wikibase-conflicts-ores-global', + 'wikibase-rcfilters-hide-wikibase-conflicts-ores', + 'wikibase-rcfilters-goodfaith-conflicts-hide-wikibase' + ); + } } + } - return $opts->getValue( $filterName ) === true; + /** + * @param IDatabase $dbr + * @param array &$conds + */ + public function addWikibaseConditions( IDatabase $dbr, array &$conds ) { + $conds[] = 'rc_source != ' . $dbr->addQuotes( RecentChangeFactory::SRC_WIKIBASE ); } /** * @return bool */ - private function hasWikibaseChangesEnabled() { + protected function hasWikibaseChangesEnabled() { // do not include wikibase changes for activated enhanced watchlist // since we do not support that format yet (T46222) return $this->showExternalChanges && !$this->isEnhancedChangesEnabled(); - } - - /** - * @return bool - */ - private function hasWikibaseChangesDisplayed() { - if ( $this->request->getVal( 'action' ) === 'submit' ) { - return !$this->request->getBool( $this->getFilterName() ); - } - - // if preference enabled, then Wikibase edits are included by default and - // the toggle default value needs to be the inverse to hide them, and vice versa. - return $this->hasShowWikibaseEditsPrefEnabled(); } /** diff --git a/extensions/Wikibase/client/includes/Hooks/MagicWordHookHandlers.php b/extensions/Wikibase/client/includes/Hooks/MagicWordHookHandlers.php new file mode 100644 index 0000000..f01a177 --- /dev/null +++ b/extensions/Wikibase/client/includes/Hooks/MagicWordHookHandlers.php @@ -0,0 +1,129 @@ +<?php + +namespace Wikibase\Client\Hooks; + +use Language; +use Message; +use Parser; +use ResourceLoaderContext; +use Wikibase\SettingsArray; +use Wikibase\Client\WikibaseClient; + +/** + * File defining hooks related to magic words + * @license GPL-2.0+ + */ +class MagicWordHookHandlers { + /** + * @var SettingsArray $settings + */ + protected $settings; + + /** + * WikibaseClient $wikibaseClient + */ + public function __construct( SettingsArray $settings ) { + $this->settings = $settings; + } + + /** + * @return self + */ + public static function newFromGlobalState() { + $client = WikibaseClient::getDefaultInstance(); + return new self( $client->getSettings() ); + } + + /** + * Register the magic word. + * + * @param string[] &$aCustomVariableIds + * + * @return bool + */ + public static function onMagicWordwgVariableIDs( &$aCustomVariableIds ) { + $aCustomVariableIds[] = 'noexternallanglinks'; + $aCustomVariableIds[] = 'wbreponame'; + + return true; + } + + /** + * Gets the user-facing repository name. + * + * This can either be a message's text, or the raw value from + * settings if that is not a message + * + * @param Language $lang Language to get text in + */ + protected function getRepoName( Language $lang ) { + $repoSiteName = $this->settings->getSetting( 'repoSiteName' ); + + $message = new Message( $repoSiteName ); + $message->inLanguage( $lang ); + + if ( $message->exists() ) { + return $message->parse(); + } else { + return $repoSiteName; + } + } + + /** + * Static handler for the ParserGetVariableValueSwitch hook + * + * @param Parser &$parser + * @param array &$cache + * @param string &$magicWordId + * @param string &$ret + * + * @return bool + */ + public static function onParserGetVariableValueSwitch( Parser &$parser, &$cache, &$magicWordId, &$ret ) { + $handler = self::newFromGlobalState(); + $handler->doParserGetVariableValueSwitch( $parser, $cache, $magicWordId, $ret ); + } + + /** + * Apply the magic word. + * + * @param Parser &$parser + * @param array &$cache + * @param string &$magicWordId + * @param string &$ret + * + * @return bool + */ + protected function doParserGetVariableValueSwitch( Parser &$parser, &$cache, &$magicWordId, &$ret ) { + if ( $magicWordId === 'noexternallanglinks' ) { + NoLangLinkHandler::handle( $parser, '*' ); + } elseif ( $magicWordId === 'wbreponame' ) { + $lang = $parser->getTargetLanguage(); + $ret = $this->getRepoName( $lang ); + } + + return true; + } + + /** + * Static handler for the ResourceLoaderJqueryMsgModuleMagicWords hook + * + * @param array $magicWords + */ + public static function onResourceLoaderJqueryMsgModuleMagicWords( ResourceLoaderContext $context, array &$magicWords ) { + $handler = self::newFromGlobalState(); + $handler->doResourceLoaderJqueryMsgModuleMagicWords( $context, $magicWords ); + } + + /** + * Adds magic word constant(s) for use by jQueryMsg + * + * @param array $magicWords Associative array mapping all-caps magic + * words to string values + */ + protected function doResourceLoaderJqueryMsgModuleMagicWords( ResourceLoaderContext $context, array &$magicWords ) { + $lang = Language::factory( $context->getLanguage() ); + $magicWords['WBREPONAME'] = $this->getRepoName( $lang ); + } + +} diff --git a/extensions/Wikibase/client/includes/Modules/SiteModule.php b/extensions/Wikibase/client/includes/Modules/SiteModule.php index 2973094..72cdeb6 100644 --- a/extensions/Wikibase/client/includes/Modules/SiteModule.php +++ b/extensions/Wikibase/client/includes/Modules/SiteModule.php @@ -4,9 +4,11 @@ use FormatJson; use MediaWikiSite; +use ResourceLoader; use ResourceLoaderContext; use ResourceLoaderModule; use Wikibase\Client\WikibaseClient; +use Xml; /** * Provides information about the current (client) site @@ -42,7 +44,11 @@ ); } - return 'mediaWiki.config.set( "wbCurrentSite", ' . FormatJson::encode( $currentSite ) . ' );'; + return Xml::encodeJsCall( + 'mw.config.set', + [ 'wbCurrentSite', $currentSite ], + ResourceLoader::inDebugMode() + ); } } diff --git a/extensions/Wikibase/client/tests/phpunit/includes/Hooks/ChangesListSpecialPageHookHandlersTest.php b/extensions/Wikibase/client/tests/phpunit/includes/Hooks/ChangesListSpecialPageHookHandlersTest.php index 2a3dfe4..aa51402 100644 --- a/extensions/Wikibase/client/tests/phpunit/includes/Hooks/ChangesListSpecialPageHookHandlersTest.php +++ b/extensions/Wikibase/client/tests/phpunit/includes/Hooks/ChangesListSpecialPageHookHandlersTest.php @@ -2,10 +2,12 @@ namespace Wikibase\Client\Tests\Hooks; +use ExtensionRegistry; use FauxRequest; use FormOptions; use IDatabase; use SpecialPageFactory; +use TestingAccessWrapper; use User; use Wikibase\Client\Hooks\ChangesListSpecialPageHookHandlers; use Wikimedia\Rdbms\LoadBalancer; @@ -18,35 +20,90 @@ * * @license GPL-2.0+ * @author Katie Filbert < aude.w...@gmail.com > + * @author Matthew Flaschen < mflasc...@wikimedia.org > */ class ChangesListSpecialPageHookHandlersTest extends \PHPUnit_Framework_TestCase { + protected $extensionRegistry; - public function testOnChangesListSpecialPageFilters() { + protected $oldExtensionRegistryLoaded; + + public function setUp() { + parent::setUp(); + + $this->extensionRegistry = TestingAccessWrapper::newFromObject( + ExtensionRegistry::getInstance() + ); + + $this->oldExtensionRegistryLoaded = $this->extensionRegistry->loaded; + + // Forget about the other extensions. Although ORES may be loaded, + // since this is only unit-testing *our* listener, ORES's listener + // hasn't run, so for all intents and purposes it's not loaded. + $this->extensionRegistry->loaded = [ 'Wikibase' ]; + } + + public function tearDown() { + parent::tearDown(); + + $this->extensionRegistry->loaded = $this->oldExtensionRegistryLoaded; + } + + public function testAddFilter() { $user = $this->getUser( array( - array( 'usernewrc' => 0 ) + array( 'usenewrc' => 0 ) ) ); /** @var \ChangesListSpecialPage $specialPage */ $specialPage = SpecialPageFactory::getPage( 'Recentchanges' ); + + $wrappedSpecialPage = TestingAccessWrapper::newFromObject( + $specialPage + ); + + $hookHandler = TestingAccessWrapper::newFromObject( new ChangesListSpecialPageHookHandlers( + $this->getRequest( array() ), + $this->getUser( [] ), + $this->getLoadBalancer(), + 'Recentchanges', + true + ) ); + $specialPage->getContext()->setUser( $user ); - $filters = array(); - - ChangesListSpecialPageHookHandlers::onChangesListSpecialPageFilters( - $specialPage, - $filters + // Register built-in filters, since the Wikidata one uses its group + $wrappedSpecialPage->registerFiltersFromDefinitions( + $wrappedSpecialPage->filterGroupDefinitions ); - $expected = array( - 'hideWikibase' => array( - 'msg' => 'wikibase-rc-hide-wikidata', - 'default' => true - ) + $hookHandler->addFilter( + $specialPage ); - $this->assertSame( $expected, $filters ); + $changeType = $specialPage->getFilterGroup( 'changeType' ); + $filter = $changeType->getFilter( 'hideWikibase' ); + + // I could do all of getJsData(), but that would make it brittle to + // unrelated changes. + $expectedFields = [ + 'label' => 'wikibase-rcfilters-hide-wikibase-label', + 'description' => 'wikibase-rcfilters-hide-wikibase-description', + 'showHide' => 'wikibase-rc-hide-wikidata', + 'default' => true, + ]; + + $actualFields = [ + 'label' => $filter->getLabel(), + 'description' => $filter->getDescription(), + 'showHide' => $filter->getShowHide(), + 'default' => $filter->getDefault(), + ]; + + $this->assertSame( + $expectedFields, + $actualFields + ); } public function testOnChangesListSpecialPageQuery() { @@ -73,86 +130,138 @@ } /** - * @dataProvider addWikibaseConditionsProvider + * @dataProvider addWikibaseConditionsIfFilterUnavailableProvider */ - public function testAddWikibaseConditions( - array $expected, - array $userOptions, - $optionDefault - ) { + public function testAddWikibaseConditionsIfFilterUnavailable( $expectedAddConditionsCalls, $hasWikibaseChangesEnabled ) { + $hookHandlerMock = $this->getMockBuilder( ChangesListSpecialPageHookHandlers::class ) + ->setConstructorArgs( + [ + $this->getRequest( array() ), + $this->getUser( [] ), + $this->getLoadBalancer(), + 'Recentchanges', + true + ] + ) + ->setMethods( [ + 'hasWikibaseChangesEnabled', + 'addWikibaseConditions' + ] ) + ->getMock(); + + $hookHandlerMock->method( 'hasWikibaseChangesEnabled' )->will( + $this->returnValue( $hasWikibaseChangesEnabled ) + ); + + $hookHandlerMock->expects( $this->exactly( $expectedAddConditionsCalls ) ) + ->method( 'addWikibaseConditions' ) + ->with( + $this->isInstanceOf( IDatabase::class ), + $this->equalTo( [] ) + ); + + $conds = []; + + $hookHandlerMock = TestingAccessWrapper::newFromObject( $hookHandlerMock ); + $hookHandlerMock->__call( 'addWikibaseConditionsIfFilterUnavailable', [ &$conds ] ); + } + + public function addWikibaseConditionsIfFilterUnavailableProvider() { + return [ + [ + 0, + true + ], + + [ + 1, + false + ], + ]; + } + + /** + * @dataProvider getOptionNameProvider + */ + public function testGetOptionName( $expected, $pageName ) { + $hookHandler = TestingAccessWrapper::newFromObject( new ChangesListSpecialPageHookHandlers( + $this->getRequest( array() ), + $this->getUser( [] ), + $this->getLoadBalancer(), + $pageName, + true + ) ); + + $this->assertSame( + $expected, + $hookHandler->getOptionName() + ); + } + + public function getOptionNameProvider() { + return [ + [ + 'wlshowwikibase', + 'Watchlist' + ], + + [ + 'rcshowwikidata', + 'Recentchanges', + ], + + [ + 'rcshowwikidata', + 'Recentchangeslinked' + ], + ]; + } + + public function testAddWikibaseConditions() { $hookHandler = new ChangesListSpecialPageHookHandlers( $this->getRequest( array() ), - $this->getUser( $userOptions ), + $this->getUser( [] ), $this->getLoadBalancer(), 'Watchlist', true ); - $opts = new FormOptions(); - $opts->add( 'hideWikibase', $optionDefault ); - $conds = array(); - $hookHandler->addWikibaseConditions( $conds, $opts ); + $hookHandler->addWikibaseConditions( + wfGetDB( DB_REPLICA ), + $conds + ); + + $expected = [ "rc_source != 'wb'" ]; $this->assertEquals( $expected, $conds ); } - public function addWikibaseConditionsProvider() { - return array( - array( - array(), - array( 'usenewrc' => 0, 'wlshowwikibase' => 1 ), - false - ), - array( - array( "rc_source != 'wb'" ), - array( 'usenewrc' => 0 ), - true - ) - ); - } - - public function testAddWikibaseConditions_wikibaseChangesDisabled() { - $hookHandler = new ChangesListSpecialPageHookHandlers( - $this->getRequest( array() ), - $this->getUser( array( 'usenewrc' => 1 ) ), - $this->getLoadBalancer(), - 'Watchlist', - true - ); - - $opts = new FormOptions(); - - $conds = array(); - $hookHandler->addWikibaseConditions( $conds, $opts ); - - $this->assertEquals( array( "rc_source != 'wb'" ), $conds ); - } - /** - * @dataProvider filterNotAddedWhenUsingEnhancedChangesProvider + * @dataProvider hasWikibaseChangesEnabledWhenUsingEnhancedChangesProvider */ - public function testFilterNotAddedWhenUsingEnhancedChanges( + public function testHasWikibaseChangesEnabledWhenUsingEnhancedChanges( array $requestParams, array $userOptions, $pageName, $message ) { - $hookHandler = new ChangesListSpecialPageHookHandlers( + $hookHandler = TestingAccessWrapper::newFromObject( new ChangesListSpecialPageHookHandlers( $this->getRequest( $requestParams ), $this->getUser( $userOptions ), $this->getLoadBalancer(), $pageName, true + ) ); + + $this->assertSame( + false, + $hookHandler->hasWikibaseChangesEnabled(), + $message ); - - $filters = array(); - $hookHandler->addFilterIfEnabled( $filters ); - - $this->assertSame( array(), $filters, $message ); } - public function filterNotAddedWhenUsingEnhancedChangesProvider() { + public function hasWikibaseChangesEnabledWhenUsingEnhancedChangesProvider() { return array( array( array(), @@ -194,37 +303,30 @@ } /** - * @dataProvider filter_withoutShowWikibaseEditsByDefaultPreference + * @dataProvider hasWikibaseChangesEnabled_withoutShowWikibaseEditsByDefaultPreferenceProvider */ - public function testFilter_withoutShowWikibaseEditsByDefaultPreference( + public function testHasWikibaseChangesEnabled_withoutShowWikibaseEditsByDefaultPreference( array $requestParams, array $userOptions, $expectedFilterName, $expectedToggleDefault, $specialPageName ) { - $hookHandler = new ChangesListSpecialPageHookHandlers( + $hookHandler = TestingAccessWrapper::newFromObject( new ChangesListSpecialPageHookHandlers( $this->getRequest( $requestParams ), $this->getUser( $userOptions ), $this->getLoadBalancer(), $specialPageName, true + ) ); + + $this->assertSame( + true, + $hookHandler->hasWikibaseChangesEnabled() ); - - $filters = array(); - $hookHandler->addFilterIfEnabled( $filters ); - - $expected = array( - $expectedFilterName => array( - 'msg' => 'wikibase-rc-hide-wikidata', - 'default' => $expectedToggleDefault - ) - ); - - $this->assertSame( $expected, $filters ); } - public function filter_withoutShowWikibaseEditsByDefaultPreference() { + public function hasWikibaseChangesEnabled_withoutShowWikibaseEditsByDefaultPreferenceProvider() { return array( array( array(), @@ -272,37 +374,30 @@ } /** - * @dataProvider filter_withShowWikibaseEditsByDefaultPreference + * @dataProvider hasWikibaseChangesEnabled_withShowWikibaseEditsByDefaultPreferenceProvider */ - public function testFilter_withShowWikibaseEditsByDefaultPreference( + public function testHasWikibaseChangesEnabled_withShowWikibaseEditsByDefaultPreference( array $requestParams, array $userOptions, $expectedFilterName, $expectedToggleDefault, $specialPageName ) { - $hookHandler = new ChangesListSpecialPageHookHandlers( + $hookHandler = TestingAccessWrapper::newFromObject( new ChangesListSpecialPageHookHandlers( $this->getRequest( $requestParams ), $this->getUser( $userOptions ), $this->getLoadBalancer(), $specialPageName, true + ) ); + + $this->assertSame( + true, + $hookHandler->hasWikibaseChangesEnabled() ); - - $filters = array(); - $hookHandler->addFilterIfEnabled( $filters ); - - $expected = array( - $expectedFilterName => array( - 'msg' => 'wikibase-rc-hide-wikidata', - 'default' => $expectedToggleDefault - ) - ); - - $this->assertSame( $expected, $filters ); } - public function filter_withShowWikibaseEditsByDefaultPreference() { + public function hasWikibaseChangesEnabled_withShowWikibaseEditsByDefaultPreferenceProvider() { return array( array( array(), @@ -343,28 +438,28 @@ } /** - * @dataProvider filterNotAddedWhenExternalRecentChangesDisabledProvider() { + * @dataProvider hasWikibaseChangesEnabledWhenExternalRecentChangesDisabledProvider() { */ - public function testFilterNotAddedWhenExternalRecentChangesDisabled( $specialPageName ) { - $hookHandler = new ChangesListSpecialPageHookHandlers( + public function testHasWikibaseChangesEnabledWhenExternalRecentChangesDisabled( $specialPageName ) { + $hookHandler = TestingAccessWrapper::newFromObject( new ChangesListSpecialPageHookHandlers( $this->getRequest( array() ), $this->getUser( array( 'usenewrc' => 0 ) ), $this->getLoadBalancer(), $specialPageName, - false + /* $showExternalChanges= */ false + ) ); + + $this->assertSame( + false, + $hookHandler->hasWikibaseChangesEnabled() ); - - $filters = array(); - $hookHandler->addFilterIfEnabled( $filters ); - - $this->assertSame( array(), $filters ); } - public function filterNotAddedWhenExternalRecentChangesDisabledProvider() { + public function hasWikibaseChangesEnabledWhenExternalRecentChangesDisabledProvider() { return array( array( 'Watchlist' ), - array( 'RecentChanges' ), - array( 'RecentChangesLinked' ) + array( 'Recentchanges' ), + array( 'Recentchangeslinked' ) ); } diff --git a/extensions/Wikibase/client/tests/phpunit/includes/Hooks/MagicWordHookHandlersTest.php b/extensions/Wikibase/client/tests/phpunit/includes/Hooks/MagicWordHookHandlersTest.php new file mode 100644 index 0000000..7436e53 --- /dev/null +++ b/extensions/Wikibase/client/tests/phpunit/includes/Hooks/MagicWordHookHandlersTest.php @@ -0,0 +1,105 @@ +<?php + +namespace Wikibase\Client\Tests\Hooks; + +use Language; +use Wikibase\Client\Hooks\MagicWordHookHandlers; +use MediaWiki\MediaWikiServices; +use MediaWikiTestCase; +use Parser; +use Wikibase\SettingsArray; +use Title; +use TestingAccessWrapper; +use Wikibase\Client\WikibaseClient; + +/** + * @covers Wikibase\Client\Hooks\MagicWordHookHandlers + * + * @group WikibaseClient + * @group Wikibase + * + * @license GPL-2.0+ + * @author Matthew Flaschen < mflasc...@wikimedia.org > + */ +class MagicWordHookHandlersTest extends MediaWikiTestCase { + + /** + * @dataProvider provideGetRepoName + */ + public function testGetRepoName( $expected, $langCode, $siteName ) { + $settings = new SettingsArray(); + $settings->setSetting( 'repoSiteName', $siteName ); + + $handler = TestingAccessWrapper::newFromObject( + new MagicWordHookHandlers( $settings ) + ); + + $actual = $handler->getRepoName( + Language::factory( $langCode ) + ); + + $this->assertEquals( + $expected, + $actual + ); + } + + // I looked at mocking the messages, but MessageCache + // is not in ServiceWiring (yet), so these are real messsages, + // except non-existent-message to test that feature. + + public function provideGetRepoName() { + return [ + [ + 'Client for the Wikibase extension', + 'en', + 'wikibase-client-desc', + ], + + [ + 'Cliente para la extensión Wikibase', + 'es', + 'wikibase-client-desc', + ], + + [ + 'non-existent-message', + 'en', + 'non-existent-message', + ], + ]; + } + + // TODO: Test noexternallanglinks + + public function testDoParserGetVariableValueSwitch() { + $parser = $this->getMockBuilder( Parser::class ) + ->getMock(); + + // Configure the stub. + $parser->method( 'getTargetLanguage' ) + ->willReturn( Language::factory( 'en' ) ); + + $ret = null; + + $settings = new SettingsArray(); + $settings->setSetting( 'repoSiteName', 'wikibase-client-desc' ); + + $handler = TestingAccessWrapper::newFromObject( + new MagicWordHookHandlers( $settings ) + ); + + $cache = []; + $word = 'wbreponame'; + call_user_func_array( + [ $handler, 'doParserGetVariableValueSwitch' ], + [ &$parser, &$cache, &$word, &$ret ] + ); + + $this->assertEquals( + 'Client for the Wikibase extension', + $ret + ); + } + +} diff --git a/extensions/Wikibase/client/tests/phpunit/includes/Modules/SiteModuleTest.php b/extensions/Wikibase/client/tests/phpunit/includes/Modules/SiteModuleTest.php index 4567053..1353eea 100644 --- a/extensions/Wikibase/client/tests/phpunit/includes/Modules/SiteModuleTest.php +++ b/extensions/Wikibase/client/tests/phpunit/includes/Modules/SiteModuleTest.php @@ -29,8 +29,8 @@ public function testGetScript() { $module = new SiteModule(); $script = $module->getScript( $this->getContext() ); - $this->assertStringStartsWith( 'mediaWiki.config.set( "wbCurrentSite", ', $script ); - $this->assertStringEndsWith( ' );', $script ); + $this->assertStringStartsWith( 'mw.config.set("wbCurrentSite",', $script ); + $this->assertStringEndsWith( ');', $script ); } } diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index de6cb7e..8813f37 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -354,6 +354,7 @@ 'Wikibase\\Client\\Hooks\\InfoActionHookHandler' => $baseDir . '/extensions/Wikibase/client/includes/Hooks/InfoActionHookHandler.php', 'Wikibase\\Client\\Hooks\\InterwikiSortingHookHandlers' => $baseDir . '/extensions/Wikibase/client/includes/Hooks/InterwikiSortingHookHandlers.php', 'Wikibase\\Client\\Hooks\\LanguageLinkBadgeDisplay' => $baseDir . '/extensions/Wikibase/client/includes/Hooks/LanguageLinkBadgeDisplay.php', + 'Wikibase\\Client\\Hooks\\MagicWordHookHandlers' => $baseDir . '/extensions/Wikibase/client/includes/Hooks/MagicWordHookHandlers.php', 'Wikibase\\Client\\Hooks\\MovePageNotice' => $baseDir . '/extensions/Wikibase/client/includes/Hooks/MovePageNotice.php', 'Wikibase\\Client\\Hooks\\OtherProjectsSidebarGenerator' => $baseDir . '/extensions/Wikibase/client/includes/Hooks/OtherProjectsSidebarGenerator.php', 'Wikibase\\Client\\Hooks\\OtherProjectsSidebarGeneratorFactory' => $baseDir . '/extensions/Wikibase/client/includes/Hooks/OtherProjectsSidebarGeneratorFactory.php', @@ -438,6 +439,7 @@ 'Wikibase\\Client\\Tests\\Hooks\\InfoActionHookHandlerTest' => $baseDir . '/extensions/Wikibase/client/tests/phpunit/includes/Hooks/InfoActionHookHandlerTest.php', 'Wikibase\\Client\\Tests\\Hooks\\InterwikiSortingHookHandlersTest' => $baseDir . '/extensions/Wikibase/client/tests/phpunit/includes/Hooks/InterwikiSortingHookHandlersTest.php', 'Wikibase\\Client\\Tests\\Hooks\\LanguageLinkBadgeDisplayTest' => $baseDir . '/extensions/Wikibase/client/tests/phpunit/includes/Hooks/LanguageLinkBadgeDisplayTest.php', + 'Wikibase\\Client\\Tests\\Hooks\\MagicWordHookHandlersTest' => $baseDir . '/extensions/Wikibase/client/tests/phpunit/includes/Hooks/MagicWordHookHandlersTest.php', 'Wikibase\\Client\\Tests\\Hooks\\MovePageNoticeTest' => $baseDir . '/extensions/Wikibase/client/tests/phpunit/includes/Hooks/MovePageNoticeTest.php', 'Wikibase\\Client\\Tests\\Hooks\\NoLangLinkHandlerTest' => $baseDir . '/extensions/Wikibase/client/tests/phpunit/includes/Hooks/NoLangLinkHandlerTest.php', 'Wikibase\\Client\\Tests\\Hooks\\OtherProjectsSidebarGeneratorFactoryTest' => $baseDir . '/extensions/Wikibase/client/tests/phpunit/includes/Hooks/OtherProjectsSidebarGeneratorFactoryTest.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index b0fc4ca..2b5cea7 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1628,12 +1628,12 @@ "source": { "type": "git", "url": "https://github.com/wikimedia/mediawiki-extensions-Wikibase.git", - "reference": "2755a3431f5a763b634c2c46d034ad34796631e0" + "reference": "9609b2470ca9259b53ecae3bc20505445101150f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/2755a3431f5a763b634c2c46d034ad34796631e0", - "reference": "2755a3431f5a763b634c2c46d034ad34796631e0", + "url": "https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/9609b2470ca9259b53ecae3bc20505445101150f", + "reference": "9609b2470ca9259b53ecae3bc20505445101150f", "shasum": "" }, "require": { @@ -1665,7 +1665,7 @@ "jakub-onderka/php-parallel-lint": ">=0.3 <0.10", "mediawiki/mediawiki-codesniffer": ">=0.4 <0.8" }, - "time": "2017-03-21 03:19:45", + "time": "2017-03-23 23:32:11", "type": "mediawiki-extension", "installation-source": "dist", "autoload": { -- To view, visit https://gerrit.wikimedia.org/r/344564 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I7614cfbd94dc66e5d64824295f6ed2e07743a44a Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikidata Gerrit-Branch: wmf/1.29.0-wmf.17 Gerrit-Owner: Catrope <r...@wikimedia.org> Gerrit-Reviewer: Addshore <addshorew...@gmail.com> Gerrit-Reviewer: Aude <aude.w...@gmail.com> Gerrit-Reviewer: Catrope <r...@wikimedia.org> Gerrit-Reviewer: Jonas Kress (WMDE) <jonas.kr...@wikimedia.de> Gerrit-Reviewer: Siebrand <siebr...@kitano.nl> Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@wikimedia.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits