1<?php 2 3namespace MediaWiki\Tests\Unit\Permissions; 4 5use MediaWiki\Block\Block; 6use MediaWiki\Permissions\Authority; 7use MediaWiki\Permissions\SimpleAuthority; 8use MediaWiki\Permissions\UltimateAuthority; 9use MediaWiki\User\UserIdentity; 10use MediaWiki\User\UserIdentityValue; 11 12/** 13 * Various useful Authority mocks. 14 * @stable to use (since 1.37) 15 */ 16trait MockAuthorityTrait { 17 18 /** 19 * Create mock ultimate Authority for anon user. 20 * 21 * @return Authority 22 */ 23 private function mockAnonUltimateAuthority(): Authority { 24 return new UltimateAuthority( new UserIdentityValue( 0, '127.0.0.1' ) ); 25 } 26 27 /** 28 * Create mock ultimate Authority for registered user. 29 * 30 * @return Authority 31 */ 32 private function mockRegisteredUltimateAuthority(): Authority { 33 return new UltimateAuthority( new UserIdentityValue( 9999, 'Petr' ) ); 34 } 35 36 /** 37 * Create mock Authority for anon user with no permissions. 38 * 39 * @return Authority 40 */ 41 private function mockAnonNullAuthority(): Authority { 42 return new SimpleAuthority( new UserIdentityValue( 0, '127.0.0.1' ), [] ); 43 } 44 45 /** 46 * Create mock Authority for a registered user with no permissions. 47 * 48 * @return Authority 49 */ 50 private function mockRegisteredNullAuthority(): Authority { 51 return new SimpleAuthority( new UserIdentityValue( 9999, 'Petr' ), [] ); 52 } 53 54 /** 55 * Create a mock Authority for anon user with $permissions. 56 * 57 * @param array $permissions 58 * @return Authority 59 */ 60 private function mockAnonAuthorityWithPermissions( array $permissions ): Authority { 61 return new SimpleAuthority( new UserIdentityValue( 0, '127.0.0.1' ), $permissions ); 62 } 63 64 /** 65 * Create a mock Authority for a registered user with $permissions. 66 * 67 * @param array $permissions 68 * @return Authority 69 */ 70 private function mockRegisteredAuthorityWithPermissions( array $permissions ): Authority { 71 return new SimpleAuthority( new UserIdentityValue( 9999, 'Petr' ), $permissions ); 72 } 73 74 /** 75 * Create a mock Authority for a $user with $permissions. 76 * 77 * @param UserIdentity $user 78 * @param array $permissions 79 * @return Authority 80 */ 81 private function mockUserAuthorityWithPermissions( 82 UserIdentity $user, 83 array $permissions 84 ): Authority { 85 return new SimpleAuthority( $user, $permissions ); 86 } 87 88 /** 89 * Create a mock Authority for $user with $block and $permissions. 90 * 91 * @param UserIdentity $user 92 * @param Block $block 93 * @param array $permissions 94 * 95 * @return Authority 96 */ 97 private function mockUserAuthorityWithBlock( 98 UserIdentity $user, 99 Block $block, 100 array $permissions = [] 101 ): Authority { 102 return $this->mockAuthority( 103 $user, 104 static function ( $permission ) use ( $permissions ) { 105 return in_array( $permission, $permissions ); 106 }, 107 $block 108 ); 109 } 110 111 /** 112 * Create a mock Authority for an anon user with all but $permissions 113 * @param array $permissions 114 * @return Authority 115 */ 116 private function mockAnonAuthorityWithoutPermissions( array $permissions ): Authority { 117 return $this->mockUserAuthorityWithoutPermissions( 118 new UserIdentityValue( 0, '127.0.0.1' ), 119 $permissions 120 ); 121 } 122 123 /** 124 * Create a mock Authority for a registered user with all but $permissions 125 * @param array $permissions 126 * @return Authority 127 */ 128 private function mockRegisteredAuthorityWithoutPermissions( array $permissions ): Authority { 129 return $this->mockUserAuthorityWithoutPermissions( 130 new UserIdentityValue( 9999, 'Petr' ), 131 $permissions 132 ); 133 } 134 135 /** 136 * Create a mock Authority for a $user with all but $permissions 137 * @param UserIdentity $user 138 * @param array $permissions 139 * @return Authority 140 */ 141 private function mockUserAuthorityWithoutPermissions( 142 UserIdentity $user, 143 array $permissions 144 ): Authority { 145 return $this->mockAuthority( 146 $user, 147 static function ( $permission ) use ( $permissions ) { 148 return !in_array( $permission, $permissions ); 149 } 150 ); 151 } 152 153 /** 154 * Create mock Authority for anon user where permissions are determined by $callback. 155 * 156 * @param callable $permissionCallback 157 * @return Authority 158 */ 159 private function mockAnonAuthority( callable $permissionCallback ): Authority { 160 return $this->mockAuthority( 161 new UserIdentityValue( 0, '127.0.0.1' ), 162 $permissionCallback 163 ); 164 } 165 166 /** 167 * Create mock Authority for registered user where permissions are determined by $callback. 168 * 169 * @param callable $permissionCallback 170 * @return Authority 171 */ 172 private function mockRegisteredAuthority( callable $permissionCallback ): Authority { 173 return $this->mockAuthority( 174 new UserIdentityValue( 9999, 'Petr' ), 175 $permissionCallback 176 ); 177 } 178 179 /** 180 * Create mock Authority for $user where permissions are determined by $callback. 181 * 182 * @param UserIdentity $user 183 * @param callable $permissionCallback ( string $permission, ?PageIdentity $page ) 184 * @param Block|null $block 185 * 186 * @return Authority 187 */ 188 private function mockAuthority( 189 UserIdentity $user, 190 callable $permissionCallback, 191 Block $block = null 192 ): Authority { 193 $mock = $this->createMock( Authority::class ); 194 $mock->method( 'getUser' )->willReturn( $user ); 195 $methods = [ 'isAllowed', 'probablyCan', 'definitelyCan', 'authorizeRead', 'authorizeWrite' ]; 196 foreach ( $methods as $method ) { 197 $mock->method( $method )->willReturnCallback( $permissionCallback ); 198 } 199 $mock->method( 'isAllowedAny' ) 200 ->willReturnCallback( static function ( ...$permissions ) use ( $permissionCallback ) { 201 foreach ( $permissions as $permission ) { 202 if ( $permissionCallback( $permission ) ) { 203 return true; 204 } 205 } 206 return false; 207 } ); 208 $mock->method( 'isAllowedAll' ) 209 ->willReturnCallback( static function ( ...$permissions ) use ( $permissionCallback ) { 210 foreach ( $permissions as $permission ) { 211 if ( !$permissionCallback( $permission ) ) { 212 return false; 213 } 214 } 215 return true; 216 } ); 217 $mock->method( 'getBlock' )->willReturn( $block ); 218 return $mock; 219 } 220} 221