Add GEUseCommunityConfigurationExtension feature flag

Why:
The Growth team works on the CommunityConfiguration extension,
which re-implements the ability for administrators to edit
MediaWiki configuration on-wiki in a different way.

This patch allows developers to switch from the GE-specific
implementation of community configuration (so-called CC1.0)
into the new dedicated implementation that CommunityConfiguration
represents.

The patch is meant to make GrowthExperiments stop use any of its
CC1.0 implementation if GEUseCommunityConfigurationExtension is true,
including the editing form.

Notes:
CommunityConfiguration expects client extensions to use a single
Config object (=the one provided by CommunityConfiguration)
for all config needs. This enables client extensions to seamlessly
switch between configurable and non-configurable fields (it is a matter
of changing the scmea), without having to review their usage across their
whole repository. To fully benefit from this expectation, we need to change
how we approach config within GrowthExperiments.

What:
* Introduce `GEUseCommunityConfigurationExtension` config flag, which
  is false by default.
* Create `GrowthExperimentsCommunityConfig`, which either returns
  the `GrowthExperimentsMultiConfig` service or the CommunityConfiguration
  provided service, depending on the feature flag.
* Switch SpecialEditGrowthConfig's registration to a conditional one,
  based on the feature flag value.
* Move two schemas from CommunityConfigurationExample to GrowthExperiments

Bug: T359124
Depends-On: If9db50b8ba8dc835a7d5e1c49de83e7ff2941c01
Change-Id: I2b6e3436c08100442baf4ed65582d0bc17fd449c
这个提交包含在:
Martin Urbanec 2024-03-11 17:36:05 +01:00 提交者 Urbanecm
父节点 39b40185d7
当前提交 67042a7099
共有 10 个文件被更改,包括 181 次插入23 次删除

查看文件

@ -9,6 +9,7 @@ $cfg['directory_list'] = array_merge(
[
'../../extensions/CentralAuth',
'../../extensions/CirrusSearch',
'../../extensions/CommunityConfiguration',
'../../extensions/Echo',
'../../extensions/EventBus',
'../../extensions/EventLogging',
@ -28,6 +29,7 @@ $cfg['exclude_analysis_directory_list'] = array_merge(
[
'../../extensions/CentralAuth',
'../../extensions/CirrusSearch',
'../../extensions/CommunityConfiguration',
'../../extensions/Echo',
'../../extensions/EventBus',
'../../extensions/EventLogging',

查看文件

@ -166,6 +166,19 @@ return [
return $services->getConfigFactory()->makeConfig( 'GrowthExperiments' );
},
'GrowthExperimentsCommunityConfig' => static function ( MediaWikiServices $services ): Config {
$geServices = GrowthExperimentsServices::wrap( $services );
if (
ExtensionRegistry::getInstance()->isLoaded( 'CommunityConfiguration' ) &&
$geServices->getGrowthConfig()->get( 'GEUseCommunityConfigurationExtension' )
) {
return $services->get( 'CommunityConfiguration.WikiPageConfigReader' );
} else {
return $services->get( 'GrowthExperimentsMultiConfig' );
}
},
'GrowthExperimentsConfigValidatorFactory' => static function (
MediaWikiServices $services
): ConfigValidatorFactory {

查看文件

@ -101,7 +101,7 @@
"growthsetmenteestatus": {
"class": "GrowthExperiments\\Api\\ApiSetMenteeStatus",
"services": [
"GrowthExperimentsMultiConfig",
"GrowthExperimentsCommunityConfig",
"GrowthExperimentsMentorManager",
"GrowthExperimentsMentorStore"
]
@ -319,7 +319,7 @@
"class": "GrowthExperiments\\HelpPanelHooks",
"services": [
"MainConfig",
"GrowthExperimentsMultiConfig",
"GrowthExperimentsCommunityConfig",
"GenderCache",
"UserEditTracker",
"UserOptionsManager",
@ -384,7 +384,7 @@
"class": "GrowthExperiments\\Mentorship\\Hooks\\MentorHooks",
"services": [
"MainConfig",
"GrowthExperimentsMultiConfig",
"GrowthExperimentsCommunityConfig",
"UserIdentityLookup",
"GenderCache",
"GrowthExperimentsMentorManager",
@ -583,6 +583,7 @@
],
"SpecialCreateAccountBenefits": "variant",
"SpecialPage_initList": [
"config",
"homepage",
"welcomeSurvey"
],
@ -652,6 +653,25 @@
]
}
}
},
"CommunityConfiguration": {
"Providers": {
"Mentorship": {
"store": {
"type": "wikipage",
"args": [
"MediaWiki:GrowthExperimentsMentorship.json"
]
},
"validator": {
"type": "jsonschema",
"args": [
"GrowthExperiments\\Config\\Schemas\\MentorshipSchema"
]
},
"type": "mw-config"
}
}
}
},
"ResourceModules": {
@ -2431,6 +2451,10 @@
"description": "If set to false, on-wiki configuration will be ignored. WARNING: This will fallback to PHP-globals for all config. By setting this to false, you can break most of the features.",
"value": true
},
"GEUseCommunityConfigurationExtension": {
"description": "If set to true, the CommunityConfiguration extension is used to power on-wiki config.",
"value": false
},
"GEHelpPanelReadingModeNamespaces": {
"description": "Numerical IDs of the MediaWiki namespaces in which to show the help panel in reading mode. Specifying a namespace will also include its talk namespace. Defaults to NS_PROJECT and NS_HELP namespaces.",
"value": [
@ -2835,19 +2859,6 @@
"JobQueueGroupFactory"
]
},
"EditGrowthConfig": {
"class": "GrowthExperiments\\Specials\\SpecialEditGrowthConfig",
"services": [
"TitleFactory",
"RevisionLookup",
"PageProps",
"DBLoadBalancer",
"ReadOnlyMode",
"GrowthExperimentsWikiPageConfigLoader",
"GrowthExperimentsWikiPageConfigWriterFactory",
"GrowthExperimentsMultiConfig"
]
},
"ManageMentors": {
"class": "GrowthExperiments\\Specials\\SpecialManageMentors",
"services": [
@ -2862,7 +2873,7 @@
"EnrollAsMentor": {
"class": "GrowthExperiments\\Specials\\SpecialEnrollAsMentor",
"services": [
"GrowthExperimentsMultiConfig",
"GrowthExperimentsCommunityConfig",
"GrowthExperimentsMentorProvider",
"GrowthExperimentsMentorWriter"
]

查看文件

@ -100,5 +100,20 @@
"growthexperiments-edit-config-try-suggested-edits-notification-title": "Try Suggested edits notification",
"growthexperiments-edit-config-try-suggested-edits-notification-description": "Maximum number of edits a newcomer can have to qualify for receiving this notification. If set to 0, no newcomers </br> will receive this notification. The higher the number, the more newcomers will receive this notification.<br> This notification is only sent to newcomers who have not completed Suggested edits.",
"growthexperiments-edit-config-keep-going-notification-title": "Keep going notification",
"growthexperiments-edit-config-keep-going-notification-description": "Maximum number of suggested edits a newcomer can complete to qualify for receiving this notification. If set to 0,<br> no newcomers will receive this notification. The higher the number, the more newcomers will receive this notification.<br> This notification is only sent to newcomers who have already completed at least one Suggested edit."
"growthexperiments-edit-config-keep-going-notification-description": "Maximum number of suggested edits a newcomer can complete to qualify for receiving this notification. If set to 0,<br> no newcomers will receive this notification. The higher the number, the more newcomers will receive this notification.<br> This notification is only sent to newcomers who have already completed at least one Suggested edit.",
"communityconfiguration-mentorship-title": "Mentorship",
"communityconfiguration-mentorship-description": "Customize mentorship settings and eligibility, while adjusting edit minimums and timeframes for mentors and praise-worthy mentees.",
"communityconfiguration-mentorship-gementorshipautomaticeligibility-label": "Should users be automatically eligible for mentorship?",
"communityconfiguration-mentorship-gementorshipautomaticeligibility-control-label": "x",
"communityconfiguration-mentorship-gementorshipenabled-label": "Are mentorship features enabled?",
"communityconfiguration-mentorship-gementorshipenabled-control-label": "x",
"communityconfiguration-mentorship-gementorshipminimumage-label": "Minimum number of days a user must be registered to sign up as a mentor",
"communityconfiguration-mentorship-gementorshipminimumeditcount-label": "Minimum number of edits a user must have made (on any namespace) to sign up as a mentor",
"communityconfiguration-mentorship-gepersonalizedpraisedays-label": "Number of days that are considered when evaluating mentee's praiseworthiness",
"communityconfiguration-mentorship-gepersonalizedpraisedays-help-text": "Mentors can change this option for their own user in the Mentor dashboard.",
"communityconfiguration-mentorship-gepersonalizedpraisedefaultnotificationsfrequency-label": "By default, how often should mentors receive notifications to remind them to send encouragement to mentees who are editing successfully?",
"communityconfiguration-mentorship-gepersonalizedpraisedefaultnotificationsfrequency-help-text": "Mentors can change this option for their own user in the Mentor dashboard.",
"communityconfiguration-mentorship-gepersonalizedpraisemaxedits-label": "Maximum number of edits an user can have to be considered praiseworthy",
"communityconfiguration-mentorship-gepersonalizedpraiseminedits-label": "Default minimum number of edits a mentee must have to be praiseworthy",
"communityconfiguration-mentorship-gepersonalizedpraiseminedits-help-text": "Mentors can change this option for their own user in the Mentor dashboard."
}

查看文件

@ -113,5 +113,20 @@
"growthexperiments-edit-config-try-suggested-edits-notification-title": "Subheader in Special:EditGrowthConfig\n\n{{doc-growthexperiments-community-configuration}}",
"growthexperiments-edit-config-try-suggested-edits-notification-description": "Description of trying suggested edits notification section in Special:EditGrowthConfig\n\n{{doc-growthexperiments-community-configuration}}",
"growthexperiments-edit-config-keep-going-notification-title": "Subheader in Special:EditGrowthConfig. \"Keep going\" should be consistent with {{msg-mw|Growthexperiments-levelingup-keepgoing-notification-header}}.\n\n{{doc-growthexperiments-community-configuration}}",
"growthexperiments-edit-config-keep-going-notification-description": "Description of keep going notification section in Special:EditGrowthConfig\n\n{{doc-growthexperiments-community-configuration}}"
"growthexperiments-edit-config-keep-going-notification-description": "Description of keep going notification section in Special:EditGrowthConfig\n\n{{doc-growthexperiments-community-configuration}}",
"communityconfiguration-mentorship-title": "Headline of the Community configuration module for mentorship",
"communityconfiguration-mentorship-description": "Description of the Community configuration module for mentorship",
"communityconfiguration-mentorship-gementorshipautomaticeligibility-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gementorshipautomaticeligibility-control-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gementorshipenabled-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gementorshipenabled-control-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gementorshipminimumage-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gementorshipminimumeditcount-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gepersonalizedpraisedays-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gepersonalizedpraisedays-help-text": "Help text for mentorship in Community configuration",
"communityconfiguration-mentorship-gepersonalizedpraisedefaultnotificationsfrequency-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gepersonalizedpraisedefaultnotificationsfrequency-help-text": "Help text for mentorship in Community configuration",
"communityconfiguration-mentorship-gepersonalizedpraisemaxedits-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gepersonalizedpraiseminedits-label": "Field label for mentorship in Community configuration",
"communityconfiguration-mentorship-gepersonalizedpraiseminedits-help-text": "Help text for mentorship in Community configuration"
}

查看文件

@ -3,8 +3,11 @@
namespace GrowthExperiments\Config;
use Content;
use ExtensionRegistry;
use FormatJson;
use GrowthExperiments\Config\Validation\ConfigValidatorFactory;
use GrowthExperiments\Specials\SpecialEditGrowthConfig;
use GrowthExperiments\Specials\SpecialEditGrowthConfigRedirect;
use IContextSource;
use JsonContent;
use MediaWiki\Config\Config;
@ -13,6 +16,7 @@ use MediaWiki\Deferred\DeferredUpdates;
use MediaWiki\Hook\EditFilterMergedContentHook;
use MediaWiki\Hook\SkinTemplateNavigation__UniversalHook;
use MediaWiki\Page\PageIdentity;
use MediaWiki\SpecialPage\Hook\SpecialPage_initListHook;
use MediaWiki\SpecialPage\SpecialPage;
use MediaWiki\Status\Status;
use MediaWiki\Storage\Hook\PageSaveCompleteHook;
@ -26,7 +30,8 @@ class ConfigHooks implements
EditFilterMergedContentHook,
JsonValidateSaveHook,
PageSaveCompleteHook,
SkinTemplateNavigation__UniversalHook
SkinTemplateNavigation__UniversalHook,
SpecialPage_initListHook
{
private ConfigValidatorFactory $configValidatorFactory;
private WikiPageConfigLoader $configLoader;
@ -159,4 +164,32 @@ class ConfigHooks implements
}
}
}
/**
* @inheritDoc
*/
public function onSpecialPage_initList( &$list ) {
if (
ExtensionRegistry::getInstance()->isLoaded( 'CommunityConfiguration' ) &&
$this->config->get( 'GEUseCommunityConfigurationExtension' )
) {
$list['EditGrowthConfig'] = [
'class' => SpecialEditGrowthConfigRedirect::class,
];
} else {
$list['EditGrowthConfig'] = [
'class' => SpecialEditGrowthConfig::class,
'services' => [
'TitleFactory',
'RevisionLookup',
'PageProps',
'DBLoadBalancer',
'ReadOnlyMode',
'GrowthExperimentsWikiPageConfigLoader',
'GrowthExperimentsWikiPageConfigWriterFactory',
'GrowthExperimentsCommunityConfig'
]
];
}
}
}

查看文件

@ -0,0 +1,41 @@
<?php
namespace GrowthExperiments\Config\Schemas;
use MediaWiki\Extension\CommunityConfiguration\Schema\JsonSchema;
// phpcs:disable Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
class MentorshipSchema extends JsonSchema {
public const GEMentorshipAutomaticEligibility = [
self::TYPE => self::TYPE_BOOLEAN,
self::DEFAULT => true,
];
public const GEMentorshipEnabled = [
self::TYPE => self::TYPE_BOOLEAN,
self::DEFAULT => false,
];
public const GEMentorshipMinimumAge = [
self::TYPE => self::TYPE_NUMBER,
self::DEFAULT => 90,
];
public const GEMentorshipMinimumEditcount = [
self::TYPE => self::TYPE_NUMBER,
self::DEFAULT => 500,
];
public const GEPersonalizedPraiseDays = [
self::TYPE => self::TYPE_NUMBER,
self::DEFAULT => 7,
];
public const GEPersonalizedPraiseDefaultNotificationsFrequency = [
self::TYPE => self::TYPE_NUMBER,
self::DEFAULT => 168,
];
public const GEPersonalizedPraiseMaxEdits = [
self::TYPE => self::TYPE_NUMBER,
self::DEFAULT => 500,
];
public const GEPersonalizedPraiseMinEdits = [
self::TYPE => self::TYPE_NUMBER,
self::DEFAULT => 8,
];
}

查看文件

@ -105,7 +105,7 @@ class GrowthExperimentsServices {
}
public function getGrowthWikiConfig(): Config {
return $this->coreServices->get( 'GrowthExperimentsMultiConfig' );
return $this->coreServices->get( 'GrowthExperimentsCommunityConfig' );
}
public function getLoadBalancer(): ILoadBalancer {

查看文件

@ -279,7 +279,7 @@ class HomepageHooks implements
'PerDbNameStatsdDataFactory',
'GrowthExperimentsExperimentUserManager',
'GrowthExperimentsMentorManager',
'GrowthExperimentsMultiConfig',
'GrowthExperimentsCommunityConfig',
'UserOptionsManager',
'TitleFactory',
]
@ -300,7 +300,7 @@ class HomepageHooks implements
'services' => [
'GrowthExperimentsMentorProvider',
'GrowthExperimentsChangeMentorFactory',
'GrowthExperimentsMultiConfig'
'GrowthExperimentsCommunityConfig'
]
];

查看文件

@ -0,0 +1,28 @@
<?php
namespace GrowthExperiments\Specials;
use SpecialPage;
/**
* An implementation for Special:EditGrowthConfig when CommunityConfiguration extension is enabled
*/
class SpecialEditGrowthConfigRedirect extends SpecialPage {
public function __construct() {
parent::__construct( 'EditGrowthConfig', '', false );
}
/**
* @inheritDoc
*/
public function execute( $subPage ) {
parent::execute( $subPage );
$this->getOutput()->redirect(
$this->getSpecialPageFactory()
->getTitleForAlias( 'CommunityConfiguration' )
->getLinkURL()
);
}
}