summaryrefslogtreecommitdiff
path: root/tests/phpunit/includes/HooksTest.php
blob: 81dd48704ae1de5a52147837c038e4d94fcbfc93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?php

class HooksTest extends MediaWikiTestCase {

	function setUp() {
		global $wgHooks;
		parent::setUp();
		Hooks::clear( 'MediaWikiHooksTest001' );
		unset( $wgHooks['MediaWikiHooksTest001'] );
	}

	public static function provideHooks() {
		$i = new NothingClass();

		return array(
			array( 'Object and method', array( $i, 'someNonStatic' ), 'changed-nonstatic', 'changed-nonstatic' ),
			array( 'Object and no method', array( $i ), 'changed-onevent', 'original' ),
			array( 'Object and method with data', array( $i, 'someNonStaticWithData', 'data' ), 'data', 'original' ),
			array( 'Object and static method', array( $i, 'someStatic' ), 'changed-static', 'original' ),
			array( 'Class::method static call', array( 'NothingClass::someStatic' ), 'changed-static', 'original' ),
			array( 'Global function', array( 'NothingFunction' ), 'changed-func', 'original' ),
			array( 'Global function with data', array( 'NothingFunctionData', 'data' ), 'data', 'original' ),
			array( 'Closure', array( function ( &$foo, $bar ) {
				$foo = 'changed-closure';

				return true;
			} ), 'changed-closure', 'original' ),
			array( 'Closure with data', array( function ( $data, &$foo, $bar ) {
				$foo = $data;

				return true;
			}, 'data' ), 'data', 'original' )
		);
	}

	/**
	 * @dataProvider provideHooks
	 */
	public function testOldStyleHooks( $msg, array $hook, $expectedFoo, $expectedBar ) {
		global $wgHooks;
		$foo = $bar = 'original';

		$wgHooks['MediaWikiHooksTest001'][] = $hook;
		wfRunHooks( 'MediaWikiHooksTest001', array( &$foo, &$bar ) );

		$this->assertSame( $expectedFoo, $foo, $msg );
		$this->assertSame( $expectedBar, $bar, $msg );
	}

	/**
	 * @dataProvider provideHooks
	 */
	public function testNewStyleHooks( $msg, $hook, $expectedFoo, $expectedBar ) {
		$foo = $bar = 'original';

		Hooks::register( 'MediaWikiHooksTest001', $hook );
		Hooks::run( 'MediaWikiHooksTest001', array( &$foo, &$bar ) );

		$this->assertSame( $expectedFoo, $foo, $msg );
		$this->assertSame( $expectedBar, $bar, $msg );
	}

	public function testNewStyleHookInteraction() {
		global $wgHooks;

		$a = new NothingClass();
		$b = new NothingClass();

		$wgHooks['MediaWikiHooksTest001'][] = $a;
		$this->assertTrue( Hooks::isRegistered( 'MediaWikiHooksTest001' ), 'Hook registered via $wgHooks should be noticed by Hooks::isRegistered' );

		Hooks::register( 'MediaWikiHooksTest001', $b );
		$this->assertEquals( 2, count( Hooks::getHandlers( 'MediaWikiHooksTest001' ) ), 'Hooks::getHandlers() should return hooks registered via wgHooks as well as Hooks::register' );

		$foo = 'quux';
		$bar = 'qaax';

		Hooks::run( 'MediaWikiHooksTest001', array( &$foo, &$bar ) );
		$this->assertEquals( 1, $a->calls, 'Hooks::run() should run hooks registered via wgHooks as well as Hooks::register' );
		$this->assertEquals( 1, $b->calls, 'Hooks::run() should run hooks registered via wgHooks as well as Hooks::register' );
	}

	/**
	 * @expectedException MWException
	 */
	public function testUncallableFunction() {
		Hooks::register( 'MediaWikiHooksTest001', 'ThisFunctionDoesntExist' );
		Hooks::run( 'MediaWikiHooksTest001', array() );
	}

	public function testFalseReturn() {
		Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
			return false;
		} );
		Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
			$foo = 'test';

			return true;
		} );
		$foo = 'original';
		Hooks::run( 'MediaWikiHooksTest001', array( &$foo ) );
		$this->assertSame( 'original', $foo, 'Hooks continued processing after a false return.' );
	}

	/**
	 * @expectedException FatalError
	 */
	public function testFatalError() {
		Hooks::register( 'MediaWikiHooksTest001', function () {
			return 'test';
		} );
		Hooks::run( 'MediaWikiHooksTest001', array() );
	}
}

function NothingFunction( &$foo, &$bar ) {
	$foo = 'changed-func';

	return true;
}

function NothingFunctionData( $data, &$foo, &$bar ) {
	$foo = $data;

	return true;
}

class NothingClass {
	public $calls = 0;

	public static function someStatic( &$foo, &$bar ) {
		$foo = 'changed-static';

		return true;
	}

	public function someNonStatic( &$foo, &$bar ) {
		$this->calls++;
		$foo = 'changed-nonstatic';
		$bar = 'changed-nonstatic';

		return true;
	}

	public function onMediaWikiHooksTest001( &$foo, &$bar ) {
		$this->calls++;
		$foo = 'changed-onevent';

		return true;
	}

	public function someNonStaticWithData( $data, &$foo, &$bar ) {
		$this->calls++;
		$foo = $data;

		return true;
	}
}