23 'class' => MessageProvider::class,
28 'ContentHandlerFactory',
33 private const OBJECT_FACTORY_KEYS = [
34 'class',
'factory',
'args',
'services',
'optional_services'
37 private const CORE = 0;
38 private const EXTENSION = 1;
41 private array $providers = [];
44 private array $providersForNamespace = [];
61 private ObjectFactory $objectFactory,
62 private array $coreSpecs,
63 private array $extensionSpecs
71 if ( $this->cachedTitle && $title->isSamePageAs( $this->cachedTitle ) ) {
72 return $this->cachedShadow;
74 $this->cachedTitle = $title;
75 $this->cachedShadow = $this->maybeCreateShadowPage( $title );
76 return $this->cachedShadow;
84 foreach ( $this->getProvidersForNamespace( $link->getNamespace() ) as $provider ) {
85 if ( $provider->existsForLink( $link ) ) {
96 if ( $this->messageProvider === null ) {
97 foreach ( $this->getProvidersForNamespace(
NS_MEDIAWIKI ) as $provider ) {
99 $this->messageProvider = $provider;
104 return $this->messageProvider;
115 foreach ( $this->extensionSpecs as $index => $spec ) {
116 if ( !isset( $spec[
'class'] ) ) {
117 $provider = $this->getProvider( self::EXTENSION, $index, $spec );
118 if ( $provider instanceof $className ) {
121 } elseif ( $spec[
'class'] === $className ) {
122 return $this->getProvider( self::EXTENSION, $index, $spec );
125 throw new OutOfBoundsException(
'No such provider class' );
131 private function maybeCreateShadowPage( PageReference $title ): ?ShadowPage {
132 foreach ( $this->getProvidersForNamespace( $title->getNamespace() ) as $provider ) {
133 $shadowPage = $provider->get( $title );
145 private function getProvidersForNamespace(
int $namespace ): array {
146 if ( !isset( $this->providersForNamespace[$namespace] ) ) {
148 foreach ( $this->coreSpecs as $index => $spec ) {
149 if ( !isset( $spec[
'namespace'] ) || $spec[
'namespace'] === $namespace ) {
150 $providers[] = $this->getProvider( self::CORE, $index, $spec );
153 foreach ( $this->extensionSpecs as $index => $spec ) {
154 if ( !isset( $spec[
'namespace'] ) || $spec[
'namespace'] === $namespace ) {
155 $providers[] = $this->getProvider( self::EXTENSION, $index, $spec );
158 $this->providersForNamespace[$namespace] = $providers;
160 return $this->providersForNamespace[$namespace];
171 private function getProvider(
int $origin,
int $index, array $spec ): ShadowPageProvider {
172 if ( !isset( $this->providers[$origin][$index] ) ) {
173 $objSpec = array_intersect_key( $spec,
174 array_fill_keys( self::OBJECT_FACTORY_KEYS,
true ) );
175 $provider = $this->objectFactory->createObject( $objSpec );
176 if ( $provider instanceof BaseShadowPageProvider ) {
177 $provider->initBaseDeps(
new ParseHelper() );
179 $this->providers[$origin][$index] = $provider;
181 return $this->providers[$origin][$index];