MediaWiki  master
ContentHandlerFactory.php
Go to the documentation of this file.
1 <?php
2 
26 
27 use ContentHandler;
28 use FatalError;
29 use Hooks;
30 use InvalidArgumentException;
31 use MWException;
33 use UnexpectedValueException;
34 use Wikimedia\ObjectFactory;
35 
43 
47  private $handlerSpecs = [];
48 
52  private $handlersByModel = [];
53 
57  private $objectFactory;
58 
68  public function __construct( array $handlerSpecs, ObjectFactory $objectFactory ) {
69  $this->handlerSpecs = $handlerSpecs;
70  $this->objectFactory = $objectFactory;
71  }
72 
80  public function getContentHandler( string $modelID ): ContentHandler {
81  if ( empty( $this->handlersByModel[$modelID] ) ) {
82  $contentHandler = $this->createForModelID( $modelID );
83 
84  wfDebugLog( 'ContentHandler',
85  "Registered handler for {$modelID}: " . get_class( $contentHandler ) );
86  $this->handlersByModel[$modelID] = $contentHandler;
87  }
88 
89  return $this->handlersByModel[$modelID];
90  }
91 
101  public function defineContentHandler( string $modelID, $handlerSpec ): void {
102  if ( !is_callable( $handlerSpec ) && !is_string( $handlerSpec ) ) {
103  throw new MWException(
104  "ContentHandler Spec for modelID '{$modelID}' must be callable or class name"
105  );
106  }
107  unset( $this->handlersByModel[$modelID] );
108  $this->handlerSpecs[$modelID] = $handlerSpec;
109  }
110 
118  public function getContentModels(): array {
119  $modelsFromHook = [];
120  Hooks::run( 'GetContentModels', [ &$modelsFromHook ] );
121  $models = array_merge( // auto-registered from config and MediaServiceWiki or manual
122  array_keys( $this->handlerSpecs ),
123 
124  // incorrect registered and called: without HOOK_NAME_GET_CONTENT_MODELS
125  array_keys( $this->handlersByModel ),
126 
127  // correct registered: as HOOK_NAME_GET_CONTENT_MODELS
128  $modelsFromHook );
129 
130  return array_unique( $models );
131  }
132 
137  public function getAllContentFormats(): array {
138  $formats = [];
139  foreach ( $this->handlerSpecs as $model => $class ) {
140  $formats += array_flip( $this->getContentHandler( $model )->getSupportedFormats() );
141  }
142 
143  return array_keys( $formats );
144  }
145 
152  public function isDefinedModel( string $modelID ): bool {
153  return in_array( $modelID, $this->getContentModels(), true );
154  }
155 
167  private function createForModelID( string $modelID ): ContentHandler {
168  $handlerSpec = $this->handlerSpecs[$modelID] ?? null;
169  if ( $handlerSpec !== null ) {
170  return $this->createContentHandlerFromHandlerSpec( $modelID, $handlerSpec );
171  }
172 
173  return $this->createContentHandlerFromHook( $modelID );
174  }
175 
183  private function validateContentHandler( string $modelID, $contentHandler ): void {
184  if ( $contentHandler === null ) {
185  throw new MWUnknownContentModelException( $modelID );
186  }
187 
188  if ( !is_object( $contentHandler ) ) {
189  throw new MWException(
190  "ContentHandler for model {$modelID} wrong: non-object given."
191  );
192  }
193 
194  if ( !$contentHandler instanceof ContentHandler ) {
195  throw new MWException(
196  "ContentHandler for model {$modelID} must supply a ContentHandler instance, "
197  . get_class( $contentHandler ) . 'given.'
198  );
199  }
200  }
201 
211  string $modelID, $handlerSpec
212  ): ContentHandler {
213  try {
217  $contentHandler = $this->objectFactory->createObject( $handlerSpec,
218  [
219  'assertClass' => ContentHandler::class,
220  'allowCallable' => true,
221  'allowClassName' => true,
222  'extraArgs' => [ $modelID ],
223  ] );
224  }
225  catch ( InvalidArgumentException $e ) {
226  // legacy support
227  throw new MWException( "Wrong Argument HandlerSpec for ModelID: {$modelID}. " .
228  "Error: {$e->getMessage()}" );
229  }
230  catch ( UnexpectedValueException $e ) {
231  // legacy support
232  throw new MWException( "Wrong HandlerSpec class for ModelID: {$modelID}. " .
233  "Error: {$e->getMessage()}" );
234  }
235  $this->validateContentHandler( $modelID, $contentHandler );
236 
237  return $contentHandler;
238  }
239 
247  private function createContentHandlerFromHook( string $modelID ): ContentHandler {
248  $contentHandler = null;
249  Hooks::run( 'ContentHandlerForModelID', [ $modelID, &$contentHandler ] );
250  $this->validateContentHandler( $modelID, $contentHandler );
251 
252  '@phan-var ContentHandler $contentHandler';
253 
254  return $contentHandler;
255  }
256 }
ContentHandler
A content handler knows how do deal with a specific type of content on a wiki page.
Definition: ContentHandler.php:56
MediaWiki\Content\ContentHandlerFactory\createContentHandlerFromHook
createContentHandlerFromHook(string $modelID)
Definition: ContentHandlerFactory.php:247
MediaWiki\Content
Definition: ContentHandlerFactory.php:25
wfDebugLog
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
Definition: GlobalFunctions.php:992
MWException
MediaWiki exception.
Definition: MWException.php:26
MediaWiki\Content\ContentHandlerFactory
Definition: ContentHandlerFactory.php:42
MediaWiki\Content\ContentHandlerFactory\getContentHandler
getContentHandler(string $modelID)
Definition: ContentHandlerFactory.php:80
MediaWiki\Content\ContentHandlerFactory\createForModelID
createForModelID(string $modelID)
Create ContentHandler for ModelID.
Definition: ContentHandlerFactory.php:167
MediaWiki\Content\IContentHandlerFactory
Definition: IContentHandlerFactory.php:10
MediaWiki\Content\ContentHandlerFactory\$handlersByModel
ContentHandler[] $handlersByModel
Registry of ContentHandler instances by model id.
Definition: ContentHandlerFactory.php:52
MediaWiki\Content\ContentHandlerFactory\validateContentHandler
validateContentHandler(string $modelID, $contentHandler)
Definition: ContentHandlerFactory.php:183
MediaWiki\Content\ContentHandlerFactory\$handlerSpecs
string[] callable[] $handlerSpecs
Definition: ContentHandlerFactory.php:47
MediaWiki\Content\ContentHandlerFactory\getContentModels
getContentModels()
Get defined ModelIDs.
Definition: ContentHandlerFactory.php:118
MediaWiki\Content\ContentHandlerFactory\defineContentHandler
defineContentHandler(string $modelID, $handlerSpec)
Define HandlerSpec for ModelID.
Definition: ContentHandlerFactory.php:101
FatalError
Abort the web request with a custom HTML string that will represent the entire response.
Definition: FatalError.php:35
MediaWiki\Content\ContentHandlerFactory\createContentHandlerFromHandlerSpec
createContentHandlerFromHandlerSpec(string $modelID, $handlerSpec)
Definition: ContentHandlerFactory.php:210
MediaWiki\Content\ContentHandlerFactory\getAllContentFormats
getAllContentFormats()
Definition: ContentHandlerFactory.php:137
MWUnknownContentModelException
Exception thrown when an unregistered content model is requested.
Definition: MWUnknownContentModelException.php:10
MediaWiki\Content\ContentHandlerFactory\$objectFactory
ObjectFactory $objectFactory
Definition: ContentHandlerFactory.php:57
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:133
MediaWiki\Content\ContentHandlerFactory\isDefinedModel
isDefinedModel(string $modelID)
Definition: ContentHandlerFactory.php:152
MediaWiki\Content\ContentHandlerFactory\__construct
__construct(array $handlerSpecs, ObjectFactory $objectFactory)
Definition: ContentHandlerFactory.php:68
Hooks
Hooks class.
Definition: Hooks.php:38