Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1428260
MockAuthorityTrait.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
MockAuthorityTrait.php
View Options
<?php
namespace
MediaWiki\Tests\Unit\Permissions
;
use
MediaWiki\Block\Block
;
use
MediaWiki\Block\BlockErrorFormatter
;
use
MediaWiki\Block\SystemBlock
;
use
MediaWiki\Context\IContextSource
;
use
MediaWiki\Language\Language
;
use
MediaWiki\Message\Message
;
use
MediaWiki\Permissions\Authority
;
use
MediaWiki\Permissions\PermissionManager
;
use
MediaWiki\Permissions\PermissionStatus
;
use
MediaWiki\Permissions\RateLimiter
;
use
MediaWiki\Permissions\RateLimitSubject
;
use
MediaWiki\Permissions\SimpleAuthority
;
use
MediaWiki\Permissions\UltimateAuthority
;
use
MediaWiki\Permissions\UserAuthority
;
use
MediaWiki\Request\FauxRequest
;
use
MediaWiki\Request\WebRequest
;
use
MediaWiki\User\User
;
use
MediaWiki\User\UserIdentity
;
use
MediaWiki\User\UserIdentityValue
;
use
PHPUnit\Framework\MockObject\MockObject
;
use
StatusValue
;
/**
* Various useful Authority mocks.
* @stable to use (since 1.37)
*/
trait
MockAuthorityTrait
{
/**
* Create mock ultimate Authority for anon user.
*
* @return Authority
*/
private
function
mockAnonUltimateAuthority
():
Authority
{
return
new
UltimateAuthority
(
new
UserIdentityValue
(
0
,
'127.0.0.1'
)
);
}
/**
* Create mock ultimate Authority for a temp user.
*
* @return Authority
*/
private
function
mockTempUltimateAuthority
():
Authority
{
return
new
UltimateAuthority
(
new
UserIdentityValue
(
42
,
'~2024-1'
),
true
);
}
/**
* Create mock ultimate Authority for registered user.
*
* @return Authority
*/
private
function
mockRegisteredUltimateAuthority
():
Authority
{
return
new
UltimateAuthority
(
new
UserIdentityValue
(
9999
,
'Petr'
)
);
}
/**
* Create mock Authority for anon user with no permissions.
*
* @return Authority
*/
private
function
mockAnonNullAuthority
():
Authority
{
return
new
SimpleAuthority
(
new
UserIdentityValue
(
0
,
'127.0.0.1'
),
[]
);
}
/**
* Create mock Authority for a temp user with no permissions.
*
* @return Authority
*/
private
function
mockTempNullAuthority
():
Authority
{
return
new
SimpleAuthority
(
new
UserIdentityValue
(
42
,
'~2024-1'
),
[],
true
);
}
/**
* Create mock Authority for a registered user with no permissions.
*
* @return Authority
*/
private
function
mockRegisteredNullAuthority
():
Authority
{
return
new
SimpleAuthority
(
new
UserIdentityValue
(
9999
,
'Petr'
),
[]
);
}
/**
* Create a mock Authority for anon user with $permissions.
*
* @param array $permissions
* @return Authority
*/
private
function
mockAnonAuthorityWithPermissions
(
array
$permissions
):
Authority
{
return
new
SimpleAuthority
(
new
UserIdentityValue
(
0
,
'127.0.0.1'
),
$permissions
);
}
/**
* Create a mock Authority for a temp user with $permissions.
*
* @param array $permissions
* @return Authority
*/
private
function
mockTempAuthorityWithPermissions
(
array
$permissions
):
Authority
{
return
new
SimpleAuthority
(
new
UserIdentityValue
(
42
,
'~2024-1'
),
$permissions
,
true
);
}
/**
* Create a mock Authority for a registered user with $permissions.
*
* @param array $permissions
* @return Authority
*/
private
function
mockRegisteredAuthorityWithPermissions
(
array
$permissions
):
Authority
{
return
new
SimpleAuthority
(
new
UserIdentityValue
(
9999
,
'Petr'
),
$permissions
);
}
/**
* Create a mock Authority for a $user with $permissions.
*
* @param UserIdentity $user
* @param array $permissions
* @param bool $isTemp
* @return Authority
*/
private
function
mockUserAuthorityWithPermissions
(
UserIdentity
$user
,
array
$permissions
,
bool
$isTemp
=
false
):
Authority
{
return
new
SimpleAuthority
(
$user
,
$permissions
,
$isTemp
);
}
/**
* Create a mock Authority for $user with $block and $permissions.
*
* @param UserIdentity $user
* @param Block $block
* @param array $permissions
* @param bool $isTemp
*
* @return Authority
*/
private
function
mockUserAuthorityWithBlock
(
UserIdentity
$user
,
Block
$block
,
array
$permissions
=
[],
bool
$isTemp
=
false
):
Authority
{
return
$this
->
mockAuthority
(
$user
,
static
function
(
$permission
)
use
(
$permissions
)
{
return
in_array
(
$permission
,
$permissions
);
},
$block
,
$isTemp
);
}
/**
* Create a mock Authority for an anon user with all but $permissions
* @param array $permissions
* @return Authority
*/
private
function
mockAnonAuthorityWithoutPermissions
(
array
$permissions
):
Authority
{
return
$this
->
mockUserAuthorityWithoutPermissions
(
new
UserIdentityValue
(
0
,
'127.0.0.1'
),
$permissions
);
}
/**
* Create a mock Authority for a temp user with all but $permissions
* @param array $permissions
* @return Authority
*/
private
function
mockTempAuthorityWithoutPermissions
(
array
$permissions
):
Authority
{
return
$this
->
mockUserAuthorityWithoutPermissions
(
new
UserIdentityValue
(
42
,
'~2024-1'
),
$permissions
,
true
);
}
/**
* Create a mock Authority for a registered user with all but $permissions
* @param array $permissions
* @return Authority
*/
private
function
mockRegisteredAuthorityWithoutPermissions
(
array
$permissions
):
Authority
{
return
$this
->
mockUserAuthorityWithoutPermissions
(
new
UserIdentityValue
(
9999
,
'Petr'
),
$permissions
);
}
/**
* Create a mock Authority for a $user with all but $permissions
* @param UserIdentity $user
* @param array $permissions
* @param bool $isTemp
* @return Authority
*/
private
function
mockUserAuthorityWithoutPermissions
(
UserIdentity
$user
,
array
$permissions
,
bool
$isTemp
=
false
):
Authority
{
return
$this
->
mockAuthority
(
$user
,
static
function
(
$permission
)
use
(
$permissions
)
{
return
!
in_array
(
$permission
,
$permissions
);
},
null
,
$isTemp
);
}
/**
* Create mock Authority for anon user where permissions are determined by $callback.
*
* @param callable $permissionCallback
* @return Authority
*/
private
function
mockAnonAuthority
(
callable
$permissionCallback
):
Authority
{
return
$this
->
mockAuthority
(
new
UserIdentityValue
(
0
,
'127.0.0.1'
),
$permissionCallback
);
}
/**
* Create mock Authority for a temp user where permissions are determined by $callback.
*
* @param callable $permissionCallback
* @return Authority
*/
private
function
mockTempAuthority
(
callable
$permissionCallback
):
Authority
{
return
$this
->
mockAuthority
(
new
UserIdentityValue
(
42
,
'~2024-1'
),
$permissionCallback
,
null
,
true
);
}
/**
* Create mock Authority for registered user where permissions are determined by $callback.
*
* @param callable $permissionCallback
* @return Authority
*/
private
function
mockRegisteredAuthority
(
callable
$permissionCallback
):
Authority
{
return
$this
->
mockAuthority
(
new
UserIdentityValue
(
9999
,
'Petr'
),
$permissionCallback
);
}
/**
* Create mock Authority for $user where permissions are determined by $callback.
*
* @param UserIdentity $user
* @param callable $permissionCallback ( string $permission, PageIdentity $page = null )
* @param Block|null $block
* @param bool $isTemp
*
* @return Authority
*/
private
function
mockAuthority
(
UserIdentity
$user
,
callable
$permissionCallback
,
?
Block
$block
=
null
,
bool
$isTemp
=
false
):
Authority
{
$mock
=
$this
->
createMock
(
Authority
::
class
);
$mock
->
method
(
'getUser'
)->
willReturn
(
$user
);
$methods
=
[
'isAllowed'
,
'probablyCan'
,
'definitelyCan'
,
'authorizeRead'
,
'authorizeWrite'
];
foreach
(
$methods
as
$method
)
{
$mock
->
method
(
$method
)->
willReturnCallback
(
$permissionCallback
);
}
$mock
->
method
(
'isAllowedAny'
)
->
willReturnCallback
(
static
function
(
...
$permissions
)
use
(
$permissionCallback
)
{
foreach
(
$permissions
as
$permission
)
{
if
(
$permissionCallback
(
$permission
)
)
{
return
true
;
}
}
return
false
;
}
);
$mock
->
method
(
'isAllowedAll'
)
->
willReturnCallback
(
static
function
(
...
$permissions
)
use
(
$permissionCallback
)
{
foreach
(
$permissions
as
$permission
)
{
if
(
!
$permissionCallback
(
$permission
)
)
{
return
false
;
}
}
return
true
;
}
);
$mock
->
method
(
'getBlock'
)->
willReturn
(
$block
);
$mock
->
method
(
'isTemp'
)->
willReturn
(
$isTemp
);
$mock
->
method
(
'isNamed'
)->
willReturn
(
$user
->
isRegistered
()
&&
!
$isTemp
);
return
$mock
;
}
/** @return string[] Some dummy message parameters to test error message formatting. */
private
function
getFakeBlockMessageParams
():
array
{
return
[
'[[User:Blocker|Blocker]]'
,
'Block reason that can contain {{templates}}'
,
'192.168.0.1'
,
'Blocker'
,
];
}
/**
* @param bool $limited
* @return RateLimiter
*/
private
function
newRateLimiter
(
$limited
=
false
):
RateLimiter
{
/** @var RateLimiter&MockObject $rateLimiter */
$rateLimiter
=
$this
->
createNoOpMock
(
RateLimiter
::
class
,
[
'limit'
,
'isLimitable'
]
);
$rateLimiter
->
method
(
'limit'
)->
willReturn
(
$limited
);
$rateLimiter
->
method
(
'isLimitable'
)->
willReturn
(
true
);
return
$rateLimiter
;
}
/**
* @param string[] $permissions
* @return PermissionManager
*/
private
function
newPermissionsManager
(
array
$permissions
):
PermissionManager
{
/** @var PermissionManager&MockObject $permissionManager */
$permissionManager
=
$this
->
createNoOpMock
(
PermissionManager
::
class
,
[
'userHasRight'
,
'userHasAnyRight'
,
'userHasAllRights'
,
'userCan'
,
'getPermissionStatus'
,
'getPermissionErrors'
,
'isBlockedFrom'
,
'getApplicableBlock'
,
'newFatalPermissionDeniedStatus'
,
]
);
$permissionManager
->
method
(
'userHasRight'
)->
willReturnCallback
(
static
function
(
$user
,
$permission
)
use
(
$permissions
)
{
return
in_array
(
$permission
,
$permissions
);
}
);
$permissionManager
->
method
(
'userHasAnyRight'
)->
willReturnCallback
(
static
function
(
$user
,
...
$actions
)
use
(
$permissions
)
{
return
array_diff
(
$actions
,
$permissions
)
!=
$actions
;
}
);
$permissionManager
->
method
(
'userHasAllRights'
)->
willReturnCallback
(
static
function
(
$user
,
...
$actions
)
use
(
$permissions
)
{
return
!
array_diff
(
$actions
,
$permissions
);
}
);
$permissionManager
->
method
(
'userCan'
)->
willReturnCallback
(
static
function
(
$permission
,
$user
)
use
(
$permissionManager
)
{
return
$permissionManager
->
userHasRight
(
$user
,
$permission
);
}
);
$fakeBlockMessageParams
=
$this
->
getFakeBlockMessageParams
();
// If the user has a block, the block applies to all actions except for 'read'
$permissionManager
->
method
(
'getPermissionStatus'
)->
willReturnCallback
(
static
function
(
$permission
,
$user
,
$target
)
use
(
$permissionManager
,
$fakeBlockMessageParams
)
{
$status
=
PermissionStatus
::
newEmpty
();
if
(
!
$permissionManager
->
userCan
(
$permission
,
$user
,
$target
)
)
{
$status
->
fatal
(
'permissionserrors'
);
}
if
(
$user
->
getBlock
()
&&
$permission
!==
'read'
)
{
$status
->
fatal
(
'blockedtext-partial'
,
...
$fakeBlockMessageParams
);
}
return
$status
;
}
);
$permissionManager
->
method
(
'getPermissionErrors'
)->
willReturnCallback
(
static
function
(
$permission
,
$user
,
$target
)
use
(
$permissionManager
,
$fakeBlockMessageParams
)
{
return
$permissionManager
->
getPermissionStatus
(
$permission
,
$user
,
$target
)
->
toLegacyErrorArray
();
}
);
$permissionManager
->
method
(
'newFatalPermissionDeniedStatus'
)->
willReturnCallback
(
static
function
(
$permission
,
$context
)
use
(
$permissionManager
)
{
return
StatusValue
::
newFatal
(
'permissionserrors'
);
}
);
// If the page's title is "Forbidden", will return a SystemBlock. Likewise,
// if the action is 'blocked', this will return a SystemBlock.
$permissionManager
->
method
(
'getApplicableBlock'
)->
willReturnCallback
(
static
function
(
$action
,
User
$user
,
$rigor
,
$page
)
{
if
(
$page
&&
$page
->
getDBkey
()
===
'Forbidden'
)
{
return
new
SystemBlock
();
}
if
(
$action
===
'blocked'
)
{
return
new
SystemBlock
();
}
return
null
;
}
);
$permissionManager
->
method
(
'isBlockedFrom'
)->
willReturnCallback
(
static
function
(
User
$user
,
$page
)
{
return
$page
->
getDBkey
()
===
'Forbidden'
;
}
);
return
$permissionManager
;
}
private
function
newUser
(
?
Block
$block
=
null
,
bool
$isTemp
=
false
):
User
{
/** @var User&MockObject $actor */
$actor
=
$this
->
createNoOpMock
(
User
::
class
,
[
'getBlock'
,
'isNewbie'
,
'toRateLimitSubject'
]
);
$actor
->
method
(
'getBlock'
)->
willReturn
(
$block
);
$actor
->
method
(
'isNewbie'
)->
willReturn
(
false
);
$actor
->
method
(
'isTemp'
)->
willReturn
(
$isTemp
);
$actor
->
method
(
'isNamed'
)->
willReturn
(
!
$isTemp
);
$subject
=
new
RateLimitSubject
(
$actor
,
'::1'
,
[]
);
$actor
->
method
(
'toRateLimitSubject'
)->
willReturn
(
$subject
);
return
$actor
;
}
private
function
newBlockErrorFormatter
():
BlockErrorFormatter
{
$blockErrorFormatter
=
$this
->
createNoOpMock
(
BlockErrorFormatter
::
class
,
[
'getMessages'
]
);
$blockErrorFormatter
->
method
(
'getMessages'
)->
willReturn
(
[
new
Message
(
'blocked'
)
]
);
return
$blockErrorFormatter
;
}
private
function
newContext
():
IContextSource
{
$language
=
$this
->
createNoOpMock
(
Language
::
class
,
[
'getCode'
]
);
$language
->
method
(
'getCode'
)->
willReturn
(
'en'
);
$context
=
$this
->
createNoOpMock
(
IContextSource
::
class
,
[
'getLanguage'
]
);
$context
->
method
(
'getLanguage'
)->
willReturn
(
$language
);
return
$context
;
}
private
function
newRequest
():
WebRequest
{
$request
=
new
FauxRequest
();
$request
->
setIP
(
'1.2.3.4'
);
return
$request
;
}
private
function
newUserAuthority
(
array
$options
=
[]
):
UserAuthority
{
$permissionManager
=
$options
[
'permissionManager'
]
??
$this
->
newPermissionsManager
(
$options
[
'permissions'
]
??
[]
);
$rateLimiter
=
$options
[
'rateLimiter'
]
??
$this
->
newRateLimiter
(
$options
[
'limited'
]
??
false
);
$blockErrorFormatter
=
$options
[
'blockErrorFormatter'
]
??
$this
->
newBlockErrorFormatter
();
return
new
UserAuthority
(
$options
[
'actor'
]
??
$this
->
newUser
(),
$options
[
'request'
]
??
$this
->
newRequest
(),
$options
[
'context'
]
??
$this
->
newContext
(),
$permissionManager
,
$rateLimiter
,
$blockErrorFormatter
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 15:56 (14 h, 1 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
fa/e2/ab2fea117f18534a14c6e61c20e4
Default Alt Text
MockAuthorityTrait.php (13 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment