Merge "Turn DefaultSettings.php into a deprecated stub"

This commit is contained in:
jenkins-bot 2022-05-18 03:28:56 +00:00 committed by Gerrit Code Review
commit df116c5002
26 changed files with 4873 additions and 7324 deletions

View file

@ -83,6 +83,8 @@ $cfg['directory_list'] = [
$cfg['exclude_analysis_directory_list'] = [
'vendor/',
'.phan/',
// Generated documentation stub for configuration variables.
'includes/config-vars.php',
// The referenced classes are not available in vendor, only when
// included from composer.
'includes/composer/',

View file

@ -215,6 +215,9 @@ because of Phabricator reports.
to pass one to wfUrlProtocols anyway);
3) they use type hints (don't try passing null instead of string, etc.).
* MaintainableDBConnRef is deprecated, use DBConnRef instead.
* Loading DefaultSettings.php is deprecated. To get default values of main
config settings, use MainConfigSchema::listDefaultValues() or
MainConfigSchema::getDefaultValue().
* AbstractContent::getRedirectChain() and
AbstractContent::getUltimateRedirectTarget() are now emitting deprecation
warnings (T296430).

View file

@ -540,10 +540,10 @@ $wgAutoloadLocalClasses = [
'GanConverter' => __DIR__ . '/includes/language/converters/GanConverter.php',
'GenderCache' => __DIR__ . '/includes/cache/GenderCache.php',
'GenerateCollationData' => __DIR__ . '/maintenance/language/generateCollationData.php',
'GenerateConfigDefaultSettings' => __DIR__ . '/maintenance/generateConfigDefaultSettings.php',
'GenerateConfigNames' => __DIR__ . '/maintenance/generateConfigNames.php',
'GenerateConfigSchemaArray' => __DIR__ . '/maintenance/generateConfigSchemaArray.php',
'GenerateConfigSchemaYaml' => __DIR__ . '/maintenance/generateConfigSchemaYaml.php',
'GenerateConfigVars' => __DIR__ . '/maintenance/generateConfigVars.php',
'GenerateJsonI18n' => __DIR__ . '/maintenance/generateJsonI18n.php',
'GenerateNormalizerDataAr' => __DIR__ . '/maintenance/language/generateNormalizerDataAr.php',
'GenerateNormalizerDataMl' => __DIR__ . '/maintenance/language/generateNormalizerDataMl.php',

File diff suppressed because it is too large Load diff

View file

@ -1,38 +0,0 @@
<?php
/**
* Generated stub variables for MediaWiki configuration settings.
* This exists for the benefit of documentation and IDE integration.
*
*
* NEVER EDIT THIS FILE
*
*
* To customize your installation, edit "LocalSettings.php". If you make
* changes here, they will be lost on next upgrade of MediaWiki!
*
* Developers who want to introduce new configuration or change defaults
* should edit the constants in the MainConfigSchema class.
* The template for this file itself is DefaultSettings.template.
*
* Documentation for each configuration variable can be found in the
* MainConfigSchema class and on the following page:
* https://www.mediawiki.org/wiki/Manual:Configuration_settings
*
* @file
*/
// phpcs:disable
/**
* @cond file_level_code
* This is not a valid entry point, perform no further processing unless
* MEDIAWIKI is defined
*/
if ( !defined( 'MEDIAWIKI' ) ) {
echo "This file is part of MediaWiki and is not a valid entry point\n";
die( 1 );
}
/** @endcond */
{{AUTO-GENERATED-SECTION}}

View file

@ -33,9 +33,11 @@ use EnotifNotifyJob;
use EnqueueJob;
use EventRelayerNull;
use FallbackContentHandler;
use Generator;
use HashBagOStuff;
use HTMLCacheUpdateJob;
use ImportLogFormatter;
use InvalidArgumentException;
use JavaScriptContentHandler;
use JobQueueDB;
use JsonContentHandler;
@ -58,6 +60,7 @@ use ProtectLogFormatter;
use PublishStashedFileJob;
use RecentChangesUpdateJob;
use RedisPubSubFeedEngine;
use ReflectionClass;
use RefreshLinksJob;
use ReplicatedBagOStuff;
use RevertedTagUpdateJob;
@ -100,6 +103,74 @@ use WinCacheBagOStuff;
*/
class MainConfigSchema {
/**
* Returns a generator for iterating over all config settings and their default values.
* The primary use of this method is to import default values into local scope.
* @code
* foreach ( MainConfigSchema::listDefaultValues( 'wg' ) as $var => $value ) {
* $$var = $value;
* }
* @endcode
*
* There should be no reason for application logic to do this.
*
* @note This method is relatively slow, it should not be used by
* performance critical code. Application logic should generally
* use ConfigSchema instead
*
* @param string $prefix A prefix to prepend to each setting name.
* Typically, this will be "wg" when constructing global
* variable names.
*
* @return Generator<string,mixed> $settingName => $defaultValue
*/
public static function listDefaultValues( string $prefix = '' ): Generator {
$class = new ReflectionClass( self::class );
foreach ( $class->getReflectionConstants() as $const ) {
if ( !$const->isPublic() ) {
continue;
}
$value = $const->getValue();
if ( !is_array( $value ) ) {
// Just in case we end up having some other kind of constant on this class.
continue;
}
$name = $const->getName();
yield "$prefix$name" => $value['default'] ?? null;
}
}
/**
* Returns the default value of the given config setting.
*
* @note This method is relatively slow, it should not be used by
* performance critical code. Application logic should generally
* use ConfigSchema instead
*
* @param string $name The config setting name.
*
* @return mixed The given config setting's default value, or null
* if no default value is specified in the schema.
*/
public static function getDefaultValue( string $name ) {
$class = new ReflectionClass( self::class );
if ( !$class->hasConstant( $name ) ) {
throw new InvalidArgumentException( "Unknown setting: $name" );
}
$value = $class->getConstant( $name );
if ( !is_array( $value ) ) {
// Might happen if we end up having other kinds of constants on this class.
throw new InvalidArgumentException( "Unknown setting: $name" );
}
return $value['default'] ?? null;
}
/***************************************************************************/
/**
* Registry of factory functions to create config objects:
* The 'main' key must be set, and the value should be a valid

View file

@ -96,6 +96,7 @@ use MediaWiki\Revision\RevisionRenderer;
use MediaWiki\Revision\RevisionStore;
use MediaWiki\Revision\RevisionStoreFactory;
use MediaWiki\Revision\SlotRoleRegistry;
use MediaWiki\Settings\Config\ConfigSchema;
use MediaWiki\Shell\CommandFactory;
use MediaWiki\Shell\ShellboxClientFactory;
use MediaWiki\SpecialPage\SpecialPageFactory;
@ -823,6 +824,14 @@ class MediaWikiServices extends ServiceContainer {
return $this->getService( 'ConfigRepository' );
}
/**
* @since 1.39
* @return ConfigSchema
*/
public function getConfigSchema(): ConfigSchema {
return $this->getService( 'ConfigSchema' );
}
/**
* @since 1.29
* @return ConfiguredReadOnlyMode

View file

@ -138,6 +138,7 @@ use MediaWiki\Revision\RevisionRenderer;
use MediaWiki\Revision\RevisionStore;
use MediaWiki\Revision\RevisionStoreFactory;
use MediaWiki\Revision\SlotRoleRegistry;
use MediaWiki\Settings\Config\ConfigSchema;
use MediaWiki\Shell\CommandFactory;
use MediaWiki\Shell\ShellboxClientFactory;
use MediaWiki\SpecialPage\SpecialPageFactory;
@ -415,6 +416,11 @@ return [
return new ConfigRepository( $services->getConfigFactory() );
},
'ConfigSchema' => static function ( MediaWikiServices $services ): ConfigSchema {
global $wgSettings; // TODO: have Setup.php declare this service
return $wgSettings->getConfigSchema();
},
'ConfiguredReadOnlyMode' => static function ( MediaWikiServices $services ): ConfiguredReadOnlyMode {
$config = $services->getMainConfig();
return new ConfiguredReadOnlyMode(

View file

@ -0,0 +1,65 @@
<?php
namespace MediaWiki\Settings\Config;
use MediaWiki\Settings\SettingsBuilderException;
/**
* Represents a config schema.
*
* @since 1.39
*/
interface ConfigSchema {
/**
* Get a list of all defined keys
*
* @return string[]
*/
public function getDefinedKeys(): array;
/**
* Check whether schema for $key is defined.
*
* @param string $key
*
* @return bool
*/
public function hasSchemaFor( string $key ): bool;
/**
* Get all defined default values.
*
* @return array<string,mixed> An associative array mapping setting names
* to their respective default values.
*/
public function getDefaults(): array;
/**
* Check if the $key has a default values set in the schema.
*
* @param string $key
*
* @return bool
*/
public function hasDefaultFor( string $key ): bool;
/**
* Get default value for the $key.
* For keys that do not define a default, null is assumed.
*
* @param string $key
*
* @return mixed
*/
public function getDefaultFor( string $key );
/**
* Get the merge strategy defined for the $key, or null if none defined.
*
* @param string $key
*
* @return MergeStrategy|null
* @throws SettingsBuilderException if merge strategy name is invalid.
*/
public function getMergeStrategyFor( string $key ): ?MergeStrategy;
}

View file

@ -16,7 +16,7 @@ use function array_key_exists;
* for settings defaults, types and merge strategies in bulk, and later
* accessing them independently of each other, for each config key.
*/
class ConfigSchemaAggregator {
class ConfigSchemaAggregator implements ConfigSchema {
/** @var array[] Maps config keys to JSON schema structures */
private $schemas = [];
@ -183,7 +183,7 @@ class ConfigSchemaAggregator {
}
/**
* Get all known default values.
* Get all defined default values.
*
* @return array
*/
@ -221,6 +221,7 @@ class ConfigSchemaAggregator {
/**
* Get default value for the $key.
* For keys that do not define a default, null is assumed.
*
* @param string $key
* @return mixed

View file

@ -11,6 +11,7 @@ use MediaWiki\MainConfigNames;
use MediaWiki\Settings\Cache\CacheableSource;
use MediaWiki\Settings\Cache\CachedSource;
use MediaWiki\Settings\Config\ConfigBuilder;
use MediaWiki\Settings\Config\ConfigSchema;
use MediaWiki\Settings\Config\ConfigSchemaAggregator;
use MediaWiki\Settings\Config\PhpIniSink;
use MediaWiki\Settings\Source\ArraySource;
@ -195,7 +196,8 @@ class SettingsBuilder {
}
/**
* Return a Config object with all the default settings loaded so far.
* Return a Config object with default for all settings from all schemas loaded so far.
* If the schema for a setting doesn't specify a default, null is assumed.
*
* @note This will implicitly call apply()
*
@ -203,7 +205,22 @@ class SettingsBuilder {
*/
public function getDefaultConfig(): IterableConfig {
$this->apply();
return new HashConfig( $this->configSchema->getDefaults() );
$defaults = $this->configSchema->getDefaults();
$nulls = array_fill_keys( $this->configSchema->getDefinedKeys(), null );
return new HashConfig( array_merge( $nulls, $defaults ) );
}
/**
* Return the configuration schema.
*
* @note This will implicitly call apply()
*
* @return ConfigSchema
*/
public function getConfigSchema(): ConfigSchema {
$this->apply();
return $this->configSchema;
}
/**

View file

@ -156,6 +156,7 @@ if ( defined( 'MW_USE_CONFIG_SCHEMA_CLASS' ) ) {
require_once MW_INSTALL_PATH . '/includes/DefaultSettings.php';
// This is temporary until we no longer need this mode.
// TODO: delete config-merge-strategies.php when this code is removed.
$wgSettings->load( new PhpSettingsSource( MW_INSTALL_PATH . '/includes/config-merge-strategies.php' ) );
} else {
$wgSettings->load( new PhpSettingsSource( MW_INSTALL_PATH . '/includes/config-schema.php' ) );
@ -184,6 +185,20 @@ $wgSettings->putConfigValues( [
] );
$wgSettings->apply();
// $wgSettings->apply() puts all configuration into global variables.
// If we are not in global scope, make all relevant globals available
// in this file's scope as well.
$wgScopeTest = 'MediaWiki Setup.php scope test';
if ( !isset( $GLOBALS['wgScopeTest'] ) || $GLOBALS['wgScopeTest'] !== $wgScopeTest ) {
foreach ( $wgSettings->getConfigSchema()->getDefinedKeys() as $key ) {
$var = "wg$key";
// phpcs:ignore MediaWiki.NamingConventions.ValidGlobalName.allowedPrefix
global $$var;
}
unset( $key, $var );
}
unset( $wgScopeTest );
if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
call_user_func( MW_CONFIG_CALLBACK, $wgSettings );
} else {
@ -211,7 +226,7 @@ $wgSettings->apply();
/**
* Customization point after all loading (constants, functions, classes,
* DefaultSettings, LocalSettings). Specifically, this is before usage of
* LocalSettings). Specifically, this is before usage of
* settings, before instantiation of Profiler (and other singletons), and
* before any setup functions or hooks run.
*/
@ -539,6 +554,8 @@ if ( !$wgCommandLineMode ) {
Pingback::schedulePingback();
}
// Explicit globals, so this works with bootstrap.php
global $wgFullyInitialised;
$wgFullyInitialised = true;
// T264370

View file

@ -326,11 +326,16 @@ if ( $wgEnableEmail ) {
$wgUsersNotifiedOnAllChanges = [];
}
if ( $wgLocaltimezone === null ) {
if ( !$wgLocaltimezone ) {
// This defaults to the `date.timezone` value of the PHP INI option. If this option is not set,
// it falls back to UTC. Prior to PHP 7.0, this fallback produced a warning.
$wgLocaltimezone = date_default_timezone_get();
}
if ( !$wgLocaltimezone ) {
// Make doubly sure we have a valid time zone, even if date_default_timezone_get()
// returned garbage.
$wgLocaltimezone = 'UTC';
}
date_default_timezone_set( $wgLocaltimezone );
if ( $wgLocalTZoffset === null ) {
$wgLocalTZoffset = (int)date( 'Z' ) / 60;

View file

@ -1,5 +1,11 @@
<?php
/**
* Schema containing merge strategies to supplement the information coming from
* DefaultSettings.php. Only used in Setup.php if MW_USE_LEGACY_DEFAULT_SETTINGS
* is set.
*
* @todo Remove this when it is no longer needed.
*/
use MediaWiki\MainConfigNames;
return [

4432
includes/config-vars.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,7 @@ use MediaWiki\HookContainer\HookContainer;
use MediaWiki\HookContainer\StaticHookRegistry;
use MediaWiki\Interwiki\NullInterwikiLookup;
use MediaWiki\MainConfigNames;
use MediaWiki\MainConfigSchema;
use MediaWiki\MediaWikiServices;
use MediaWiki\Settings\SettingsBuilder;
use Wikimedia\AtEase\AtEase;
@ -169,34 +170,33 @@ abstract class Installer {
*
* @var array
*/
protected $defaultVarNames = [
'wgSitename',
'wgPasswordSender',
'wgLanguageCode',
'wgLocaltimezone',
'wgRightsIcon',
'wgRightsText',
'wgRightsUrl',
'wgEnableEmail',
'wgEnableUserEmail',
'wgEnotifUserTalk',
'wgEnotifWatchlist',
'wgEmailAuthentication',
'wgDBname',
'wgDBtype',
'wgDiff3',
'wgImageMagickConvertCommand',
'wgGitBin',
'IP',
'wgScriptPath',
'wgMetaNamespace',
'wgDeletedDirectory',
'wgEnableUploads',
'wgSecretKey',
'wgUseInstantCommons',
'wgUpgradeKey',
'wgDefaultSkin',
'wgPingback',
private const DEFAULT_VAR_NAMES = [
'Sitename',
'PasswordSender',
'LanguageCode',
'Localtimezone',
'RightsIcon',
'RightsText',
'RightsUrl',
'EnableEmail',
'EnableUserEmail',
'EnotifUserTalk',
'EnotifWatchlist',
'EmailAuthentication',
'DBname',
'DBtype',
'Diff3',
'ImageMagickConvertCommand',
'GitBin',
'ScriptPath',
'MetaNamespace',
'DeletedDirectory',
'EnableUploads',
'SecretKey',
'UseInstantCommons',
'UpgradeKey',
'DefaultSkin',
'Pingback',
];
/**
@ -442,8 +442,9 @@ abstract class Installer {
private function getDefaultSettings(): array {
$ret = $this->internalDefaults;
foreach ( $this->defaultVarNames as $var ) {
$ret[$var] = $GLOBALS[$var];
foreach ( self::DEFAULT_VAR_NAMES as $name ) {
$var = "wg{$name}";
$ret[$var] = MainConfigSchema::getDefaultValue( $name );
}
return $ret;
}
@ -586,7 +587,7 @@ abstract class Installer {
/**
* Get an MW configuration variable, or internal installer configuration variable.
* The defaults come from $GLOBALS (ultimately DefaultSettings.php).
* The defaults come from MainConfigSchema.
* Installer variables are typically prefixed by an underscore.
*
* @param string $name
@ -678,7 +679,11 @@ abstract class Installer {
}
unset( $lsExists );
require "$IP/includes/DefaultSettings.php";
// Extract the defaults into the current scope
foreach ( MainConfigSchema::listDefaultValues( 'wg' ) as $var => $value ) {
$$var = $value;
}
$wgExtensionDirectory = "$IP/extensions";
$wgStyleDirectory = "$IP/skins";
@ -1540,7 +1545,10 @@ abstract class Installer {
* but we're not opening that can of worms
* @see https://phabricator.wikimedia.org/T28857
*/
require "$IP/includes/DefaultSettings.php";
// Extract the defaults into the current scope
foreach ( MainConfigSchema::listDefaultValues( 'wg' ) as $var => $value ) {
$$var = $value;
}
// phpcs:ignore MediaWiki.VariableAnalysis.UnusedGlobalVariables
global $wgAutoloadClasses, $wgExtensionDirectory, $wgStyleDirectory;

View file

@ -207,7 +207,7 @@ class SiteConfig extends ISiteConfig {
// Override parent default
// Override parent default
if ( isset( $this->parsoidSettings['linting'] ) ) {
// @todo: Add this setting to MW's DefaultSettings.php
// @todo: Add this setting to MW's MainConfigSchema
$this->linterEnabled = $this->parsoidSettings['linting'];
}

View file

@ -1,97 +0,0 @@
<?php
use MediaWiki\Settings\Source\JsonTypeHelper;
use Wikimedia\StaticArrayWriter;
require_once __DIR__ . '/Maintenance.php';
require_once __DIR__ . '/includes/ConfigSchemaDerivativeTrait.php';
// Tell Setup.php to load the config schema from MainConfigSchema rather than
// any generated file, so we can use this script to re-generate a broken schema file.
define( 'MW_USE_CONFIG_SCHEMA_CLASS', 1 );
/**
* Maintenance script that generates a DefaultSettings.php file,
* for backwards compatibility and as documentation stub.
*
* @ingroup Maintenance
*/
class GenerateConfigDefaultSettings extends Maintenance {
use ConfigSchemaDerivativeTrait;
/** @var string */
private const DEFAULT_OUTPUT_PATH = __DIR__ . '/../includes/DefaultSettings.php';
/** @var JsonTypeHelper */
private $jsonTypeHelper;
public function __construct() {
parent::__construct();
$this->addDescription( 'Generate the DefaultSettings.php file.' );
$this->addOption(
'output',
'Path to output relative to $IP. Default: ' . self::DEFAULT_OUTPUT_PATH,
false,
true
);
}
public function execute() {
$this->jsonTypeHelper = new JsonTypeHelper();
$input = $this->loadSettingsSource();
$code = '';
// Details about each config variable
foreach ( $input['config-schema'] as $configKey => $configSchema ) {
$code .= "\n";
$code .= $this->getVariableDeclaration( $configKey, $configSchema );
}
$newContent = $this->processTemplate( MW_INSTALL_PATH . '/includes/DefaultSettings.template', $code );
$this->writeOutput( self::DEFAULT_OUTPUT_PATH, $newContent );
}
/**
* @param string $name
* @param array $schema
*
* @return string
*/
private function getVariableDeclaration( string $name, array $schema ): string {
$doc = [];
$docType = null;
if ( isset( $schema['type'] ) ) {
$docType = $this->jsonTypeHelper->jsonToPhpDoc( $schema['type'] );
}
$doc[] = "Variable for the $name setting, for use in LocalSettings.php";
$doc[] = "@see MainConfigSchema::$name";
$doc[] = "@note Do not change manually, " .
"generated by maintenance/generateConfigDefaultSettings.php!";
if ( isset( $schema['since'] ) ) {
$doc[] = "@since {$schema['since']}";
}
if ( isset( $schema['deprecated'] ) ) {
$deprecated = str_replace( "\n", "\n * ", wordwrap( $schema['deprecated'] ) );
$doc[] = "@deprecated {$deprecated}";
}
if ( $docType ) {
$doc[] = "@var $docType";
}
$code = "/**\n * ";
$code .= implode( "\n * ", $doc );
$code .= "\n */\n";
$value = StaticArrayWriter::encodeValue( $schema['default'] ?? null );
$code .= "\$wg{$name} = {$value};\n";
return $code;
}
}
$maintClass = GenerateConfigDefaultSettings::class;
require_once RUN_MAINTENANCE_IF_MAIN;

View file

@ -0,0 +1,93 @@
<?php
use MediaWiki\Settings\Source\JsonTypeHelper;
require_once __DIR__ . '/Maintenance.php';
require_once __DIR__ . '/includes/ConfigSchemaDerivativeTrait.php';
// Tell Setup.php to load the config schema from MainConfigSchema rather than
// any generated file, so we can use this script to re-generate a broken schema file.
define( 'MW_USE_CONFIG_SCHEMA_CLASS', 1 );
/**
* Maintenance script that generates a config-vars.php file,
* as documentation stub.
*
* @ingroup Maintenance
*/
class GenerateConfigVars extends Maintenance {
use ConfigSchemaDerivativeTrait;
/** @var string */
private const DEFAULT_OUTPUT_PATH = __DIR__ . '/../includes/config-vars.php';
/**
* @var JsonTypeHelper
*/
private $jsonTypeHelper;
public function __construct() {
parent::__construct();
$this->addDescription( 'Generate the config-vars.php file.' );
$this->addOption(
'output',
'Path to output relative to $IP. Default: ' . self::DEFAULT_OUTPUT_PATH,
false,
true
);
}
public function execute() {
$this->jsonTypeHelper = new JsonTypeHelper();
$settings = $this->loadSettingsSource();
$content = "<?php\n";
$content .= "/**\n" .
" * This file is automatically generated using maintenance/generateConfigVars.php.\n" .
" * Do not modify this file manually, edit includes/MainConfigSchema.php instead.\n" .
" */\n";
$content .= "// phpcs:disable\n";
$content .= "throw new LogicException( 'Do not load config-vars.php, " .
"it exists as a documentation stub only' );\n";
foreach ( $settings['config-schema'] as $name => $schema ) {
$content .= "\n";
$content .= $this->getVariableDeclaration( $name, $schema );
}
$this->writeOutput( self::DEFAULT_OUTPUT_PATH, $content );
}
/**
* @param string $name
* @param array $schema
*
* @return string
*/
private function getVariableDeclaration( string $name, array $schema ): string {
$chunks = [];
$chunks[] = "Config variable stub for the $name setting, for use by phpdoc and IDEs.";
$chunks[] = "@see MediaWiki\\MainConfigSchema::$name";
if ( isset( $schema['since'] ) ) {
$chunks[] = "@since {$schema['since']}";
}
if ( isset( $schema['deprecated'] ) ) {
$deprecated = str_replace( "\n", "\n * ", wordwrap( $schema['deprecated'] ) );
$chunks[] = "@deprecated {$deprecated}";
}
$code = "/**\n * ";
$code .= implode( "\n * ", $chunks );
$code .= "\n */\n";
$code .= "\$wg{$name} = null;\n";
return $code;
}
}
$maintClass = GenerateConfigVars::class;
require_once RUN_MAINTENANCE_IF_MAIN;

View file

@ -22,8 +22,9 @@ class TestSetup {
}
/**
* This should be called before Setup.php, e.g. from the finalSetup() method
* of a Maintenance subclass
* Overrides config settings for testing.
* This should be called after loading local settings, typically from the finalSetup() method
* of a Maintenance subclass which then gets called via MW_SETUP_CALLBACK in Setup.php.
*/
public static function applyInitialConfig() {
global $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType, $wgMainWANCache, $wgSessionCacheType;

View file

@ -174,7 +174,6 @@ abstract class MediaWikiIntegrationTestCase extends PHPUnit\Framework\TestCase {
if ( defined( 'MW_PHPUNIT_UNIT' ) ) {
$IP = realpath( __DIR__ . '/../..' );
TestSetup::requireOnceInGlobalScope( "$IP/includes/Defines.php" );
TestSetup::requireOnceInGlobalScope( "$IP/includes/DefaultSettings.php" );
TestSetup::requireOnceInGlobalScope( "$IP/includes/GlobalFunctions.php" );
TestSetup::requireOnceInGlobalScope( "$IP/includes/Setup.php" );
TestSetup::requireOnceInGlobalScope( "$IP/tests/common/TestsAutoLoader.php" );

View file

@ -22,6 +22,8 @@
* @ingroup Testing
*/
use MediaWiki\MainConfigSchema;
if ( PHP_SAPI !== 'cli' ) {
die( 'This file is only meant to be executed indirectly by PHPUnit\'s bootstrap process!' );
}
@ -48,17 +50,23 @@ $GLOBALS['IP'] = $IP;
TestSetup::snapshotGlobals();
// Faking in lieu of Setup.php
$GLOBALS['wgScopeTest'] = 'MediaWiki Setup.php scope test';
$GLOBALS['wgCommandLineMode'] = true;
$GLOBALS['wgAutoloadClasses'] = [];
$GLOBALS['wgBaseDirectory'] = MW_INSTALL_PATH;
TestSetup::requireOnceInGlobalScope( "$IP/includes/AutoLoader.php" );
TestSetup::requireOnceInGlobalScope( "$IP/tests/common/TestsAutoLoader.php" );
TestSetup::requireOnceInGlobalScope( "$IP/includes/Defines.php" );
TestSetup::requireOnceInGlobalScope( "$IP/includes/DefaultSettings.php" );
TestSetup::requireOnceInGlobalScope( "$IP/includes/DevelopmentSettings.php" );
TestSetup::requireOnceInGlobalScope( "$IP/includes/GlobalFunctions.php" );
// Extract the defaults into global variables.
// NOTE: this does not apply any dynamic defaults.
foreach ( MainConfigSchema::listDefaultValues( 'wg' ) as $var => $value ) {
$GLOBALS[$var] = $value;
}
TestSetup::requireOnceInGlobalScope( "$IP/includes/DevelopmentSettings.php" );
TestSetup::applyInitialConfig();
MediaWikiCliOptions::initialize();

View file

@ -78,9 +78,9 @@ class SettingsTest extends MediaWikiIntegrationTestCase {
'script' => MW_INSTALL_PATH . '/maintenance/generateConfigSchemaArray.php',
'expectedFile' => MW_INSTALL_PATH . '/includes/config-schema.php',
];
yield 'includes/DefaultSettings.php' => [
'script' => MW_INSTALL_PATH . '/maintenance/generateConfigDefaultSettings.php',
'expectedFile' => MW_INSTALL_PATH . '/includes/DefaultSettings.php',
yield 'includes/config-vars.php' => [
'script' => MW_INSTALL_PATH . '/maintenance/generateConfigVars.php',
'expectedFile' => MW_INSTALL_PATH . '/includes/config-vars.php',
];
yield 'docs/config-schema.yaml' => [
'script' => MW_INSTALL_PATH . '/maintenance/generateConfigSchemaYaml.php',
@ -125,6 +125,7 @@ class SettingsTest extends MediaWikiIntegrationTestCase {
* @dataProvider provideDefaultSettingsConsistency
*/
public function testDefaultSettingsConsistency( SettingsSource $source ) {
$this->expectDeprecationAndContinue( '/DefaultSettings\\.php/' );
$defaultSettingsProps = ( static function () {
require MW_INSTALL_PATH . '/includes/DefaultSettings.php';
$vars = get_defined_vars();
@ -518,4 +519,24 @@ class SettingsTest extends MediaWikiIntegrationTestCase {
);
}
/**
* @covers \MediaWiki\MainConfigSchema::listDefaultValues
* @covers \MediaWiki\MainConfigSchema::getDefaultValue
*/
public function testMainConfigSchemaDefaults() {
$defaults = iterator_to_array( MainConfigSchema::listDefaultValues() );
$prefixed = iterator_to_array( MainConfigSchema::listDefaultValues( 'wg' ) );
$schema = $this->getSchemaData();
foreach ( $schema['config-schema'] as $name => $sch ) {
$this->assertArrayHasKey( $name, $defaults );
$this->assertArrayHasKey( "wg$name", $prefixed );
$this->assertSame( $sch['default'] ?? null, $defaults[$name] );
$this->assertSame( $sch['default'] ?? null, $prefixed["wg$name"] );
$this->assertSame( $sch['default'] ?? null, MainConfigSchema::getDefaultValue( $name ) );
}
}
}

View file

@ -46,6 +46,26 @@ class ConfigSchemaAggregatorTest extends TestCase {
], $aggregator->getDefaults() );
}
public function testGetDefaults() {
$aggregator = new ConfigSchemaAggregator();
$aggregator->addSchema( 'no_default', [ 'type' => 'string', ] );
$aggregator->addSchema( 'with_default', [ 'type' => 'string', 'default' => 'bla', ] );
$aggregator->addSchema(
'another_with_default',
[ 'type' => 'string', 'default' => 'blabla', ]
);
$this->assertEquals( [
'with_default' => 'bla',
'another_with_default' => 'blabla',
], $aggregator->getDefaults() );
$this->assertFalse( $aggregator->hasDefaultFor( 'no_default' ) );
$this->assertNull( $aggregator->getDefaultFor( 'no_default' ) );
$this->assertTrue( $aggregator->hasDefaultFor( 'with_default' ) );
$this->assertSame( 'bla', $aggregator->getDefaultFor( 'with_default' ) );
}
public function testDefaultOverrideFails() {
$aggregator = new ConfigSchemaAggregator();
$aggregator->addSchema( 'foo', [ 'default' => 'bla', ] );

View file

@ -547,11 +547,26 @@ class SettingsBuilderTest extends TestCase {
public function testGetDefaultConfig() {
$defaultConfig = $this->newSettingsBuilder()
->loadArray( [ 'config-schema' => [ 'MySetting' => [ 'default' => 'bla' ], ], ] )
->loadArray( [ 'config-schema' => [
'MySetting' => [ 'default' => 'bla' ],
'OtherSetting' => [ 'type' => 'number' ], // no default
] ] )
->apply()
->getDefaultConfig();
$this->assertTrue( $defaultConfig->has( 'MySetting' ) );
$this->assertSame( 'bla', $defaultConfig->get( 'MySetting' ) );
$this->assertTrue( $defaultConfig->has( 'OtherSetting' ) );
$this->assertNull( $defaultConfig->get( 'OtherSetting' ) );
}
public function testGetConfigSchema() {
$configSchema = $this->newSettingsBuilder()
->loadArray( [ 'config-schema' => [ 'MySetting' => [ 'default' => 'bla' ], ], ] )
->apply()
->getConfigSchema();
$this->assertTrue( $configSchema->hasSchemaFor( 'MySetting' ) );
$this->assertSame( 'bla', $configSchema->getDefaultFor( 'MySetting' ) );
}
}

View file

@ -969,8 +969,9 @@ class SetupDynamicConfigTest extends MediaWikiUnitTestCase {
* argument, and a ScopedCallback may optionally be returned.
*/
public function testGlobals( array $test, $expected, ?callable $setup = null ): void {
$IP = '/install/path';
require MW_INSTALL_PATH . '/includes/DefaultSettings.php';
foreach ( MainConfigSchema::listDefaultValues( 'wg' ) as $key => $val ) {
$$key = $val;
}
foreach ( $test as $key => $val ) {
// $wgCacheEpoch default doesn't work properly on CI if evaluated in the provider
$$key = is_callable( $val ) ? $val() : $val;
@ -978,6 +979,8 @@ class SetupDynamicConfigTest extends MediaWikiUnitTestCase {
if ( $setup ) {
$scopedCallback = $setup( $this );
}
$IP = '/install/path';
require MW_INSTALL_PATH . '/includes/SetupDynamicConfig.php';
if ( is_callable( $expected ) ) {