MediaWiki master
ShadowPageLoader.php
Go to the documentation of this file.
1<?php
2
4
6use OutOfBoundsException;
7use Wikimedia\ObjectFactory\ObjectFactory;
8use Wikimedia\Parsoid\Core\LinkTarget;
9
20 public const CORE_SPECS = [
21 [
22 'namespace' => NS_MEDIAWIKI,
23 'class' => MessageProvider::class,
24 'services' => [
25 'MessageCache',
26 'ContentLanguage',
27 'SlotRoleRegistry',
28 'ContentHandlerFactory',
29 ]
30 ]
31 ];
32
33 private const OBJECT_FACTORY_KEYS = [
34 'class', 'factory', 'args', 'services', 'optional_services'
35 ];
36
37 private const CORE = 0;
38 private const EXTENSION = 1;
39
41 private array $providers = [];
42
44 private array $providersForNamespace = [];
45
46 private ?PageReference $cachedTitle = null;
47 private ?ShadowPage $cachedShadow = null;
48 private ?MessageProvider $messageProvider = null;
49
60 public function __construct(
61 private ObjectFactory $objectFactory,
62 private array $coreSpecs,
63 private array $extensionSpecs
64 ) {
65 }
66
70 public function get( PageReference $title ): ?ShadowPage {
71 if ( $this->cachedTitle && $title->isSamePageAs( $this->cachedTitle ) ) {
72 return $this->cachedShadow;
73 }
74 $this->cachedTitle = $title;
75 $this->cachedShadow = $this->maybeCreateShadowPage( $title );
76 return $this->cachedShadow;
77 }
78
83 public function existsForLink( LinkTarget $link ): bool {
84 foreach ( $this->getProvidersForNamespace( $link->getNamespace() ) as $provider ) {
85 if ( $provider->existsForLink( $link ) ) {
86 return true;
87 }
88 }
89 return false;
90 }
91
96 if ( $this->messageProvider === null ) {
97 foreach ( $this->getProvidersForNamespace( NS_MEDIAWIKI ) as $provider ) {
98 if ( $provider instanceof MessageProvider ) {
99 $this->messageProvider = $provider;
100 break;
101 }
102 }
103 }
104 return $this->messageProvider;
105 }
106
114 public function getExtensionProvider( string $className ): ShadowPageProvider {
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 ) {
119 return $provider;
120 }
121 } elseif ( $spec['class'] === $className ) {
122 return $this->getProvider( self::EXTENSION, $index, $spec );
123 }
124 }
125 throw new OutOfBoundsException( 'No such provider class' );
126 }
127
131 private function maybeCreateShadowPage( PageReference $title ): ?ShadowPage {
132 foreach ( $this->getProvidersForNamespace( $title->getNamespace() ) as $provider ) {
133 $shadowPage = $provider->get( $title );
134 if ( $shadowPage ) {
135 return $shadowPage;
136 }
137 }
138 return null;
139 }
140
145 private function getProvidersForNamespace( int $namespace ): array {
146 if ( !isset( $this->providersForNamespace[$namespace] ) ) {
147 $providers = [];
148 foreach ( $this->coreSpecs as $index => $spec ) {
149 if ( !isset( $spec['namespace'] ) || $spec['namespace'] === $namespace ) {
150 $providers[] = $this->getProvider( self::CORE, $index, $spec );
151 }
152 }
153 foreach ( $this->extensionSpecs as $index => $spec ) {
154 if ( !isset( $spec['namespace'] ) || $spec['namespace'] === $namespace ) {
155 $providers[] = $this->getProvider( self::EXTENSION, $index, $spec );
156 }
157 }
158 $this->providersForNamespace[$namespace] = $providers;
159 }
160 return $this->providersForNamespace[$namespace];
161 }
162
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() );
178 }
179 $this->providers[$origin][$index] = $provider;
180 }
181 return $this->providers[$origin][$index];
182 }
183}
const NS_MEDIAWIKI
Definition Defines.php:59
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:71
The provider for NS_MEDIAWIKI.
A service which loads shadow content, which is content that is displayed on a nonexistent page with a...
__construct(private ObjectFactory $objectFactory, private array $coreSpecs, private array $extensionSpecs)
getMessageProvider()
Get the MessageProvider instance.
existsForLink(LinkTarget $link)
Check if a link should be shown as existing, due to the existence of shadow content at that location.
getExtensionProvider(string $className)
Get an extension provider with a given class name, or throw if no such provider exists.
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
The interface for providers of ShadowPage instances.
The interface for shadow pages.