MediaWiki REL1_33
HooksTest.php
Go to the documentation of this file.
1<?php
2
4
5 function setUp() {
6 global $wgHooks;
7 parent::setUp();
8 Hooks::clear( 'MediaWikiHooksTest001' );
9 unset( $wgHooks['MediaWikiHooksTest001'] );
10 }
11
12 public static function provideHooks() {
13 $i = new NothingClass();
14
15 return [
16 [
17 'Object and method',
18 [ $i, 'someNonStatic' ],
19 'changed-nonstatic',
20 'changed-nonstatic'
21 ],
22 [ 'Object and no method', [ $i ], 'changed-onevent', 'original' ],
23 [
24 'Object and method with data',
25 [ $i, 'someNonStaticWithData', 'data' ],
26 'data',
27 'original'
28 ],
29 [ 'Object and static method', [ $i, 'someStatic' ], 'changed-static', 'original' ],
30 [
31 'Class::method static call',
32 [ 'NothingClass::someStatic' ],
33 'changed-static',
34 'original'
35 ],
36 [
37 'Class::method static call as array',
38 [ [ 'NothingClass::someStatic' ] ],
39 'changed-static',
40 'original'
41 ],
42 [ 'Global function', [ 'NothingFunction' ], 'changed-func', 'original' ],
43 [ 'Global function with data', [ 'NothingFunctionData', 'data' ], 'data', 'original' ],
44 [ 'Closure', [ function ( &$foo, $bar ) {
45 $foo = 'changed-closure';
46
47 return true;
48 } ], 'changed-closure', 'original' ],
49 [ 'Closure with data', [ function ( $data, &$foo, $bar ) {
50 $foo = $data;
51
52 return true;
53 }, 'data' ], 'data', 'original' ]
54 ];
55 }
56
63 public function testNewStyleHooks( $msg, $hook, $expectedFoo, $expectedBar ) {
64 $foo = $bar = 'original';
65
66 Hooks::register( 'MediaWikiHooksTest001', $hook );
67 Hooks::run( 'MediaWikiHooksTest001', [ &$foo, &$bar ] );
68
69 $this->assertSame( $expectedFoo, $foo, $msg );
70 $this->assertSame( $expectedBar, $bar, $msg );
71 }
72
76 public function testGetHandlers() {
77 global $wgHooks;
78
79 $this->assertSame(
80 [],
81 Hooks::getHandlers( 'MediaWikiHooksTest001' ),
82 'No hooks registered'
83 );
84
85 $a = new NothingClass();
86 $b = new NothingClass();
87
88 $wgHooks['MediaWikiHooksTest001'][] = $a;
89
90 $this->assertSame(
91 [ $a ],
92 Hooks::getHandlers( 'MediaWikiHooksTest001' ),
93 'Hook registered by $wgHooks'
94 );
95
96 Hooks::register( 'MediaWikiHooksTest001', $b );
97 $this->assertSame(
98 [ $b, $a ],
99 Hooks::getHandlers( 'MediaWikiHooksTest001' ),
100 'Hooks::getHandlers() should return hooks registered via wgHooks as well as Hooks::register'
101 );
102
103 Hooks::clear( 'MediaWikiHooksTest001' );
104 unset( $wgHooks['MediaWikiHooksTest001'] );
105
106 Hooks::register( 'MediaWikiHooksTest001', $b );
107 $this->assertSame(
108 [ $b ],
109 Hooks::getHandlers( 'MediaWikiHooksTest001' ),
110 'Hook registered by Hook::register'
111 );
112 }
113
120 public function testNewStyleHookInteraction() {
121 global $wgHooks;
122
123 $a = new NothingClass();
124 $b = new NothingClass();
125
126 $wgHooks['MediaWikiHooksTest001'][] = $a;
127 $this->assertTrue(
128 Hooks::isRegistered( 'MediaWikiHooksTest001' ),
129 'Hook registered via $wgHooks should be noticed by Hooks::isRegistered'
130 );
131
132 Hooks::register( 'MediaWikiHooksTest001', $b );
133 $this->assertEquals(
134 2,
135 count( Hooks::getHandlers( 'MediaWikiHooksTest001' ) ),
136 'Hooks::getHandlers() should return hooks registered via wgHooks as well as Hooks::register'
137 );
138
139 $foo = 'quux';
140 $bar = 'qaax';
141
142 Hooks::run( 'MediaWikiHooksTest001', [ &$foo, &$bar ] );
143 $this->assertEquals(
144 1,
145 $a->calls,
146 'Hooks::run() should run hooks registered via wgHooks as well as Hooks::register'
147 );
148 $this->assertEquals(
149 1,
150 $b->calls,
151 'Hooks::run() should run hooks registered via wgHooks as well as Hooks::register'
152 );
153 }
154
160 public function testUncallableFunction() {
161 Hooks::register( 'MediaWikiHooksTest001', 'ThisFunctionDoesntExist' );
162 Hooks::run( 'MediaWikiHooksTest001', [] );
163 }
164
169 public function testFalseReturn() {
170 Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
171 return false;
172 } );
173 Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
174 $foo = 'test';
175
176 return true;
177 } );
178 $foo = 'original';
179 Hooks::run( 'MediaWikiHooksTest001', [ &$foo ] );
180 $this->assertSame( 'original', $foo, 'Hooks abort after a false return.' );
181 }
182
186 public function testNullReturn() {
187 Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
188 return;
189 } );
190 Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
191 $foo = 'test';
192
193 return true;
194 } );
195 $foo = 'original';
196 Hooks::run( 'MediaWikiHooksTest001', [ &$foo ] );
197 $this->assertSame( 'test', $foo, 'Hooks continue after a null return.' );
198 }
199
203 public function testCallHook_FalseHook() {
204 Hooks::register( 'MediaWikiHooksTest001', false );
205 Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
206 $foo = 'test';
207
208 return true;
209 } );
210 $foo = 'original';
211 Hooks::run( 'MediaWikiHooksTest001', [ &$foo ] );
212 $this->assertSame( 'test', $foo, 'Hooks that are falsey are skipped.' );
213 }
214
220 Hooks::register( 'MediaWikiHooksTest001', 12345 );
221 Hooks::run( 'MediaWikiHooksTest001' );
222 }
223
228 public function testCallHook_Deprecated() {
229 Hooks::register( 'MediaWikiHooksTest001', 'NothingClass::someStatic' );
230 Hooks::run( 'MediaWikiHooksTest001', [], '1.31' );
231 }
232
237 public function testRunWithoutAbort() {
238 $list = [];
239 Hooks::register( 'MediaWikiHooksTest001', function ( &$list ) {
240 $list[] = 1;
241 return true; // Explicit true
242 } );
243 Hooks::register( 'MediaWikiHooksTest001', function ( &$list ) {
244 $list[] = 2;
245 return; // Implicit null
246 } );
247 Hooks::register( 'MediaWikiHooksTest001', function ( &$list ) {
248 $list[] = 3;
249 // No return
250 } );
251
252 Hooks::runWithoutAbort( 'MediaWikiHooksTest001', [ &$list ] );
253 $this->assertSame( [ 1, 2, 3 ], $list, 'All hooks ran.' );
254 }
255
260 public function testRunWithoutAbortWarning() {
261 Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
262 return false;
263 } );
264 Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
265 $foo = 'test';
266 return true;
267 } );
268 $foo = 'original';
269
270 $this->setExpectedException(
271 UnexpectedValueException::class,
272 'Invalid return from hook-MediaWikiHooksTest001-closure for ' .
273 'unabortable MediaWikiHooksTest001'
274 );
275 Hooks::runWithoutAbort( 'MediaWikiHooksTest001', [ &$foo ] );
276 }
277
282 public function testFatalError() {
283 Hooks::register( 'MediaWikiHooksTest001', function () {
284 return 'test';
285 } );
286 Hooks::run( 'MediaWikiHooksTest001', [] );
287 }
288}
289
290function NothingFunction( &$foo, &$bar ) {
291 $foo = 'changed-func';
292
293 return true;
294}
295
296function NothingFunctionData( $data, &$foo, &$bar ) {
297 $foo = $data;
298
299 return true;
300}
301
303 public $calls = 0;
304
305 public static function someStatic( &$foo, &$bar ) {
306 $foo = 'changed-static';
307
308 return true;
309 }
310
311 public function someNonStatic( &$foo, &$bar ) {
312 $this->calls++;
313 $foo = 'changed-nonstatic';
314 $bar = 'changed-nonstatic';
315
316 return true;
317 }
318
319 public function onMediaWikiHooksTest001( &$foo, &$bar ) {
320 $this->calls++;
321 $foo = 'changed-onevent';
322
323 return true;
324 }
325
326 public function someNonStaticWithData( $data, &$foo, &$bar ) {
327 $this->calls++;
328 $foo = $data;
329
330 return true;
331 }
332}
NothingFunction(&$foo, &$bar)
NothingFunctionData( $data, &$foo, &$bar)
testFatalError()
FatalError Hooks::run.
testUncallableFunction()
MWException Hooks::run Hooks::callHook.
testCallHook_Deprecated()
Hooks::callHook PHPUnit_Framework_Error_Deprecated.
testFalseReturn()
Hooks::run Hooks::callHook.
testNewStyleHookInteraction()
Hooks::isRegistered Hooks::register Hooks::run Hooks::callHook.
testNewStyleHooks( $msg, $hook, $expectedFoo, $expectedBar)
provideHooks Hooks::register Hooks::run Hooks::callHook
Definition HooksTest.php:63
testRunWithoutAbortWarning()
Hooks::runWithoutAbort Hooks::callHook.
static provideHooks()
Definition HooksTest.php:12
testCallHook_UnknownDatatype()
Hooks::callHook MWException.
testNullReturn()
Hooks::run.
testGetHandlers()
Hooks::getHandlers.
Definition HooksTest.php:76
testRunWithoutAbort()
Hooks::runWithoutAbort Hooks::callHook.
testCallHook_FalseHook()
Hooks::callHook.
static someStatic(&$foo, &$bar)
someNonStaticWithData( $data, &$foo, &$bar)
someNonStatic(&$foo, &$bar)
onMediaWikiHooksTest001(&$foo, &$bar)
$data
Utility to generate mapping file used in mw.Title (phpCharToUpper.json)
$wgHooks['ArticleShow'][]
Definition hooks.txt:108
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