X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fconfig%2FConfigFactory.php;h=09b0baa7be85f716ee595ab0bd6ca53ffe08a63b;hb=11ee7f78da9776db26098642a151a288f98bea14;hp=4b803d8eaf4c7a6357c054f4f43cdd37f0e1e7fc;hpb=47b93ded1388ce5712d0a816db4ddd3466609bcd;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/config/ConfigFactory.php b/includes/config/ConfigFactory.php index 4b803d8eaf..2c7afdae07 100644 --- a/includes/config/ConfigFactory.php +++ b/includes/config/ConfigFactory.php @@ -20,13 +20,15 @@ * * @file */ +use MediaWiki\Services\SalvageableService; +use Wikimedia\Assert\Assert; /** * Factory class to create Config objects * * @since 1.23 */ -class ConfigFactory { +class ConfigFactory implements SalvageableService { /** * Map of config name => callback @@ -51,16 +53,67 @@ class ConfigFactory { } /** - * Register a new config factory function - * Will override if it's already registered + * Re-uses existing Cache objects from $other. Cache objects are only re-used if the + * registered factory function for both is the same. Cache config is not copied, + * and only instances of caches defined on this instance with the same config + * are copied. + * + * @see SalvageableService::salvage() + * + * @param SalvageableService $other The object to salvage state from. $other must have the + * exact same type as $this. + */ + public function salvage( SalvageableService $other ) { + Assert::parameterType( self::class, $other, '$other' ); + + /** @var ConfigFactory $other */ + foreach ( $other->factoryFunctions as $name => $otherFunc ) { + if ( !isset( $this->factoryFunctions[$name] ) ) { + continue; + } + + // if the callback function is the same, salvage the Cache object + // XXX: Closures are never equal! + if ( isset( $other->configs[$name] ) + && $this->factoryFunctions[$name] == $otherFunc + ) { + $this->configs[$name] = $other->configs[$name]; + unset( $other->configs[$name] ); + } + } + + // disable $other + $other->factoryFunctions = []; + $other->configs = []; + } + + /** + * @return string[] + */ + public function getConfigNames() { + return array_keys( $this->factoryFunctions ); + } + + /** + * Register a new config factory function. + * Will override if it's already registered. + * Use "*" for $name to provide a fallback config for all unknown names. * @param string $name - * @param callable $callback That takes this ConfigFactory as an argument + * @param callable|Config $callback A factory callback that takes this ConfigFactory + * as an argument and returns a Config instance, or an existing Config instance. * @throws InvalidArgumentException If an invalid callback is provided */ public function register( $name, $callback ) { - if ( !is_callable( $callback ) ) { - throw new InvalidArgumentException( 'Invalid callback provided' ); + if ( !is_callable( $callback ) && !( $callback instanceof Config ) ) { + if ( is_array( $callback ) ) { + $callback = '[ ' . implode( ', ', $callback ) . ' ]'; + } elseif ( is_object( $callback ) ) { + $callback = 'instanceof ' . get_class( $callback ); + } + throw new InvalidArgumentException( 'Invalid callback \'' . $callback . '\' provided' ); } + + unset( $this->configs[$name] ); $this->factoryFunctions[$name] = $callback; } @@ -75,10 +128,20 @@ class ConfigFactory { */ public function makeConfig( $name ) { if ( !isset( $this->configs[$name] ) ) { - if ( !isset( $this->factoryFunctions[$name] ) ) { + $key = $name; + if ( !isset( $this->factoryFunctions[$key] ) ) { + $key = '*'; + } + if ( !isset( $this->factoryFunctions[$key] ) ) { throw new ConfigException( "No registered builder available for $name." ); } - $conf = call_user_func( $this->factoryFunctions[$name], $this ); + + if ( $this->factoryFunctions[$key] instanceof Config ) { + $conf = $this->factoryFunctions[$key]; + } else { + $conf = call_user_func( $this->factoryFunctions[$key], $this ); + } + if ( $conf instanceof Config ) { $this->configs[$name] = $conf; } else { @@ -88,4 +151,5 @@ class ConfigFactory { return $this->configs[$name]; } + }