Currently this is implemented internally as a second method call. In the future, it might be possible to optimize the implementation, e.g. to reduce the amount of DB queries/jobs etc. without changing anything for callers. Since the implementation of e.g. the result getters is generic, a future commit may add an option to delete subpages with relatively low effort. The revision limit for big deletions is now using the total number of revisions (base page + talk page). This is because both deletions would happen in the same main transaction, and we presumably want to optimize the deletion as a whole, not as two separated steps. This would become even more important if the aforementioned improvements are ever implemented. Note, the whole concept of "big deletion" might have been superseded by batched deletions in the author's opinion, but as long as such a limit exists, it should serve its purpose. The current interpretation of the associated talk option is that the request is validated, and an exception is raised if we cannot delete the associated talk, as opposed to silently ignoring the parameter if the talk cannot be deleted. The only exception to this is that it will not fail hard if the talk page turns out not to exist by the time the deletion is attempted, as that's hard to foresee due to race conditions. Note that the summary for the talk deletion is prefixed with the delete-talk-summary-prefix message. The main reason behind this is that the delete UI can sometimes offer an auto-generated summary like "the only contributor was XXX" or "the content was YYY", and since this may not apply to the talk page as well, the log entry might look confusing. Bug: T263209 Bug: T27471 Change-Id: Ife1f4e8258a69528dd1ce8fef8ae809761aa6f1d
220 lines
5.8 KiB
PHP
220 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Tests\Unit\Permissions;
|
|
|
|
use MediaWiki\Block\Block;
|
|
use MediaWiki\Permissions\Authority;
|
|
use MediaWiki\Permissions\SimpleAuthority;
|
|
use MediaWiki\Permissions\UltimateAuthority;
|
|
use MediaWiki\User\UserIdentity;
|
|
use MediaWiki\User\UserIdentityValue;
|
|
|
|
/**
|
|
* 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 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 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 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
|
|
* @return Authority
|
|
*/
|
|
private function mockUserAuthorityWithPermissions(
|
|
UserIdentity $user,
|
|
array $permissions
|
|
): Authority {
|
|
return new SimpleAuthority( $user, $permissions );
|
|
}
|
|
|
|
/**
|
|
* Create a mock Authority for $user with $block and $permissions.
|
|
*
|
|
* @param UserIdentity $user
|
|
* @param Block $block
|
|
* @param array $permissions
|
|
*
|
|
* @return Authority
|
|
*/
|
|
private function mockUserAuthorityWithBlock(
|
|
UserIdentity $user,
|
|
Block $block,
|
|
array $permissions = []
|
|
): Authority {
|
|
return $this->mockAuthority(
|
|
$user,
|
|
static function ( $permission ) use ( $permissions ) {
|
|
return in_array( $permission, $permissions );
|
|
},
|
|
$block
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 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 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
|
|
* @return Authority
|
|
*/
|
|
private function mockUserAuthorityWithoutPermissions(
|
|
UserIdentity $user,
|
|
array $permissions
|
|
): Authority {
|
|
return $this->mockAuthority(
|
|
$user,
|
|
static function ( $permission ) use ( $permissions ) {
|
|
return !in_array( $permission, $permissions );
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 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 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
|
|
*
|
|
* @return Authority
|
|
*/
|
|
private function mockAuthority(
|
|
UserIdentity $user,
|
|
callable $permissionCallback,
|
|
Block $block = null
|
|
): 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 );
|
|
return $mock;
|
|
}
|
|
}
|