MediaWiki REL1_27
ContentHandlerTest.php
Go to the documentation of this file.
1<?php
2
7
8 protected function setUp() {
10 parent::setUp();
11
12 $this->setMwGlobals( [
13 'wgExtraNamespaces' => [
14 12312 => 'Dummy',
15 12313 => 'Dummy_talk',
16 ],
17 // The below tests assume that namespaces not mentioned here (Help, User, MediaWiki, ..)
18 // default to CONTENT_MODEL_WIKITEXT.
19 'wgNamespaceContentModels' => [
20 12312 => 'testing',
21 ],
22 'wgContentHandlers' => [
23 CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler',
24 CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler',
25 CONTENT_MODEL_JSON => 'JsonContentHandler',
26 CONTENT_MODEL_CSS => 'CssContentHandler',
27 CONTENT_MODEL_TEXT => 'TextContentHandler',
28 'testing' => 'DummyContentHandlerForTesting',
29 'testing-callbacks' => function( $modelId ) {
30 return new DummyContentHandlerForTesting( $modelId );
31 }
32 ],
33 ] );
34
35 // Reset namespace cache
37 $wgContLang->resetNamespaces();
38 // And LinkCache
40 }
41
42 protected function tearDown() {
44
45 // Reset namespace cache
47 $wgContLang->resetNamespaces();
48 // And LinkCache
50
51 parent::tearDown();
52 }
53
54 public static function dataGetDefaultModelFor() {
55 return [
56 [ 'Help:Foo', CONTENT_MODEL_WIKITEXT ],
57 [ 'Help:Foo.js', CONTENT_MODEL_WIKITEXT ],
58 [ 'Help:Foo.css', CONTENT_MODEL_WIKITEXT ],
59 [ 'Help:Foo.json', CONTENT_MODEL_WIKITEXT ],
60 [ 'Help:Foo/bar.js', CONTENT_MODEL_WIKITEXT ],
61 [ 'User:Foo', CONTENT_MODEL_WIKITEXT ],
62 [ 'User:Foo.js', CONTENT_MODEL_WIKITEXT ],
63 [ 'User:Foo.css', CONTENT_MODEL_WIKITEXT ],
64 [ 'User:Foo.json', CONTENT_MODEL_WIKITEXT ],
65 [ 'User:Foo/bar.js', CONTENT_MODEL_JAVASCRIPT ],
66 [ 'User:Foo/bar.css', CONTENT_MODEL_CSS ],
67 [ 'User:Foo/bar.json', CONTENT_MODEL_JSON ],
68 [ 'User:Foo/bar.json.nope', CONTENT_MODEL_WIKITEXT ],
69 [ 'User talk:Foo/bar.css', CONTENT_MODEL_WIKITEXT ],
70 [ 'User:Foo/bar.js.xxx', CONTENT_MODEL_WIKITEXT ],
71 [ 'User:Foo/bar.xxx', CONTENT_MODEL_WIKITEXT ],
72 [ 'MediaWiki:Foo.js', CONTENT_MODEL_JAVASCRIPT ],
73 [ 'MediaWiki:Foo.JS', CONTENT_MODEL_WIKITEXT ],
74 [ 'MediaWiki:Foo.css', CONTENT_MODEL_CSS ],
75 [ 'MediaWiki:Foo.css.xxx', CONTENT_MODEL_WIKITEXT ],
76 [ 'MediaWiki:Foo.CSS', CONTENT_MODEL_WIKITEXT ],
77 [ 'MediaWiki:Foo.json', CONTENT_MODEL_JSON ],
78 [ 'MediaWiki:Foo.JSON', CONTENT_MODEL_WIKITEXT ],
79 ];
80 }
81
86 public function testGetDefaultModelFor( $title, $expectedModelId ) {
88 $this->assertEquals( $expectedModelId, ContentHandler::getDefaultModelFor( $title ) );
89 }
90
95 public function testGetForTitle( $title, $expectedContentModel ) {
97 LinkCache::singleton()->addBadLinkObj( $title );
99 $this->assertEquals( $expectedContentModel, $handler->getModelID() );
100 }
101
102 public static function dataGetLocalizedName() {
103 return [
104 [ null, null ],
105 [ "xyzzy", null ],
106
107 // XXX: depends on content language
108 [ CONTENT_MODEL_JAVASCRIPT, '/javascript/i' ],
109 ];
110 }
111
116 public function testGetLocalizedName( $id, $expected ) {
118
119 if ( $expected ) {
120 $this->assertNotNull( $name, "no name found for content model $id" );
121 $this->assertTrue( preg_match( $expected, $name ) > 0,
122 "content model name for #$id did not match pattern $expected"
123 );
124 } else {
125 $this->assertEquals( $id, $name, "localization of unknown model $id should have "
126 . "fallen back to use the model id directly."
127 );
128 }
129 }
130
131 public static function dataGetPageLanguage() {
133
134 return [
135 [ "Main", $wgLanguageCode ],
136 [ "Dummy:Foo", $wgLanguageCode ],
137 [ "MediaWiki:common.js", 'en' ],
138 [ "User:Foo/common.js", 'en' ],
139 [ "MediaWiki:common.css", 'en' ],
140 [ "User:Foo/common.css", 'en' ],
141 [ "User:Foo", $wgLanguageCode ],
142
143 [ CONTENT_MODEL_JAVASCRIPT, 'javascript' ],
144 ];
145 }
146
151 public function testGetPageLanguage( $title, $expected ) {
152 if ( is_string( $title ) ) {
154 LinkCache::singleton()->addBadLinkObj( $title );
155 }
156
157 $expected = wfGetLangObj( $expected );
158
160 $lang = $handler->getPageLanguage( $title );
161
162 $this->assertEquals( $expected->getCode(), $lang->getCode() );
163 }
164
165 public static function dataGetContentText_Null() {
166 return [
167 [ 'fail' ],
168 [ 'serialize' ],
169 [ 'ignore' ],
170 ];
171 }
172
177 public function testGetContentText_Null( $contentHandlerTextFallback ) {
178 $this->setMwGlobals( 'wgContentHandlerTextFallback', $contentHandlerTextFallback );
179
180 $content = null;
181
183 $this->assertEquals( '', $text );
184 }
185
186 public static function dataGetContentText_TextContent() {
187 return [
188 [ 'fail' ],
189 [ 'serialize' ],
190 [ 'ignore' ],
191 ];
192 }
193
198 public function testGetContentText_TextContent( $contentHandlerTextFallback ) {
199 $this->setMwGlobals( 'wgContentHandlerTextFallback', $contentHandlerTextFallback );
200
201 $content = new WikitextContent( "hello world" );
202
204 $this->assertEquals( $content->getNativeData(), $text );
205 }
206
213 $this->setMwGlobals( 'wgContentHandlerTextFallback', 'fail' );
214
215 $content = new DummyContentForTesting( "hello world" );
216
218 }
219
224 $this->setMwGlobals( 'wgContentHandlerTextFallback', 'serialize' );
225
226 $content = new DummyContentForTesting( "hello world" );
227
229 $this->assertEquals( $content->serialize(), $text );
230 }
231
236 $this->setMwGlobals( 'wgContentHandlerTextFallback', 'ignore' );
237
238 $content = new DummyContentForTesting( "hello world" );
239
241 $this->assertNull( $text );
242 }
243
244 /*
245 public static function makeContent( $text, Title $title, $modelId = null, $format = null ) {}
246 */
247
248 public static function dataMakeContent() {
249 return [
250 [ 'hallo', 'Help:Test', null, null, CONTENT_MODEL_WIKITEXT, 'hallo', false ],
251 [ 'hallo', 'MediaWiki:Test.js', null, null, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ],
252 [ serialize( 'hallo' ), 'Dummy:Test', null, null, "testing", 'hallo', false ],
253
254 [
255 'hallo',
256 'Help:Test',
257 null,
260 'hallo',
261 false
262 ],
263 [
264 'hallo',
265 'MediaWiki:Test.js',
266 null,
269 'hallo',
270 false
271 ],
272 [ serialize( 'hallo' ), 'Dummy:Test', null, "testing", "testing", 'hallo', false ],
273
274 [ 'hallo', 'Help:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ],
275 [
276 'hallo',
277 'MediaWiki:Test.js',
279 null,
281 'hallo',
282 false
283 ],
284 [
285 serialize( 'hallo' ),
286 'Dummy:Test',
288 null,
290 serialize( 'hallo' ),
291 false
292 ],
293
294 [ 'hallo', 'Help:Test', CONTENT_MODEL_WIKITEXT, "testing", null, null, true ],
295 [ 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, "testing", null, null, true ],
296 [ 'hallo', 'Dummy:Test', CONTENT_MODEL_JAVASCRIPT, "testing", null, null, true ],
297 ];
298 }
299
304 public function testMakeContent( $data, $title, $modelId, $format,
305 $expectedModelId, $expectedNativeData, $shouldFail
306 ) {
308 LinkCache::singleton()->addBadLinkObj( $title );
309 try {
310 $content = ContentHandler::makeContent( $data, $title, $modelId, $format );
311
312 if ( $shouldFail ) {
313 $this->fail( "ContentHandler::makeContent should have failed!" );
314 }
315
316 $this->assertEquals( $expectedModelId, $content->getModel(), 'bad model id' );
317 $this->assertEquals( $expectedNativeData, $content->getNativeData(), 'bads native data' );
318 } catch ( MWException $ex ) {
319 if ( !$shouldFail ) {
320 $this->fail( "ContentHandler::makeContent failed unexpectedly: " . $ex->getMessage() );
321 } else {
322 // dummy, so we don't get the "test did not perform any assertions" message.
323 $this->assertTrue( true );
324 }
325 }
326 }
327
328 /*
329 * Test if we become a "Created blank page" summary from getAutoSummary if no Content added to
330 * page.
331 */
332 public function testGetAutosummary() {
333 $this->setMwGlobals( 'wgContLang', Language::factory( 'en' ) );
334
336 $title = Title::newFromText( 'Help:Test' );
337 // Create a new content object with no content
338 $newContent = ContentHandler::makeContent( '', $title, null, null, CONTENT_MODEL_WIKITEXT );
339 // first check, if we become a blank page created summary with the right bitmask
340 $autoSummary = $content->getAutosummary( null, $newContent, 97 );
341 $this->assertEquals( $autoSummary, 'Created blank page' );
342 // now check, what we become with another bitmask
343 $autoSummary = $content->getAutosummary( null, $newContent, 92 );
344 $this->assertEquals( $autoSummary, '' );
345 }
346
347 /*
348 public function testSupportsSections() {
349 $this->markTestIncomplete( "not yet implemented" );
350 }
351 */
352
353 public function testSupportsCategories() {
355 $this->assertTrue( $handler->supportsCategories(), 'content model supports categories' );
356 }
357
358 public function testSupportsDirectEditing() {
360 $this->assertFalse( $handler->supportsDirectEditing(), 'direct editing is not supported' );
361 }
362
366 public function testRunLegacyHooks() {
367 Hooks::register( 'testRunLegacyHooks', __CLASS__ . '::dummyHookHandler' );
368
369 $content = new WikitextContent( 'test text' );
371 'testRunLegacyHooks',
372 [ 'foo', &$content, 'bar' ],
373 false
374 );
375
376 $this->assertTrue( $ok, "runLegacyHooks should have returned true" );
377 $this->assertEquals( "TEST TEXT", $content->getNativeData() );
378 }
379
380 public static function dummyHookHandler( $foo, &$text, $bar ) {
381 if ( $text === null || $text === false ) {
382 return false;
383 }
384
385 $text = strtoupper( $text );
386
387 return true;
388 }
389
390 public function provideGetModelForID() {
391 return [
392 [ CONTENT_MODEL_WIKITEXT, 'WikitextContentHandler' ],
393 [ CONTENT_MODEL_JAVASCRIPT, 'JavaScriptContentHandler' ],
394 [ CONTENT_MODEL_JSON, 'JsonContentHandler' ],
395 [ CONTENT_MODEL_CSS, 'CssContentHandler' ],
396 [ CONTENT_MODEL_TEXT, 'TextContentHandler' ],
397 [ 'testing', 'DummyContentHandlerForTesting' ],
398 [ 'testing-callbacks', 'DummyContentHandlerForTesting' ],
399 ];
400 }
401
405 public function testGetModelForID( $modelId, $handlerClass ) {
407
408 $this->assertInstanceOf( $handlerClass, $handler );
409 }
410
411}
serialize()
$wgLanguageCode
Site language code.
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
testGetPageLanguage( $title, $expected)
dataGetPageLanguage ContentHandler::getPageLanguage
testGetContentText_Null( $contentHandlerTextFallback)
dataGetContentText_Null ContentHandler::getContentText
testGetContentText_TextContent( $contentHandlerTextFallback)
dataGetContentText_TextContent ContentHandler::getContentText
testGetContentText_NonTextContent_ignore()
ContentHandler::getContentText.
testGetModelForID( $modelId, $handlerClass)
provideGetModelForID
testRunLegacyHooks()
ContentHandler::runLegacyHooks.
testMakeContent( $data, $title, $modelId, $format, $expectedModelId, $expectedNativeData, $shouldFail)
dataMakeContent ContentHandler::makeContent
testGetDefaultModelFor( $title, $expectedModelId)
dataGetDefaultModelFor ContentHandler::getDefaultModelFor
testGetContentText_NonTextContent_fail()
ContentHandler::getContentText should have thrown an exception for non-text Content object MWExceptio...
static dummyHookHandler( $foo, &$text, $bar)
static dataGetContentText_TextContent()
testGetForTitle( $title, $expectedContentModel)
dataGetDefaultModelFor ContentHandler::getForTitle
testGetLocalizedName( $id, $expected)
dataGetLocalizedName ContentHandler::getLocalizedName
testGetContentText_NonTextContent_serialize()
ContentHandler::getContentText.
static makeContent( $text, Title $title=null, $modelId=null, $format=null)
Convenience function for creating a Content object from a given textual representation.
static getForModelID( $modelId)
Returns the ContentHandler singleton for the given model ID.
static getForTitle(Title $title)
Returns the appropriate ContentHandler singleton for the given title.
static runLegacyHooks( $event, $args=[], $warn=null)
Call a legacy hook that uses text instead of Content objects.
static getDefaultModelFor(Title $title)
Returns the name of the default content model to be used for the page with the given title.
static getLocalizedName( $name, Language $lang=null)
Returns the localized name for a given content model.
static getContentText(Content $content=null)
Convenience function for getting flat text from a Content object.
static destroySingleton()
Destroy the singleton instance.
Definition LinkCache.php:76
static singleton()
Get an instance of this class.
Definition LinkCache.php:61
MediaWiki exception.
static getCanonicalNamespaces( $rebuild=false)
Returns array of all defined namespaces with their canonical (English) names.
setMwGlobals( $pairs, $value=null)
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition Title.php:277
Content object for wiki text pages.
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang
Definition design.txt:57
when a variable name is used in a it is silently declared as a new local masking the global
Definition design.txt:95
const CONTENT_FORMAT_JAVASCRIPT
Definition Defines.php:295
const CONTENT_MODEL_CSS
Definition Defines.php:280
const CONTENT_MODEL_WIKITEXT
Definition Defines.php:278
const CONTENT_MODEL_JSON
Definition Defines.php:282
const CONTENT_FORMAT_WIKITEXT
Definition Defines.php:293
const CONTENT_MODEL_TEXT
Definition Defines.php:281
const CONTENT_MODEL_JAVASCRIPT
Definition Defines.php:279
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content $content
Definition hooks.txt:1040
namespace and then decline to actually register it file or subcat img or subcat $title
Definition hooks.txt:944
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
Definition hooks.txt:1811
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:314
processing should stop and the error should be shown to the user * false
Definition hooks.txt:189
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable modifiable after all normalizations have been except for the $wgMaxImageArea check set to true or false to override the $wgMaxImageArea check result gives extension the possibility to transform it themselves $handler
Definition hooks.txt:885
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition injection.txt:37
if(!isset( $args[0])) $lang