5 use InvalidArgumentException;
6 use Psr\Container\ContainerInterface;
8 use Wikimedia\Assert\Assert;
9 use Wikimedia\ScopedCallback;
114 $this->serviceInstantiators = [];
116 $this->services = [];
117 $this->destroyed =
true;
126 foreach ( $wiringFiles as
$file ) {
128 $wiring = require
$file;
130 Assert::postcondition(
132 "Wiring file $file is expected to return an array!"
164 $newInstantiators = array_diff_key(
165 $container->serviceInstantiators,
169 $this->serviceInstantiators = array_merge(
170 $this->serviceInstantiators,
174 $newManipulators = array_diff(
175 array_keys( $container->serviceManipulators ),
179 foreach ( $newManipulators as $name ) {
180 if ( isset( $this->serviceManipulators[$name] ) ) {
181 $this->serviceManipulators[$name] = array_merge(
182 $this->serviceManipulators[$name],
183 $container->serviceManipulators[$name]
186 $this->serviceManipulators[$name] = $container->serviceManipulators[$name];
200 return isset( $this->serviceInstantiators[$name] );
204 public function has( $name ) {
228 return $this->services[$name] ??
null;
235 return array_keys( $this->serviceInstantiators );
253 Assert::parameterType(
'string', $name,
'$name' );
259 $this->serviceInstantiators[$name] = $instantiator;
282 Assert::parameterType(
'string', $name,
'$name' );
288 if ( isset( $this->services[$name] ) ) {
292 $this->serviceInstantiators[$name] = $instantiator;
293 unset( $this->disabled[$name] );
323 Assert::parameterType(
'string', $name,
'$name' );
329 if ( isset( $this->services[$name] ) ) {
333 $this->serviceManipulators[$name][] = $manipulator;
358 $this->disabled[$name] =
true;
385 Assert::parameterType(
'string', $name,
'$name' );
390 $instance->destroy();
393 unset( $this->services[$name] );
394 unset( $this->disabled[$name] );
418 if ( $this->destroyed ) {
422 if ( isset( $this->disabled[$name] ) ) {
426 if ( !isset( $this->services[$name] ) ) {
430 return $this->services[$name];
434 public function get( $name ) {
446 if ( isset( $this->serviceInstantiators[$name] ) ) {
447 if ( isset( $this->servicesBeingCreated[$name] ) ) {
448 throw new RuntimeException(
"Circular dependency when creating service! " .
449 implode(
' -> ', array_keys( $this->servicesBeingCreated ) ) .
" -> $name" );
451 $this->servicesBeingCreated[$name] =
true;
452 $removeFromStack =
new ScopedCallback(
function () use ( $name ) {
453 unset( $this->servicesBeingCreated[$name] );
456 $service = ( $this->serviceInstantiators[$name] )(
458 ...$this->extraInstantiationParams
461 if ( isset( $this->serviceManipulators[$name] ) ) {
462 foreach ( $this->serviceManipulators[$name] as $callback ) {
463 $ret = call_user_func_array(
465 array_merge( [ $service, $this ], $this->extraInstantiationParams )
471 if ( $ret !==
null ) {
477 $removeFromStack->consume();
493 return isset( $this->disabled[$name] );
501 class_alias( ServiceContainer::class,
'MediaWiki\Services\ServiceContainer' );