Add doc-typehints to class properties found by the PropertyDocumentation sniff to improve the documentation. Once the sniff is enabled it avoids that new code is missing type declarations. This is focused on documentation and does not change code. Change-Id: I1da4b272a6b28c419cc8e860d142dae19ca0bbcf
98 lines
3.2 KiB
PHP
98 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Config;
|
|
|
|
use InvalidArgumentException;
|
|
use Wikimedia\Assert\Assert;
|
|
|
|
/**
|
|
* A class for passing options to services. It can be constructed from a Config, and in practice
|
|
* most options will be taken from site configuration, but they don't have to be. The options passed
|
|
* are copied and will not reflect subsequent updates to site configuration (assuming they're not
|
|
* objects).
|
|
*
|
|
* Services that take this type as a parameter to their constructor should specify a list of the
|
|
* keys they expect to receive in an array. The convention is to make it a public const called
|
|
* CONSTRUCTOR_OPTIONS. In the constructor, they should call assertRequiredOptions() to make sure
|
|
* that they weren't passed too few or too many options. This way it's clear what each class
|
|
* depends on, and that it's getting passed the correct set of options. (This means there are no
|
|
* optional options. This makes sense for services, since they shouldn't be constructed by
|
|
* outside code.)
|
|
*
|
|
* @newable since 1.36
|
|
*
|
|
* @since 1.34
|
|
*/
|
|
class ServiceOptions {
|
|
/** @var string[] */
|
|
private $keys;
|
|
/** @var array */
|
|
private $options = [];
|
|
|
|
/**
|
|
* @stable to call since 1.36
|
|
*
|
|
* @param string[] $keys Which keys to extract from $sources
|
|
* @param Config|ServiceOptions|array ...$sources Each source is either a Config object or an array. If the
|
|
* same key is present in two sources, the first one takes precedence. Keys that are not in
|
|
* $keys are ignored.
|
|
* @throws InvalidArgumentException if one of $keys is not found in any of $sources
|
|
*/
|
|
public function __construct( array $keys, ...$sources ) {
|
|
$this->keys = $keys;
|
|
foreach ( $keys as $key ) {
|
|
foreach ( $sources as $source ) {
|
|
if ( $source instanceof Config ) {
|
|
if ( $source->has( $key ) ) {
|
|
$this->options[$key] = $source->get( $key );
|
|
continue 2;
|
|
}
|
|
} elseif ( $source instanceof ServiceOptions ) {
|
|
if ( array_key_exists( $key, $source->options ) ) {
|
|
$this->options[$key] = $source->get( $key );
|
|
continue 2;
|
|
}
|
|
} elseif ( array_key_exists( $key, $source ) ) {
|
|
$this->options[$key] = $source[$key];
|
|
continue 2;
|
|
}
|
|
}
|
|
throw new InvalidArgumentException( "Key \"$key\" not found in input sources" );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assert that the list of options provided in this instance exactly match $expectedKeys,
|
|
* without regard for order.
|
|
*
|
|
* @param string[] $expectedKeys
|
|
*/
|
|
public function assertRequiredOptions( array $expectedKeys ) {
|
|
if ( $this->keys !== $expectedKeys ) {
|
|
$extraKeys = array_diff( $this->keys, $expectedKeys );
|
|
$missingKeys = array_diff( $expectedKeys, $this->keys );
|
|
Assert::precondition( !$extraKeys && !$missingKeys,
|
|
(
|
|
$extraKeys
|
|
? 'Unsupported options passed: ' . implode( ', ', $extraKeys ) . '!'
|
|
: ''
|
|
) . ( $extraKeys && $missingKeys ? ' ' : '' ) . (
|
|
$missingKeys
|
|
? 'Required options missing: ' . implode( ', ', $missingKeys ) . '!'
|
|
: ''
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $key
|
|
* @return mixed
|
|
*/
|
|
public function get( $key ) {
|
|
if ( !array_key_exists( $key, $this->options ) ) {
|
|
throw new InvalidArgumentException( "Unrecognized option \"$key\"" );
|
|
}
|
|
return $this->options[$key];
|
|
}
|
|
}
|