Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F6023145
SpecialNukeHTMLFormTest.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
85 KB
Referenced Files
None
Subscribers
None
SpecialNukeHTMLFormTest.php
View Options
<?php
namespace
MediaWiki\Extension\Nuke\Test\Integration
;
use
MediaWiki\Context\RequestContext
;
use
MediaWiki\Exception\ErrorPageError
;
use
MediaWiki\Exception\PermissionsError
;
use
MediaWiki\Extension\Nuke\NukeConfigNames
;
use
MediaWiki\Extension\Nuke\SpecialNuke
;
use
MediaWiki\Extension\Nuke\Test\NukeIntegrationTest
;
use
MediaWiki\MainConfigNames
;
use
MediaWiki\Permissions\UltimateAuthority
;
use
MediaWiki\Request\FauxRequest
;
use
MediaWiki\Tests\User\TempUser\TempUserTestTrait
;
use
MediaWiki\Title\Title
;
use
SpecialPageTestBase
;
use
Wikimedia\IPUtils
;
/**
* @group Database
* @covers \MediaWiki\Extension\Nuke\SpecialNuke
* @covers \MediaWiki\Extension\Nuke\NukeQueryBuilder
* @covers \MediaWiki\Extension\Nuke\Form\SpecialNukeUIRenderer
* @covers \MediaWiki\Extension\Nuke\Form\SpecialNukeHTMLFormUIRenderer
* @covers \MediaWiki\Extension\Nuke\Form\HTMLForm\NukeDateTimeField
* @covers \MediaWiki\Extension\Nuke\NukeContext
*/
class
SpecialNukeHTMLFormTest
extends
SpecialPageTestBase
{
use
NukeIntegrationTest
;
use
TempUserTestTrait
;
/**
* @before
* @return void
*/
public
function
nukeUISetUp
()
{
$this
->
overrideConfigValue
(
NukeConfigNames
::
UIType
,
null
);
}
protected
function
newSpecialPage
():
SpecialNuke
{
$services
=
$this
->
getServiceContainer
();
return
new
SpecialNuke
(
$services
->
getJobQueueGroup
(),
$services
->
getDBLoadBalancerFactory
(),
$services
->
getPermissionManager
(),
$services
->
getRepoGroup
(),
$services
->
getUserOptionsLookup
(),
$services
->
getUserNamePrefixSearch
(),
$services
->
getUserNameUtils
(),
$services
->
getNamespaceInfo
(),
$services
->
getContentLanguage
(),
$services
->
getRedirectLookup
(),
$services
->
getService
(
'NukeIPLookup'
)
);
}
/**
* Ensure that the prompt appears as expected for users with nuke permission.
*
* @return void
*/
public
function
testPrompt
()
{
$admin
=
$this
->
getTestSysop
()->
getUser
();
$this
->
disableAutoCreateTempUser
();
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
null
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'(nuke-summary)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools-prompt)'
,
$html
);
$this
->
assertStringNotContainsString
(
'(nuke-tools-prompt-restricted)'
,
$html
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-submit-continue'
,
$html
);
}
/**
* Ensure that the prompt appears as expected for users without nuke permission.
*
* @return void
*/
public
function
testPromptNoPermission
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
$this
->
disableAutoCreateTempUser
();
$permissionManager
=
$this
->
getServiceContainer
()->
getPermissionManager
();
$permissions
=
$permissionManager
->
getUserPermissions
(
$user
);
$permissions
=
array_diff
(
$permissions
,
[
'nuke'
]
);
$permissionManager
->
overrideUserRightsForTesting
(
$user
,
$permissions
);
$performer
=
new
UltimateAuthority
(
$user
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
null
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'(nuke-summary)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools)'
,
$html
);
$this
->
assertStringNotContainsString
(
'(nuke-tools-prompt)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools-prompt-restricted)'
,
$html
);
$this
->
assertStringNotContainsString
(
'(nuke-tools-notice-blocked)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools-notice-noperm)'
,
$html
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-submit-continue'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-minsize)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-maxsize)'
,
$html
);
}
/**
* Ensure that the prompt displays the correct messages when
* temp accounts and CheckUser are enabled
*
* @return void
*/
public
function
testPromptWithCheckUser
()
{
$this
->
markTestSkippedIfExtensionNotLoaded
(
'CheckUser'
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$this
->
enableAutoCreateTempUser
();
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
null
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'(nuke-summary)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools-tempaccount)'
,
$html
);
}
/**
* Ensure that the prompt appears as expected for a blocked sysop
*
* @return void
*/
public
function
testPromptBlocked
()
{
$user
=
$this
->
getTestSysop
()->
getUser
();
$performer
=
new
UltimateAuthority
(
$user
);
// Self-blocks should still prevent the form from being shown
$this
->
getServiceContainer
()
->
getBlockUserFactory
()
->
newBlockUser
(
$user
,
$performer
,
'infinity'
,
'SpecialNukeTest::testBlocked'
)
->
placeBlockUnsafe
();
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
null
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'(nuke-summary)'
,
$html
);
$this
->
assertStringNotContainsString
(
'(nuke-tools-prompt)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools-prompt-restricted)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools-notice-blocked)'
,
$html
);
$this
->
assertStringNotContainsString
(
'(nuke-tools-notice-noperm)'
,
$html
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-submit-continue'
,
$html
);
// regression check: now list the pages and confirm the same message is shown at the top
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user
->
getName
()
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
assertStringContainsString
(
'(nuke-summary)'
,
$html
);
$this
->
assertStringNotContainsString
(
'(nuke-tools-prompt)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools-prompt-restricted)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-tools-notice-blocked)'
,
$html
);
$this
->
assertStringNotContainsString
(
'(nuke-tools-notice-noperm)'
,
$html
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-submit-continue'
,
$html
);
$this
->
getServiceContainer
()
->
getUnblockUserFactory
()
->
newUnblockUser
(
$user
,
$performer
,
'SpecialNukeTest::testBlocked'
)
->
unblockUnsafe
();
}
/**
* Ensure that the prompt prevents a nuke user without the checkuser-temporary-account permission
* from performing CheckUser IP lookups
*
* @return void
*/
public
function
testListCheckUserNoPermission
()
{
$this
->
expectException
(
PermissionsError
::
class
);
$this
->
markTestSkippedIfExtensionNotLoaded
(
'CheckUser'
);
$this
->
enableAutoCreateTempUser
();
$ip
=
'1.2.3.4'
;
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$permissionManager
=
$this
->
getServiceContainer
()->
getPermissionManager
();
$permissions
=
$permissionManager
->
getUserPermissions
(
$adminUser
);
$permissions
=
array_diff
(
$permissions
,
[
'checkuser-temporary-account'
]
);
$permissionManager
->
overrideUserRightsForTesting
(
$adminUser
,
$permissions
);
$performer
=
new
UltimateAuthority
(
$adminUser
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$ip
,
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
}
/**
* Ensure that the prompt prevents a nuke user who hasn't accepted the agreement
* from performing CheckUser IP lookups
*
* @return void
*/
public
function
testListCheckUserNoAgreementAccepted
()
{
$this
->
expectException
(
ErrorPageError
::
class
);
$this
->
expectExceptionMessage
(
'To view temporary account contributions for an IP, please accept'
.
' the agreement in [[Special:Preferences|your preferences]].'
);
$this
->
markTestSkippedIfExtensionNotLoaded
(
'CheckUser'
);
$this
->
enableAutoCreateTempUser
();
$ip
=
'1.2.3.4'
;
$this
->
overrideConfigValues
(
[
'GroupPermissions'
=>
[
'testgroup'
=>
[
'nuke'
=>
true
,
'checkuser-temporary-account'
=>
true
]
]
]
);
$adminUser
=
$this
->
getTestUser
(
[
'testgroup'
]
)->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$ip
,
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
}
/**
* Ensure that pages created by a specific user are shown accordingly
*
* @return void
*/
public
function
testListTarget
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
$this
->
insertPage
(
'Target1'
,
'test'
,
NS_MAIN
,
$user
);
$this
->
insertPage
(
'Target2'
,
'test'
,
NS_MAIN
,
$user
);
$this
->
insertPage
(
'Should not show'
,
'No show'
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$request1
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user
->
getName
()
]
);
[
$html1
]
=
$this
->
executeSpecialPage
(
''
,
$request1
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html1
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html1
);
$this
->
assertStringContainsString
(
'nuke-submit-continue'
,
$html1
);
$this
->
assertStringContainsString
(
'Target1'
,
$html1
);
$this
->
assertStringContainsString
(
'Target2'
,
$html1
);
$this
->
assertStringNotContainsString
(
'Should not show'
,
$html1
);
// Not supplying an action should imply 'list'.
$request2
=
new
FauxRequest
(
[
'target'
=>
$user
->
getName
()
]
);
[
$html2
]
=
$this
->
executeSpecialPage
(
''
,
$request2
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html2
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html2
);
$this
->
assertStringContainsString
(
'nuke-submit-continue'
,
$html2
);
$this
->
assertStringContainsString
(
'Target1'
,
$html2
);
$this
->
assertStringContainsString
(
'Target2'
,
$html2
);
$this
->
assertStringNotContainsString
(
'Should not show'
,
$html2
);
}
/**
* Ensure that the prompt works with anon IP searches when temp accounts are disabled
*
* @return void
*/
public
function
testListTargetAnonUser
()
{
$this
->
disableAutoCreateTempUser
(
[
'known'
=>
false
]
);
$ip
=
'127.0.0.1'
;
$testUser
=
$this
->
getServiceContainer
()->
getUserFactory
()->
newAnonymous
(
$ip
);
$performer
=
new
UltimateAuthority
(
$testUser
);
$this
->
editPage
(
'Target1'
,
'test'
,
""
,
NS_MAIN
,
$performer
);
$this
->
editPage
(
'Target2'
,
'test'
,
""
,
NS_MAIN
,
$performer
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
()
]
);
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'Target1'
,
$html
);
$this
->
assertStringContainsString
(
'Target2'
,
$html
);
$this
->
assertEquals
(
2
,
substr_count
(
$html
,
'nuke-editby: 127.0.0.1'
),
"Failed asserting that the IP address is shown twice in '$html'"
);
}
public
static
function
provideListTargetNormalizeUser
()
{
yield
'normalize IPv4'
=>
[
'001.002.003.004'
,
'1.2.3.4'
];
$ip
=
'2001:0db8::ff00:0042:8329'
;
yield
'normalize IPv6'
=>
[
$ip
,
IPUtils
::
sanitizeIP
(
$ip
)
];
}
/**
* Ensure that the prompt works with searches for non-canonical user names, like lowercase IPv6
* @dataProvider provideListTargetNormalizeUser
*/
public
function
testListTargetNormalizeUser
(
$target
,
$normalized
)
{
$this
->
disableAutoCreateTempUser
(
[
'known'
=>
false
]
);
$testUser
=
$this
->
getServiceContainer
()->
getUserFactory
()->
newAnonymous
(
$normalized
);
$performer
=
new
UltimateAuthority
(
$testUser
);
$this
->
editPage
(
'Target1'
,
'test'
,
""
,
NS_MAIN
,
$performer
);
$this
->
editPage
(
'Target2'
,
'test'
,
""
,
NS_MAIN
,
$performer
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$target
]
);
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'Target1'
,
$html
);
$this
->
assertStringContainsString
(
'Target2'
,
$html
);
$this
->
assertEquals
(
2
,
substr_count
(
$html
,
"(nuke-editby: $normalized)"
)
);
}
/**
* Ensure that the prompt returns temp accounts from IP lookups when temp accounts and
* CheckUser are enabled
*
* @return void
*/
public
function
testListTargetCheckUser
()
{
$this
->
markTestSkippedIfExtensionNotLoaded
(
'CheckUser'
);
$this
->
enableAutoCreateTempUser
();
$ip
=
'1.2.3.4'
;
RequestContext
::
getMain
()->
getRequest
()->
setIP
(
$ip
);
$testUser
=
$this
->
getServiceContainer
()->
getTempUserCreator
()
->
create
(
null
,
new
FauxRequest
()
)->
getUser
();
$this
->
editPage
(
'Target1'
,
'test'
,
""
,
NS_MAIN
,
$testUser
);
$this
->
editPage
(
'Target2'
,
'test'
,
""
,
NS_MAIN
,
$testUser
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$permissionManager
=
$this
->
getServiceContainer
()->
getPermissionManager
();
$permissionManager
->
overrideUserRightsForTesting
(
$adminUser
,
array_merge
(
$permissionManager
->
getUserPermissions
(
$adminUser
),
[
'checkuser-temporary-account-no-preference'
]
)
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$ip
,
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$year
=
gmdate
(
'Y'
);
$this
->
assertEquals
(
2
,
substr_count
(
$html
,
"~$year-1"
),
"Failed asserting that the temporary account is shown twice in '$html'"
);
$this
->
assertStringContainsString
(
'Target1'
,
$html
);
$this
->
assertStringContainsString
(
'Target2'
,
$html
);
}
/**
* Ensure that the prompt returns temp accounts and IP accounts from IP lookups when
* temp accounts and CheckUser are enabled and Anonymous IP accounts exist
*
* @return void
*/
public
function
testListTargetCheckUserMixed
()
{
$this
->
markTestSkippedIfExtensionNotLoaded
(
'CheckUser'
);
$this
->
disableAutoCreateTempUser
(
[
'known'
=>
false
]
);
$ip
=
'1.2.3.4'
;
$testUser
=
$this
->
getServiceContainer
()->
getUserFactory
()->
newAnonymous
(
$ip
);
$performer
=
new
UltimateAuthority
(
$testUser
);
// create a page as an anonymous IP user
$this
->
editPage
(
'Target1'
,
'test'
,
""
,
NS_MAIN
,
$performer
);
$this
->
enableAutoCreateTempUser
();
RequestContext
::
getMain
()->
getRequest
()->
setIP
(
$ip
);
$testUser
=
$this
->
getServiceContainer
()->
getTempUserCreator
()
->
create
(
null
,
new
FauxRequest
()
)->
getUser
();
$performer
=
new
UltimateAuthority
(
$testUser
);
// create a page as a temp user
$this
->
editPage
(
'Target2'
,
'test'
,
""
,
NS_MAIN
,
$performer
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$permissionManager
=
$this
->
getServiceContainer
()->
getPermissionManager
();
$permissionManager
->
overrideUserRightsForTesting
(
$adminUser
,
array_merge
(
$permissionManager
->
getUserPermissions
(
$adminUser
),
[
'checkuser-temporary-account-no-preference'
]
)
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$ip
,
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$year
=
gmdate
(
'Y'
);
$this
->
assertSame
(
1
,
substr_count
(
$html
,
"~$year-1"
),
"Failed asserting that the temporary account name is shown once in '$html'"
);
$this
->
assertSame
(
1
,
substr_count
(
$html
,
'nuke-editby: 1.2.3.4'
),
"Failed asserting that the IP address is shown once in '$html'"
);
// They should all show up together
$this
->
assertStringContainsString
(
'Target1'
,
$html
);
$this
->
assertStringContainsString
(
'Target2'
,
$html
);
}
/**
* Ensure that matching wildcards works, and that escaping wildcards works as documented at
* https://www.mediawiki.org/wiki/Help:Extension:Nuke
*
* @return void
*/
public
function
testListPattern
()
{
$this
->
editPage
(
'%PositiveNukeTest123'
,
'test'
);
$this
->
editPage
(
'NegativeNukeTest123'
,
'test'
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'
\\
%PositiveNukeTest%'
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'PositiveNukeTest123'
,
$html
);
$this
->
assertStringNotContainsString
(
'NegativeNukeTest123'
,
$html
);
}
public
function
testListNamespaces
()
{
$this
->
insertPage
(
'Page123'
,
'Test'
,
NS_MAIN
);
$this
->
insertPage
(
'Paging456'
,
'Test'
,
NS_MAIN
);
$this
->
insertPage
(
'Should not show'
,
'No show'
,
NS_TALK
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'namespace'
=>
NS_MAIN
,
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'Page123'
,
$html
);
$this
->
assertStringContainsString
(
'Paging456'
,
$html
);
$this
->
assertStringNotContainsString
(
'Should not show'
,
$html
);
}
public
function
testListNoPagesGlobal
()
{
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'ThisPageShouldNotExist-'
.
rand
()
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-nopages-global'
]
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-submit-continue'
,
$html
);
}
public
function
testListNoPagesUser
()
{
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
'ThisPageShouldNotExist-'
.
rand
()
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-nopages-global'
]
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-submit-continue'
,
$html
);
}
public
function
testListNamespace
()
{
$this
->
editPage
(
'NukeUserPageTarget'
,
'test'
,
''
,
NS_USER
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'NukeUserPageTarget'
,
'namespace'
=>
NS_USER
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$expectedTitle
=
Title
::
makeTitle
(
NS_USER
,
'NukeUserPageTarget'
)
->
getPrefixedText
();
$this
->
assertStringContainsString
(
$expectedTitle
,
$html
);
}
public
function
testListTalk
()
{
$this
->
editPage
(
'NukeTalkPageTarget'
,
'test'
,
''
,
NS_TALK
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'NukeTalkPageTarget'
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$expectedTitle
=
Title
::
makeTitle
(
NS_TALK
,
'NukeTalkPageTarget'
)
->
getPrefixedText
();
$this
->
assertStringContainsString
(
$expectedTitle
,
$html
);
}
public
function
testListNamespaceMultiple
()
{
$this
->
editPage
(
'NukeMainPageTarget'
,
'test'
);
$this
->
editPage
(
'NukeProjectPageTarget'
,
'test'
,
''
,
NS_PROJECT
);
$this
->
editPage
(
'NukeUserPageTarget'
,
'test'
,
''
,
NS_USER
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'Nuke%PageTarget'
,
'namespace'
=>
implode
(
"
\n
"
,
[
NS_MAIN
,
NS_USER
]
)
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
Title
::
makeTitle
(
NS_MAIN
,
'NukeMainPageTarget'
)->
getPrefixedText
(),
$html
);
$this
->
assertStringContainsString
(
Title
::
makeTitle
(
NS_USER
,
'NukeUserPageTarget'
)->
getPrefixedText
(),
$html
);
$this
->
assertStringNotContainsString
(
Title
::
makeTitle
(
NS_PROJECT
,
'NukNukeProjectPageTarget'
)->
getPrefixedText
(),
$html
);
}
public
function
testListNamespaceMultipleEdge
()
{
$page1
=
$this
->
insertPage
(
'NukeMainPageTarget'
,
'test'
)[
'title'
];
$page2
=
$this
->
insertPage
(
'NukeProjectPageTarget'
,
'test'
,
NS_PROJECT
)[
'title'
];
$page3
=
$this
->
insertPage
(
'NukeUserPageTarget'
,
'test'
,
NS_USER
)[
'title'
];
$admin
=
$this
->
getTestSysop
()->
getUser
();
$performer
=
new
UltimateAuthority
(
$admin
);
// Input includes empty line
$request1
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'Nuke%PageTarget'
,
'namespace'
=>
NS_PROJECT
.
"
\n
"
],
true
);
[
$html1
]
=
$this
->
executeSpecialPage
(
''
,
$request1
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html1
);
$this
->
assertStringNotContainsString
(
$page1
,
$html1
);
$this
->
assertStringContainsString
(
$page2
,
$html1
);
$this
->
assertStringNotContainsString
(
$page3
,
$html1
);
// Input includes invalid namespace ID
$request1
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'Nuke%PageTarget'
,
'namespace'
=>
NS_PROJECT
.
"
\n
99999999"
],
true
);
[
$html1
]
=
$this
->
executeSpecialPage
(
''
,
$request1
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html1
);
$this
->
assertStringNotContainsString
(
$page1
,
$html1
);
$this
->
assertStringContainsString
(
$page2
,
$html1
);
$this
->
assertStringNotContainsString
(
$page3
,
$html1
);
// Input includes a string
$request1
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'Nuke%PageTarget'
,
'namespace'
=>
NS_PROJECT
.
"
\n
User"
],
true
);
[
$html1
]
=
$this
->
executeSpecialPage
(
''
,
$request1
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html1
);
$this
->
assertStringNotContainsString
(
$page1
,
$html1
);
$this
->
assertStringContainsString
(
$page2
,
$html1
);
$this
->
assertStringNotContainsString
(
$page3
,
$html1
);
// Input is entirely invalid
$request1
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'Nuke%PageTarget'
,
'namespace'
=>
"Project
\n
User"
],
true
);
[
$html1
]
=
$this
->
executeSpecialPage
(
''
,
$request1
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html1
);
// Pages from all namespaces will be returned
$this
->
assertStringContainsString
(
$page1
,
$html1
);
$this
->
assertStringContainsString
(
$page2
,
$html1
);
$this
->
assertStringContainsString
(
$page3
,
$html1
);
}
public
function
testListCapitalizedNamespace
()
{
$this
->
overrideConfigValues
(
[
'CapitalLinks'
=>
false
,
'CapitalLinkOverrides'
=>
[]
]
);
$this
->
editPage
(
'uncapsTarget'
,
'test'
);
$this
->
editPage
(
'UncapsTarget'
,
'test'
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$expectedTitle
=
Title
::
makeTitle
(
NS_MAIN
,
'uncapsTarget'
)
->
getPrefixedText
();
$shouldMatch
=
[
"%ncapsTarget"
,
"u%"
,
"uncapsTarget"
];
$shouldNotMatch
=
[
"UncapsTarget"
];
foreach
(
$shouldMatch
as
$match
)
{
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'uncapsTarget'
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
$expectedTitle
,
$html
,
"match: $match"
);
foreach
(
$shouldNotMatch
as
$noMatch
)
{
$this
->
assertStringNotContainsString
(
$noMatch
,
$html
);
}
}
}
public
function
testListCapitalizedNamespaceOverrides
()
{
$overriddenNamespaces
=
[
NS_PROJECT
=>
true
,
NS_MEDIAWIKI
=>
true
,
NS_USER
=>
true
,
];
$this
->
overrideConfigValues
(
[
'CapitalLinks'
=>
false
,
'CapitalLinkOverrides'
=>
$overriddenNamespaces
]
);
$overriddenNamespaces
[
NS_MAIN
]
=
false
;
foreach
(
$overriddenNamespaces
as
$ns
=>
$override
)
{
$this
->
editPage
(
"UncapsTarget"
.
$ns
,
'test'
,
''
,
$ns
);
// If capital links for this ns is `true`, then the existing page should be edited.
$this
->
editPage
(
"uncapsTarget"
.
$ns
,
'test2'
,
''
,
$ns
);
}
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'u%'
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
"uncapsTarget"
.
NS_MAIN
,
$html
);
// Check that the overridden namespaces are included in the search
$this
->
assertStringContainsString
(
"UncapsTarget"
.
NS_PROJECT
,
$html
);
$this
->
assertStringContainsString
(
"UncapsTarget"
.
NS_MEDIAWIKI
,
$html
);
$this
->
assertStringContainsString
(
"UncapsTarget"
.
NS_USER
,
$html
);
$this
->
assertStringNotContainsString
(
"UncapsTarget"
.
NS_MAIN
,
$html
);
// Check that the non-overridden namespaces are not included in the search
$this
->
assertStringNotContainsString
(
"uncapsTarget"
.
NS_PROJECT
,
$html
);
$this
->
assertStringNotContainsString
(
"uncapsTarget"
.
NS_MEDIAWIKI
,
$html
);
$this
->
assertStringNotContainsString
(
"uncapsTarget"
.
NS_USER
,
$html
);
}
public
function
testListCapitalizedNamespaceMultiple
()
{
// The goal of this test is to:
// - Ensure that for case-sensitive namespaces, the search remains case-sensitive.
// - Ensure that for non-case-sensitive namespaces, the search capitalizes the condition accordingly.
// Here, `NS_MAIN` remains case-insensitive, but other namespaces will be case-sensitive.
$this
->
overrideConfigValues
(
[
'CapitalLinks'
=>
false
,
'CapitalLinkOverrides'
=>
[
NS_MAIN
=>
true
]
]
);
$this
->
editPage
(
'UncapsTargetMain'
,
'test'
);
$this
->
editPage
(
'UncapsTarget'
,
'test'
,
''
,
NS_PROJECT
);
$this
->
editPage
(
'uncapsTarget'
,
'test'
,
''
,
NS_PROJECT
);
$this
->
editPage
(
'UncapsTarget'
,
'test'
,
''
,
NS_HELP
);
$this
->
editPage
(
'uncapsTarget'
,
'test'
,
''
,
NS_HELP
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'uncapsTarget%'
,
'namespace'
=>
implode
(
"
\n
"
,
[
NS_MAIN
,
NS_HELP
]
)
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
Title
::
makeTitle
(
NS_MAIN
,
'UncapsTargetMain'
)->
getPrefixedText
(),
$html
);
$this
->
assertStringContainsString
(
Title
::
makeTitle
(
NS_HELP
,
'uncapsTarget'
)->
getPrefixedText
(),
$html
);
$this
->
assertStringNotContainsString
(
Title
::
makeTitle
(
NS_PROJECT
,
'UncapsTarget'
)->
getPrefixedText
(),
$html
);
$this
->
assertStringNotContainsString
(
Title
::
makeTitle
(
NS_PROJECT
,
'uncapsTarget'
)->
getPrefixedText
(),
$html
);
$this
->
assertStringNotContainsString
(
Title
::
makeTitle
(
NS_HELP
,
'UncapsTarget'
)->
getPrefixedText
(),
$html
);
}
/**
* Check if Nuke still works with languages with complicated capitalization
* or no capitalization.
*
* Since the first letter of each title should be capitalized, searching for the
* lowercase version should still yield the uppercase version, or the same character
* if casing does not exist for the language.
*
* @return void
*/
public
function
testListCapitalized
()
{
/** @noinspection SpellCheckingInspection */
$testedLanguages
=
[
"ee"
=>
[
"Ülemiste"
,
"ülemiste"
],
"zh"
=>
"你好"
,
"ja"
=>
"にほんご"
,
];
foreach
(
$testedLanguages
as
$lang
=>
$testData
)
{
[
$created
,
$wanted
]
=
is_array
(
$testData
)
?
$testData
:
[
$testData
,
$testData
];
// Disable case-sensitive page titles
$this
->
overrideConfigValue
(
'CapitalLinks'
,
true
);
$this
->
overrideConfigValue
(
'LanguageCode'
,
$lang
);
$this
->
editPage
(
$created
,
'test'
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
$wanted
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
$created
,
$html
);
}
}
public
function
testListLimit
()
{
$this
->
editPage
(
'Page1'
,
'test'
);
$this
->
editPage
(
'Page2'
,
'test'
);
$this
->
editPage
(
'Page3'
,
'test'
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'Page%'
,
'limit'
=>
2
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
// NOTE: No 'nuke-associated-limited' message box will be shown here, because the limit is
// enforced on the initial 'pages' query and no associated pages are selected.
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertEquals
(
2
,
substr_count
(
$html
,
'<li>'
),
"Failed asserting that two entries are shown in '$html'"
);
}
public
function
testListLimitWithHooks
()
{
$this
->
editPage
(
'Page1'
,
'test'
);
$this
->
editPage
(
'Page2'
,
'test'
);
$this
->
editPage
(
'Page3'
,
'test'
);
$this
->
setTemporaryHook
(
"NukeGetNewPages"
,
static
function
(
$_1
,
$_2
,
$_3
,
$_4
,
&
$pages
)
{
$pages
[]
=
"Page3"
;
return
true
;
}
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'Page%'
,
'limit'
=>
2
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertEquals
(
2
,
substr_count
(
$html
,
'<li>'
),
"Failed asserting that two entries are shown in '$html'"
);
}
public
function
testListMaxAge
()
{
$time
=
time
();
$creator
=
$this
->
getTestUser
()->
getAuthority
();
// A page that's always older than $wgNukeMaxAge and $wgRCMaxAge.
// This should never show up; if it does, the max age isn't being applied at all.
$this
->
editPageAtTime
(
'Page1'
,
'test'
,
''
,
$time
-
(
86400
*
7
),
NS_MAIN
,
$creator
);
// A page that's four days old.
$this
->
editPageAtTime
(
'Page2'
,
'test'
,
''
,
$time
-
(
86400
*
4
),
NS_MAIN
,
$creator
);
// A page that's two days old.
$this
->
editPageAtTime
(
'Page3'
,
'test'
,
''
,
$time
-
(
86400
*
2
),
NS_MAIN
,
$creator
);
// A page that was just made.
$this
->
editPage
(
'Page4'
,
'test'
,
''
,
NS_MAIN
,
$creator
);
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
86400
*
5
,
'RCMaxAge'
=>
86400
*
3
]
);
$this
->
rebuildRecentChanges
(
$time
-
(
86400
*
3
)
-
60
,
$time
+
60
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$performer
=
new
UltimateAuthority
(
$admin
);
// == Pattern-only (recentchanges) searches ==
// Request with a pattern but no actor.
// This should use the recentchanges table exclusively.
// Page3 and Page4 should be present.
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'Page%'
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'nuke-daterange-helper-text-max-age-different'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-daterange-helper-text-max-age-same'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
// Changing NukeMaxAge to be way larger than RCMaxAge shouldn't affect that query.
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
86400
*
6
,
'RCMaxAge'
=>
86400
]
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'nuke-daterange-helper-text-max-age-different'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-daterange-helper-text-max-age-same'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
// Changing NukeMaxAge to be smaller than RCMaxAge should limit to just those pages.
// We don't want to provide pages larger than the scope of NukeMaxAge just because
// we're using the recentchanges table.
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
600
,
'RCMaxAge'
=>
86400
]
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'nuke-daterange-helper-text-max-age-different'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-daterange-helper-text-max-age-same'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
// Changing NukeMaxAge to 0 should make it fall back to RCMaxAge.
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
0
,
'RCMaxAge'
=>
86400
*
3
]
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'nuke-daterange-helper-text-max-age-different'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-daterange-helper-text-max-age-same'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
// == With-actor (revision) searches ==
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$creator
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
],
true
);
// NukeMaxAge falls back to RCMaxAge.
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
0
,
'RCMaxAge'
=>
86400
*
3
]
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'nuke-daterange-helper-text-max-age-different'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-daterange-helper-text-max-age-same'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
// NukeMaxAge matches RCMaxAge. Should have no difference from above.
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
86400
*
3
,
'RCMaxAge'
=>
86400
*
3
]
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'nuke-daterange-helper-text-max-age-different'
,
$html
);
$this
->
assertStringContainsString
(
'nuke-daterange-helper-text-max-age-same'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
// NukeMaxAge is greater than RCMaxAge. It should show older pages.
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
86400
*
5
,
'RCMaxAge'
=>
86400
]
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'nuke-daterange-helper-text-max-age-different'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-daterange-helper-text-max-age-same'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
// NukeMaxAge is lesser than RCMaxAge. It should show newer pages.
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
86400
*
3
,
'RCMaxAge'
=>
86400
*
5
]
);
// Rebuild recent changes to make Page2 reappear on the recentchanges table.
// We still don't want to match it.
$this
->
rebuildRecentChanges
(
$time
-
(
86400
*
8
)
-
60
,
$time
+
60
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'nuke-daterange-helper-text-max-age-different'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-daterange-helper-text-max-age-same'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
}
public
function
testListDateFrom
()
{
$time
=
time
();
// 7 days
$maxAge
=
86400
*
7
;
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
$maxAge
]
);
$testUser
=
$this
->
getTestUser
();
// Will never show up. If it does, the max age isn't being applied at all.
// We're still checking this here on the off-chance that something in Special:Nuke logic
// causes us to completely forget about our max age configuration.
$this
->
editPageAtTime
(
'Page1'
,
'test'
,
''
,
$time
-
(
$maxAge
*
2
),
NS_MAIN
,
$testUser
->
getAuthority
()
);
// Will show up conditionally (see below).
$this
->
editPageAtTime
(
'Page2'
,
'test'
,
''
,
$time
-
(
86400
*
2
),
NS_MAIN
,
$testUser
->
getAuthority
()
);
// Will always show up.
$this
->
editPage
(
'Page3'
,
'test'
,
''
,
NS_MAIN
,
$testUser
->
getAuthority
()
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
// Test setting from to include Page3 only
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateFrom'
=>
date
(
'Y-m-d'
,
$time
),
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
// Now include Page2 by including things which are 2 days old
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateFrom'
=>
date
(
'Y-m-d'
,
$time
-
(
86400
*
2
)
),
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
// Now go beyond our max age and ensure we get an error
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateFrom'
=>
date
(
'Y-m-d'
,
$time
-
(
$maxAge
*
2
+
60
)
),
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-date-limited'
]
);
$this
->
assertStringContainsString
(
"(days: 7)"
,
$html
);
// The search should not happen at all.
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page3'
,
$html
);
// Now go beyond the current time and ensure we get no pages
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateFrom'
=>
date
(
'Y-m-d'
,
$time
+
86400
),
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
// There should be no listed pages.
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-nopages-global'
]
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page3'
,
$html
);
// Test invalid date filter
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateFrom'
=>
'i am an invalid date filter!!!'
,
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
// The search should not happen.
$this
->
checkForValidationMessages
(
$html
,
[
'htmlform-date-invalid'
]
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page3'
,
$html
);
}
public
function
testListDateTo
()
{
// 7 days
$maxAge
=
86400
*
7
;
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
$maxAge
]
);
$testUser
=
$this
->
getTestUser
();
// Will never show up. If it does, the max age isn't being applied at all.
// We're still checking this here on the off-chance that something in Special:Nuke logic
// causes us to completely forget about our max age configuration.
$this
->
editPageAtTime
(
'Page1'
,
'test'
,
''
,
time
()
-
(
$maxAge
*
2
),
NS_MAIN
,
$testUser
->
getAuthority
()
);
// Will always show up.
$this
->
editPageAtTime
(
'Page2'
,
'test'
,
''
,
time
()
-
(
86400
*
4
),
NS_MAIN
,
$testUser
->
getAuthority
()
);
// Will show up conditionally (see below).
$this
->
editPage
(
'Page3'
,
'test'
,
''
,
NS_MAIN
,
$testUser
->
getAuthority
()
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
// Include everything except Page1
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateTo'
=>
date
(
'Y-m-d'
,
time
()
),
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
// Now exclude Page3 by shortening the date range
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateTo'
=>
date
(
'Y-m-d'
,
time
()
-
(
86400
*
2
)
),
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringContainsString
(
'Page2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page3'
,
$html
);
// Now go beyond our max age and ensure we get an error
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateTo'
=>
date
(
'Y-m-d'
,
time
()
-
(
$maxAge
*
2
+
60
)
),
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-date-limited'
]
);
$this
->
assertStringContainsString
(
"(days: 7)"
,
$html
);
// The search should not happen at all.
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page3'
,
$html
);
// Now go beyond the current time and ensure we still get pages
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateTo'
=>
date
(
'Y-m-d'
,
time
()
+
86400
),
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
// Test invalid date filter
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'limit'
=>
2
,
'wpdateTo'
=>
'i am an invalid date filter!!!'
,
// Required for field validation to run
'wpFormIdentifier'
=>
'massdelete'
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
// The search should not happen.
$this
->
checkForValidationMessages
(
$html
,
[
'htmlform-date-invalid'
]
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page3'
,
$html
);
}
/**
* Runs tests which use both "from date" and "to date" filters.
*
* See also:
* - {@link testListDateFrom}
* - {@link testListDateTo}
*
* @return void
*/
public
function
testListDateFilters
()
{
// 7 days
$maxAge
=
86400
*
7
;
$this
->
overrideConfigValues
(
[
'NukeMaxAge'
=>
$maxAge
]
);
$testUser
=
$this
->
getTestUser
();
for
(
$i
=
0
;
$i
<=
8
;
$i
++
)
{
// Creates Page0, Page1, Page2... with creation date of `now`, `now - 1 day`, `now -
// 2 days`, etc.
$this
->
editPageAtTime
(
"Page$i"
,
"$i"
,
''
,
time
()
-
(
86400
*
$i
),
NS_MAIN
,
$testUser
->
getAuthority
()
);
}
$admin
=
$this
->
getTestSysop
()->
getUser
();
// Standard search
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'wpdateFrom'
=>
date
(
'Y-m-d'
,
time
()
-
(
86400
*
4
)
),
'wpdateTo'
=>
date
(
'Y-m-d'
,
time
()
-
(
86400
*
2
)
)
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'Page0'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
// A page created on the same day as "to date" should still be included.
$this
->
assertStringContainsString
(
'Page2'
,
$html
);
$this
->
assertStringContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page5'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page6'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page7'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page8'
,
$html
);
// Impossible search ("to date" is before "from date")
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'wpdateFrom'
=>
date
(
'Y-m-d'
,
time
()
-
(
86400
*
2
)
),
'wpdateTo'
=>
date
(
'Y-m-d'
,
time
()
-
(
86400
*
4
)
)
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-nopages-global'
]
);
$this
->
assertStringNotContainsString
(
'Page0'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page3'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page4'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page5'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page6'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page7'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page8'
,
$html
);
// Single date search ("to date" is equal to "from date")
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$testUser
->
getUser
()->
getName
(),
'pattern'
=>
'Page%'
,
'wpdateFrom'
=>
date
(
'Y-m-d'
,
time
()
-
(
86400
*
4
)
),
'wpdateTo'
=>
date
(
'Y-m-d'
,
time
()
-
(
86400
*
4
)
)
],
true
);
$adminPerformer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'Page0'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page3'
,
$html
);
$this
->
assertStringContainsString
(
'Page4'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page5'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page6'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page7'
,
$html
);
$this
->
assertStringNotContainsString
(
'Page8'
,
$html
);
}
public
function
testListIncludeTalkPages
()
{
$user1
=
$this
->
getMutableTestUser
();
$user2
=
$this
->
getMutableTestUser
();
// Create a page and its talk page
$this
->
insertPage
(
'Page1'
,
'test'
,
NS_MAIN
,
$user1
->
getUser
()
);
$this
->
insertPage
(
'Talk:Page1'
,
'test'
,
NS_TALK
,
$user2
->
getUser
()
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$performer
=
new
UltimateAuthority
(
$admin
);
// Include talk pages
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user1
->
getUser
()->
getName
(),
'includeTalkPages'
=>
true
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
// HTML syntax here is used to ensure that it doesn't appear inside a tag.
$this
->
assertStringContainsString
(
'Page1</a>'
,
$html
);
$this
->
assertStringContainsString
(
'Talk:Page1</a>'
,
$html
);
$this
->
assertStringContainsString
(
$user2
->
getUser
()->
getName
(),
$html
);
// Exclude talk pages
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user1
->
getUser
()->
getName
(),
'includeTalkPages'
=>
false
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
// HTML syntax here is used to ensure that it doesn't appear inside a tag.
$this
->
assertStringContainsString
(
'Page1</a>'
,
$html
);
$this
->
assertStringNotContainsString
(
'Talk:Page1</a>'
,
$html
);
$this
->
assertStringNotContainsString
(
$user2
->
getUser
()->
getName
(),
$html
);
}
public
function
testListIncludeRedirectPages
()
{
$user1
=
$this
->
getMutableTestUser
();
$user2
=
$this
->
getMutableTestUser
();
// Create a page and its talk page
$this
->
insertPage
(
'Page 1'
,
'test'
,
NS_MAIN
,
$user1
->
getUser
()
);
$this
->
insertPage
(
'Redirect 1'
,
'#REDIRECT [[Page 1]]'
,
NS_MAIN
,
$user2
->
getUser
()
)[
'title'
];
$this
->
runJobs
();
$admin
=
$this
->
getTestSysop
()->
getUser
();
$performer
=
new
UltimateAuthority
(
$admin
);
// Include talk pages
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user1
->
getUser
()->
getName
(),
'includeRedirects'
=>
true
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
// HTML syntax here is used to ensure that it doesn't appear inside a tag.
$this
->
assertStringContainsString
(
'Page 1</a>'
,
$html
);
$this
->
assertStringContainsString
(
'Redirect 1</a>'
,
$html
);
$this
->
assertStringContainsString
(
$user2
->
getUser
()->
getName
(),
$html
);
// Exclude talk pages
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user1
->
getUser
()->
getName
(),
'includeRedirects'
=>
false
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
// HTML syntax here is used to ensure that it doesn't appear inside a tag.
$this
->
assertStringContainsString
(
'Page 1</a>'
,
$html
);
$this
->
assertStringNotContainsString
(
'Redirect 1</a>'
,
$html
);
$this
->
assertStringNotContainsString
(
$user2
->
getUser
()->
getName
(),
$html
);
}
/**
* Ensure that pages don't appear twice on the list when a page was created by a user and is
* also an associated page of another page.
*
* @return void
*/
public
function
testListAssociatedPagesDeduplication
()
{
$user
=
$this
->
getTestUser
();
$this
->
insertPage
(
'Page 1'
,
'test'
,
NS_MAIN
,
$user
->
getUser
()
);
$this
->
insertPage
(
'Redirect 1'
,
'#REDIRECT [[Page 1]]'
,
NS_MAIN
,
$user
->
getUser
()
);
$this
->
insertPage
(
'Page 1'
,
'test'
,
NS_TALK
,
$user
->
getUser
()
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$performer
=
new
UltimateAuthority
(
$admin
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user
->
getUser
()->
getName
(),
'includeTalkPages'
=>
true
,
'includeRedirects'
=>
true
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
// HTML syntax here is used to ensure that it doesn't appear inside a tag.
$this
->
assertSame
(
1
,
substr_count
(
$html
,
'>Page 1</a>'
),
"Failed asserting that
\"
$html
\"
contains '>>Page 1</a>' only once."
);
$this
->
assertSame
(
1
,
substr_count
(
$html
,
'>Redirect 1</a>'
),
"Failed asserting that
\"
$html
\"
contains '>Redirect 1</a>' only once."
);
$this
->
assertSame
(
1
,
substr_count
(
$html
,
'>Talk:Page 1</a>'
),
"Failed asserting that
\"
$html
\"
contains '>Talk:Page 1</a>' only once."
);
}
public
function
testListLimitAssociatedPages
()
{
$time
=
time
();
$authority1
=
$this
->
getMutableTestUser
()->
getAuthority
();
$authority2
=
$this
->
getMutableTestUser
()->
getAuthority
();
$page1
=
$this
->
editPageAtTime
(
'Page 1'
,
'test'
,
''
,
$time
,
NS_MAIN
,
$authority1
);
$this
->
editPageAtTime
(
'Page 2'
,
'test'
,
''
,
$time
-
5
,
NS_MAIN
,
$authority1
);
$this
->
editPageAtTime
(
'Page 3'
,
'test'
,
''
,
$time
-
10
,
NS_MAIN
,
$authority1
);
$this
->
editPageAtTime
(
'Redirect 1'
,
'#REDIRECT [[Page 2]]'
,
''
,
$time
-
1
,
NS_MAIN
,
$authority2
);
$this
->
editPageAtTime
(
'Redirect 2'
,
'#REDIRECT [[Page 2]]'
,
''
,
$time
-
20
,
NS_MAIN
,
$authority2
);
$this
->
editPageAtTime
(
'Page 3'
,
'test'
,
''
,
$time
-
25
,
NS_TALK
,
$authority2
);
$pages
=
[
'Page 1'
,
'Page 2'
,
'Page 3'
,
'Redirect 1'
,
'Redirect 2'
,
'Talk:Page 3'
];
$admin
=
$this
->
getTestSysop
()->
getUser
();
$performer
=
new
UltimateAuthority
(
$admin
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$authority1
->
getUser
()->
getName
(),
'includeTalkPages'
=>
true
,
'includeRedirects'
=>
true
],
true
);
// First test no limits
$request
->
setVal
(
'limit'
,
7
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringsFound
(
$html
,
$pages
,
$pages
);
// Now test with limit = 1.
// Only Page 1 should show up, and there should be no validation error messages.
$request
->
setVal
(
'limit'
,
1
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringsFound
(
$html
,
$pages
,
[
'Page 1'
]
);
// Now test with limit = 2.
// It should still only be page 1 here.
// Page 2 will be skipped because it has 2 associated pages, totalling 3 pages in the group.
// Page 3 will be skipped because it has a talk page, totalling 2 pages in the group.
// This will cause a limit warning to show up.
$request
->
setVal
(
'limit'
,
2
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-associated-limited'
]
);
$this
->
assertStringsFound
(
$html
,
$pages
,
[
'Page 1'
]
);
// Now test with limit = 3
// Only the Page 1 and Page 3 should show up.
// Page 2 will be skipped because it has 2 associated pages, totalling 3 pages in the group.
// This will cause a limit warning to show up.
$request
->
setVal
(
'limit'
,
3
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-associated-limited'
]
);
$this
->
assertStringsFound
(
$html
,
$pages
,
[
'Page 1'
,
'Page 3'
,
'Talk:Page 3'
]
);
// Now test with limit = 4
// Page 1, Page 2, and all its redirects should show up.
// Page 3 will be excluded since Page 2 was created later.
// This will cause a limit warning to show up.
$request
->
setVal
(
'limit'
,
4
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-associated-limited'
]
);
$this
->
assertStringsFound
(
$html
,
$pages
,
[
'Page 1'
,
'Page 2'
,
'Redirect 1'
,
'Redirect 2'
]
);
// Now test with limit = 4, but include only talk pages
// Page 1, Page 2, Page 3, and Talk:Page 3 should show up.
// There should be no limit warning.
$request
->
setVal
(
'limit'
,
4
);
$request
->
setVal
(
'includeRedirects'
,
false
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringsFound
(
$html
,
$pages
,
[
'Page 1'
,
'Page 2'
,
'Page 3'
,
'Talk:Page 3'
]
);
// Now test with limit = 1, but delete Page 1
// There should be a limit warning and a no pages warning.
$this
->
deletePage
(
$this
->
getServiceContainer
()->
getWikiPageFactory
()->
newFromID
(
$page1
->
getNewRevision
()->
getPageId
()
)
);
$request
->
setVal
(
'limit'
,
1
);
$request
->
setVal
(
'includeRedirects'
,
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-nopages-global'
,
'nuke-associated-limited'
]
);
$this
->
assertStringsFound
(
$html
,
$pages
,
[]
);
}
public
function
testListFiles
()
{
$this
->
overrideConfigValue
(
MainConfigNames
::
EnableUploads
,
true
);
$testFileName
=
$this
->
uploadTestFile
()[
'title'
]->
getPrefixedText
();
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'namespace'
=>
NS_FILE
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
);
// The title should be in the list
$this
->
assertStringContainsString
(
$testFileName
,
$html
);
// There should also be an image preview
$this
->
assertStringContainsString
(
"<img src"
,
$html
);
}
public
function
testConfirm
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
// Set content language to English; needed to get the right "defaultreason".
$this
->
overrideConfigValue
(
'wgLanguageCode'
,
'en'
);
$defaultReason
=
RequestContext
::
getMain
()
->
msg
(
'nuke-defaultreason'
,
$user
->
getName
()
)
->
inContentLanguage
()
->
text
();
/** @var Title $page1 */
$page1
=
$this
->
insertPage
(
'Target1'
,
'test'
,
NS_MAIN
,
$user
)[
'title'
];
/** @var Title $page2 */
$page2
=
$this
->
insertPage
(
'Target2'
,
'test'
)[
'title'
];
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_CONFIRM
,
'target'
=>
$user
->
getName
(),
'pages'
=>
[
$page1
->
getPrefixedDBkey
()
],
'originalPageList'
=>
implode
(
SpecialNuke
::
PAGE_LIST_SEPARATOR
,
[
$page1
->
getPrefixedDBkey
(),
$page2
->
getPrefixedDBkey
()
]
),
// 'confirm' action requires an edit token
'wpEditToken'
=>
$user
->
getEditToken
()
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
// Default reason should pre-fill the reason field
$this
->
assertStringContainsString
(
$defaultReason
,
$html
);
// Selected pages will have talk and history links
$this
->
assertStringContainsString
(
'Target1'
,
$html
);
$this
->
assertStringContainsString
(
'Talk:Target1'
,
$html
);
$this
->
assertStringContainsString
(
'Target1&action=history'
,
$html
);
// Skipped pages will not show up at all, but will be found in the hidden
// originalPageList field.
$this
->
assertStringContainsString
(
'Target2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Talk:Target2'
,
$html
);
$this
->
assertStringNotContainsString
(
'Target2&action=history'
,
$html
);
// Ensure the originalPageList field was included
$this
->
assertStringContainsString
(
'"originalPageList"'
,
$html
);
$this
->
assertStringContainsString
(
'"Target1|Target2"'
,
$html
);
}
/**
* Tests a malformed confirm request: a request that either
* - was not posted
* - does not have an edit token
*
* @return void
*/
public
function
testConfirmMalformed
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
/** @var Title $page1 */
$page1
=
$this
->
insertPage
(
'Target1'
,
'test'
,
NS_MAIN
,
$user
)[
'title'
];
/** @var Title $page2 */
$page2
=
$this
->
insertPage
(
'Target2'
,
'test'
)[
'title'
];
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_CONFIRM
,
'target'
=>
$user
->
getName
(),
'pages'
=>
[
$page1
->
getPrefixedDBkey
()
],
'originalPageList'
=>
implode
(
SpecialNuke
::
PAGE_LIST_SEPARATOR
,
[
$page1
->
getPrefixedDBkey
(),
$page2
->
getPrefixedDBkey
()
]
),
],
false
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
// We should be re-prompting the user, since no edit token was provided.
$this
->
assertStringContainsString
(
"(nuke-tools-prompt)"
,
$html
);
// Correct target should still be on the prompt box
$this
->
assertStringContainsString
(
$user
->
getName
(),
$html
);
}
/**
* Ensure that the default deletion reason used correctly changes based on whether or not
* temporary accounts are being used or not.
*
* @return void
*/
public
function
testConfirmAnonUser
()
{
$this
->
markTestSkippedIfExtensionNotLoaded
(
'CheckUser'
);
$this
->
enableAutoCreateTempUser
();
$ip
=
'1.2.3.4'
;
RequestContext
::
getMain
()->
getRequest
()->
setIP
(
$ip
);
$testUser
=
$this
->
getServiceContainer
()->
getTempUserCreator
()
->
create
(
null
,
new
FauxRequest
()
)->
getUser
();
$user
=
$this
->
getTestUser
()->
getUser
();
// Set content language to English; needed to get the right "defaultreason".
$this
->
overrideConfigValue
(
'wgLanguageCode'
,
'en'
);
$defaultReason
=
RequestContext
::
getMain
()
->
msg
(
'nuke-defaultreason-tempaccount'
,
$user
->
getName
()
)
->
inContentLanguage
()
->
text
();
/** @var Title $page1 */
$page1
=
$this
->
insertPage
(
'Target1'
,
'test'
,
NS_MAIN
,
$testUser
)[
'title'
];
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$permissionManager
=
$this
->
getServiceContainer
()->
getPermissionManager
();
$permissionManager
->
overrideUserRightsForTesting
(
$adminUser
,
array_merge
(
$permissionManager
->
getUserPermissions
(
$adminUser
),
[
'checkuser-temporary-account-no-preference'
]
)
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_CONFIRM
,
'target'
=>
$ip
,
'pages'
=>
[
$page1
->
getPrefixedDBkey
()
],
'originalPageList'
=>
$page1
->
getPrefixedDBkey
(),
// 'confirm' action requires an edit token
'wpEditToken'
=>
$user
->
getEditToken
()
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
$defaultReason
,
$html
);
$this
->
assertStringContainsString
(
'Target1'
,
$html
);
$this
->
assertStringContainsString
(
'Talk:Target1'
,
$html
);
$this
->
assertStringContainsString
(
'Target1&action=history'
,
$html
);
}
/**
* Tests requests which have pages but no original page list. This is similar to a click on
* the "Continue" button without having first clicked on the "List pages" button.
*
* @return void
*/
public
function
testConfirmWithoutList
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
$this
->
editPage
(
'Page1'
,
'test'
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_CONFIRM
,
// 'confirm' action requires an edit token
'wpEditToken'
=>
$user
->
getEditToken
()
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-nolist'
]
);
// The search should not happen automatically.
$this
->
assertStringNotContainsString
(
'Page1'
,
$html
);
}
public
function
testConfirmWithoutSelection
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
/** @var Title $page1 */
$page1
=
$this
->
insertPage
(
'Target1'
,
'test'
,
NS_MAIN
,
$user
)[
'title'
];
/** @var Title $page2 */
$page2
=
$this
->
insertPage
(
'Target2'
,
'test'
)[
'title'
];
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_CONFIRM
,
'target'
=>
$user
->
getName
(),
'originalPageList'
=>
implode
(
SpecialNuke
::
PAGE_LIST_SEPARATOR
,
[
$page1
->
getPrefixedDBkey
(),
$page2
->
getPrefixedDBkey
()
]
),
// 'confirm' action requires an edit token
'wpEditToken'
=>
$user
->
getEditToken
()
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-noselected'
]
);
// The search should still happen.
$this
->
assertStringContainsString
(
'Target1'
,
$html
);
// Page2 was not created by the user, it shouldn't show up.
$this
->
assertStringNotContainsString
(
'Target2'
,
$html
);
}
public
function
testConfirmAssociatedPages
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
$this
->
insertPage
(
'Page 1'
,
'test'
,
NS_MAIN
,
$user
);
$this
->
insertPage
(
'Redirect 2'
,
'#REDIRECT [[Page 1]]'
,
NS_MAIN
,
$user
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_CONFIRM
,
'target'
=>
$user
->
getName
(),
'originalPageList'
=>
implode
(
SpecialNuke
::
PAGE_LIST_SEPARATOR
,
[
'Page_1'
,
'Page_2'
]
),
'pages'
=>
[
'Page_1'
],
'associatedPages'
=>
[
'Redirect_2'
],
// 'confirm' action requires an edit token
'wpEditToken'
=>
$user
->
getEditToken
()
],
true
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
// Ensure that the associated pages are also listed on the confirm form
$this
->
assertStringContainsString
(
'name="associatedPages[]"'
,
$html
);
}
public
function
testDelete
()
{
$pages
=
[];
$pages
[]
=
$this
->
insertPage
(
'Page123'
,
'Test'
,
NS_MAIN
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Paging456'
,
'Test'
,
NS_MAIN
)[
'title'
];
$admin
=
$this
->
getTestSysop
()->
getUser
();
$fauxReason
=
"Reason "
.
wfRandomString
();
$request
=
new
FauxRequest
(
[
'action'
=>
'delete'
,
'wpDeleteReasonList'
=>
'Vandalism'
,
'wpReason'
=>
$fauxReason
,
'pages'
=>
$pages
,
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$admin
->
getEditToken
(),
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$deleteCount
=
count
(
$pages
);
$this
->
assertStringContainsString
(
"(nuke-delete-summary: $deleteCount)"
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-deletion-queued: Page123)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-deletion-queued: Paging456)'
,
$html
);
// Pre-check to confirm that the page hasn't been deleted yet
// "mw-tag-marker-nuke" is the CSS class for the "Nuke" tag's <span> on Special:Log.
$this
->
assertStringNotContainsString
(
'mw-tag-marker-nuke'
,
$this
->
getDeleteLogHtml
()
);
// Ensure all delete jobs are run
$this
->
runJobs
();
$deleteLogHtml
=
$this
->
getDeleteLogHtml
();
$this
->
assertStringContainsString
(
'Vandalism'
,
$deleteLogHtml
);
$this
->
assertStringContainsString
(
'mw-tag-marker-nuke'
,
$deleteLogHtml
);
$this
->
assertStringContainsString
(
$fauxReason
,
$deleteLogHtml
);
}
public
function
testDeleteTarget
()
{
$pages
=
[];
$testUser
=
$this
->
getTestUser
(
"user"
)->
getUser
();
$testUserName
=
$testUser
->
getName
();
$this
->
overrideConfigValue
(
MainConfigNames
::
EnableUploads
,
true
);
$pages
[]
=
$this
->
uploadTestFile
(
$testUser
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Page123'
,
'Test'
,
NS_MAIN
,
$testUser
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Paging456'
,
'Test'
,
NS_MAIN
,
$testUser
)[
'title'
];
$admin
=
$this
->
getTestSysop
()->
getUser
();
$fauxReason
=
"Reason "
.
wfRandomString
();
$request
=
new
FauxRequest
(
[
'action'
=>
'delete'
,
'wpDeleteReasonList'
=>
'Vandalism'
,
'wpReason'
=>
$fauxReason
,
'target'
=>
$testUserName
,
'pages'
=>
$pages
,
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$admin
->
getEditToken
(),
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$deleteCount
=
count
(
$pages
);
$this
->
assertStringContainsString
(
"(nuke-delete-summary-user: $deleteCount, $testUserName)"
,
$html
);
}
public
function
testDeleteTargetAnon
()
{
$pages
=
[];
$testUser
=
$this
->
getTestUser
(
"user"
)->
getUser
();
$testUserName
=
$testUser
->
getName
();
$this
->
overrideConfigValue
(
MainConfigNames
::
EnableUploads
,
true
);
$pages
[]
=
$this
->
uploadTestFile
(
$testUser
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Page123'
,
'Test'
,
NS_MAIN
,
$testUser
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Paging456'
,
'Test'
,
NS_MAIN
,
$testUser
)[
'title'
];
$admin
=
$this
->
getTestSysop
()->
getUser
();
$fauxReason
=
"Reason "
.
wfRandomString
();
$request
=
new
FauxRequest
(
[
'action'
=>
'delete'
,
'wpDeleteReasonList'
=>
'Vandalism'
,
'wpReason'
=>
$fauxReason
,
'pages'
=>
$pages
,
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$admin
->
getEditToken
(),
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$deleteCount
=
count
(
$pages
);
$this
->
assertStringContainsString
(
"(nuke-delete-summary: $deleteCount)"
,
$html
);
}
public
function
testDeleteSkipped
()
{
$pages
=
[];
$pages
[]
=
$this
->
insertPage
(
'Page123'
,
'Test'
,
NS_MAIN
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Paging 456'
,
'Test'
,
NS_MAIN
)[
'title'
];
$skippedPage
=
$this
->
insertPage
(
'Page 789'
,
'Test'
,
NS_MAIN
)[
'title'
];
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
'delete'
,
'wpDeleteReasonList'
=>
'Vandalism'
,
'originalPageList'
=>
implode
(
'|'
,
$pages
),
'pages'
=>
[
$skippedPage
->
getPrefixedDBkey
()
],
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$admin
->
getEditToken
(),
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$skippedCount
=
count
(
$pages
);
$this
->
assertStringContainsString
(
'(nuke-delete-summary: 1)'
,
$html
);
$this
->
assertStringContainsString
(
"(nuke-skipped-summary: $skippedCount)"
,
$html
);
// Ensure all delete jobs are run
$this
->
runJobs
();
// Make sure that those pages are not in the deletion log.
$deleteLogHtml
=
$this
->
getDeleteLogHtml
();
foreach
(
$pages
as
$title
)
{
$this
->
assertStringNotContainsString
(
$title
->
getPrefixedText
(),
$deleteLogHtml
);
}
$this
->
assertStringContainsString
(
$skippedPage
->
getPrefixedText
(),
$deleteLogHtml
);
}
public
function
testDeleteDropdownReason
()
{
$pages
=
[];
$pages
[]
=
$this
->
insertPage
(
'Page123'
,
'Test'
,
NS_MAIN
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Paging456'
,
'Test'
,
NS_MAIN
)[
'title'
];
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
'delete'
,
'wpDeleteReasonList'
=>
'Vandalism'
,
'wpReason'
=>
""
,
'pages'
=>
$pages
,
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$admin
->
getEditToken
(),
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
// Ensure all jobs are run
$this
->
runJobs
();
// Check logs
$this
->
assertStringContainsString
(
"Vandalism"
,
$this
->
getDeleteLogHtml
()
);
}
public
function
testDeleteCustomReason
()
{
$pages
=
[];
$pages
[]
=
$this
->
insertPage
(
'Page123'
,
'Test'
,
NS_MAIN
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Paging456'
,
'Test'
,
NS_MAIN
)[
'title'
];
$admin
=
$this
->
getTestSysop
()->
getUser
();
$fauxReason
=
"Reason "
.
wfRandomString
();
$request
=
new
FauxRequest
(
[
'action'
=>
'delete'
,
'wpDeleteReasonList'
=>
'other'
,
'wpReason'
=>
$fauxReason
,
'pages'
=>
$pages
,
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$admin
->
getEditToken
(),
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
// Ensure all jobs are run
$this
->
runJobs
();
// Check logs
$this
->
assertStringContainsString
(
$fauxReason
,
$this
->
getDeleteLogHtml
()
);
}
public
function
testDeleteAssociatedReason
()
{
$this
->
insertPage
(
'Page 1'
,
'Test'
,
NS_MAIN
);
$this
->
insertPage
(
'Redirect 1'
,
'#REDIRECT [[Page 1]]'
,
NS_MAIN
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$fauxReason
=
"Reason "
.
wfRandomString
();
$request
=
new
FauxRequest
(
[
'action'
=>
'delete'
,
'wpDeleteReasonList'
=>
'other'
,
'wpReason'
=>
$fauxReason
,
'pages'
=>
[
'Page 1'
],
'associatedPages'
=>
[
'Redirect 1'
],
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$admin
->
getEditToken
(),
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
// Ensure all jobs are run
$this
->
runJobs
();
// Check logs
$logHtml
=
$this
->
getDeleteLogHtml
();
$this
->
assertStringContainsString
(
$fauxReason
,
$logHtml
);
$this
->
assertStringContainsString
(
wfMessage
(
'delete-talk-summary-prefix'
,
$fauxReason
)
->
inContentLanguage
()
->
text
(),
$this
->
getDeleteLogHtml
()
);
}
public
function
testDeleteFiles
()
{
$this
->
overrideConfigValue
(
MainConfigNames
::
EnableUploads
,
true
);
$testFileName
=
$this
->
uploadTestFile
()[
'title'
]->
getPrefixedText
();
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
'delete'
,
'wpDeleteReasonList'
=>
'Reason'
,
'wpReason'
=>
'Reason'
,
'pages'
=>
[
$testFileName
],
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$admin
->
getEditToken
(),
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
// Files are deleted instantly
$this
->
assertStringContainsString
(
"nuke-deleted"
,
$html
);
$this
->
assertStringContainsString
(
$testFileName
,
$html
);
}
public
function
testDeleteHook
()
{
$wasCalled
=
false
;
$pages
=
[];
$pages
[]
=
$this
->
insertPage
(
'Bad article'
,
'test'
,
NS_MAIN
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'DO NOT DELETE'
,
'test'
,
NS_MAIN
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Bad article 2'
,
'test'
,
NS_MAIN
)[
'title'
];
$this
->
setTemporaryHook
(
"NukeDeletePage"
,
static
function
(
Title
$title
,
$reason
,
&
$deletionResult
)
use
(
&
$wasCalled
)
{
$wasCalled
=
true
;
$deletionResult
=
$title
->
getPrefixedText
()
!==
"DO NOT DELETE"
;
return
$title
->
getPrefixedText
()
===
"Bad article 2"
;
}
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
'delete'
,
'wpDeleteReasonList'
=>
'Reason'
,
'wpReason'
=>
'Reason'
,
'pages'
=>
$pages
,
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$admin
->
getRequest
()->
getSession
()->
getToken
(),
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
assertTrue
(
$wasCalled
);
$this
->
assertStringContainsString
(
'(nuke-deleted: Bad article)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-not-deleted: DO NOT DELETE)'
,
$html
);
$this
->
assertStringContainsString
(
'(nuke-deletion-queued: Bad article 2)'
,
$html
);
}
public
function
testOldDeleteProtectedPage
()
{
$pages
=
[];
$pages
[]
=
$this
->
insertPage
(
'Page123'
,
'Test'
,
NS_MAIN
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Page456'
,
'Test'
,
NS_MAIN
)[
'title'
];
$pages
[]
=
$this
->
insertPage
(
'Page789'
,
'Test'
,
NS_MAIN
)[
'title'
];
$this
->
overrideConfigValues
(
[
"GroupPermissions"
=>
[
"testgroup"
=>
[
"nuke"
=>
true
,
"delete"
=>
true
]
]
]
);
$services
=
$this
->
getServiceContainer
();
$page
=
$services
->
getWikiPageFactory
()
->
newFromTitle
(
$pages
[
2
]
);
$restrictions
=
[];
foreach
(
$services
->
getRestrictionStore
()->
listApplicableRestrictionTypes
(
$page
)
as
$type
)
{
$restrictions
[
$type
]
=
"sysop"
;
}
$cascade
=
false
;
$page
->
doUpdateRestrictions
(
$restrictions
,
[],
$cascade
,
"test"
,
$this
->
getTestSysop
()->
getUser
()
);
$testUser
=
$this
->
getTestUser
(
[
"testgroup"
]
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_DELETE
,
'wpDeleteReasonList'
=>
'other'
,
'wpReason'
=>
'Reason'
,
'pages'
=>
$pages
,
'wpFormIdentifier'
=>
'nukelist'
,
'wpEditToken'
=>
$testUser
->
getUser
()->
getEditToken
(),
],
true
);
$this
->
expectException
(
PermissionsError
::
class
);
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$testUser
->
getAuthority
()
);
foreach
(
$pages
as
$checkedPage
)
{
$this
->
assertTrue
(
$checkedPage
->
exists
()
);
}
}
public
function
testSearchSubpages
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
$username
=
$user
->
getName
();
$truncatedUsername
=
substr
(
$username
,
0
,
2
);
$searchResults1
=
$this
->
newSpecialPage
()
->
prefixSearchSubpages
(
$truncatedUsername
,
10
,
0
);
$this
->
assertArrayContains
(
[
$username
],
$searchResults1
);
$searchResults2
=
$this
->
newSpecialPage
()
->
prefixSearchSubpages
(
""
,
10
,
0
);
$this
->
assertCount
(
0
,
$searchResults2
);
}
/**
* Test filtering by minimum page size.
*
* @return void
*/
public
function
testListMinPageSizeFilter
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
// 4 bytes content
$this
->
insertPage
(
'SmallPage'
,
'test'
,
NS_MAIN
,
$user
);
// 9 bytes content
$this
->
insertPage
(
'MediumPage'
,
'test test'
,
NS_MAIN
,
$user
);
// 14 bytes content
$this
->
insertPage
(
'LargePage'
,
'test test test'
,
NS_MAIN
,
$user
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user
->
getName
(),
// Filter out pages smaller than 10 bytes
'minPageSize'
=>
10
]
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'SmallPage'
,
$html
);
$this
->
assertStringNotContainsString
(
'MediumPage'
,
$html
);
$this
->
assertStringContainsString
(
'LargePage'
,
$html
);
}
/**
* Test filtering by maximum page size.
*
* @return void
*/
public
function
testListMaxPageSizeFilter
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
// 4 bytes content
$this
->
insertPage
(
'SmallPage'
,
'test'
,
NS_MAIN
,
$user
);
// 9 bytes content
$this
->
insertPage
(
'MediumPage'
,
'test test'
,
NS_MAIN
,
$user
);
// 14 bytes content
$this
->
insertPage
(
'LargePage'
,
'test test test'
,
NS_MAIN
,
$user
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user
->
getName
(),
// Filter out pages larger than 9 bytes
'maxPageSize'
=>
9
,
]
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringContainsString
(
'SmallPage'
,
$html
);
$this
->
assertStringContainsString
(
'MediumPage'
,
$html
);
$this
->
assertStringNotContainsString
(
'LargePage'
,
$html
);
}
/**
* Test filtering by both minimum and maximum page size.
*
* @return void
*/
public
function
testListMinMaxPageSizeFilter
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
// 2 bytes content
$this
->
insertPage
(
'TinyPage'
,
'te'
,
NS_MAIN
,
$user
);
// 4 bytes content
$this
->
insertPage
(
'SmallPage'
,
'test'
,
NS_MAIN
,
$user
);
// 9 bytes content
$this
->
insertPage
(
'MediumPage'
,
'test test'
,
NS_MAIN
,
$user
);
// 14 bytes content
$this
->
insertPage
(
'LargePage'
,
'test test test'
,
NS_MAIN
,
$user
);
// 19 bytes content
$this
->
insertPage
(
'HugePage'
,
'test test test test'
,
NS_MAIN
,
$user
);
$adminUser
=
$this
->
getTestSysop
()->
getUser
();
$adminPerformer
=
new
UltimateAuthority
(
$adminUser
);
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user
->
getName
(),
// Minimum size is 5 bytes
'minPageSize'
=>
5
,
// Maximum size is 15 bytes
'maxPageSize'
=>
15
]
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$adminPerformer
);
$this
->
checkForValidationMessages
(
$html
);
$this
->
assertStringNotContainsString
(
'TinyPage'
,
$html
);
// size is 4, less than minSize
$this
->
assertStringNotContainsString
(
'SmallPage'
,
$html
);
// size is 9, within range
$this
->
assertStringContainsString
(
'MediumPage'
,
$html
);
// size is 14, within range
$this
->
assertStringContainsString
(
'LargePage'
,
$html
);
// size is 19, greater than maxSize
$this
->
assertStringNotContainsString
(
'HugePage'
,
$html
);
}
/**
* Check if a validation warning/error message can be found in the search, and ensure that no
* other error messages appear.
*
* @param string $html The HTML to check
* @param string[] $messages The i18n keys of the messages that should be found.
* @return void
*/
protected
function
checkForValidationMessages
(
string
$html
,
?
array
$messages
=
[]
)
{
$errorMessages
=
[
"htmlform-user-not-valid"
,
"nuke-date-limited"
,
"nuke-date-ahead"
,
"htmlform-date-invalid"
,
"nuke-nolist"
,
"nuke-nopages-global"
,
"nuke-noselected"
,
"nuke-associated-limited"
,
"nuke-searchnotice-minmorethanmax"
,
"nuke-searchnotice-negmin"
,
"nuke-searchnotice-negmax"
];
$shouldBeFound
=
$messages
;
$shouldBeMissing
=
array_diff
(
$errorMessages
,
$messages
);
foreach
(
$shouldBeFound
as
$validationMessage
)
{
$this
->
assertStringContainsString
(
$validationMessage
,
$html
);
}
foreach
(
$shouldBeMissing
as
$validationMessage
)
{
$this
->
assertStringNotContainsString
(
$validationMessage
,
$html
);
}
}
/**
* Test search notices are displayed when no pages are found and there are search notices.
*
* @return void
*/
public
function
testListNoPagesGlobalWithSearchNotices
()
{
$admin
=
$this
->
getTestSysop
()->
getUser
();
// Cause a search notice by maxing the min more than the max
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'pattern'
=>
'ThisPageShouldNotExist-'
.
rand
(),
'minPageSize'
=>
2000
,
'maxPageSize'
=>
1000
,
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-nopages-global'
,
'nuke-searchnotice-minmorethanmax'
]
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html
);
$this
->
assertStringNotContainsString
(
'nuke-submit-continue'
,
$html
);
}
/**
* Test search notices are displayed even when pages are found.
*
* @return void
*/
public
function
testListWithSearchNotices
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
$this
->
insertPage
(
'SomePage'
,
'test'
,
NS_MAIN
,
$user
);
$admin
=
$this
->
getTestSysop
()->
getUser
();
$request
=
new
FauxRequest
(
[
'action'
=>
SpecialNuke
::
ACTION_LIST
,
'target'
=>
$user
->
getName
(),
'minPageSize'
=>
-
1
,
'maxPageSize'
=>
1000
,
],
true
);
$performer
=
new
UltimateAuthority
(
$admin
);
[
$html
]
=
$this
->
executeSpecialPage
(
''
,
$request
,
'qqx'
,
$performer
);
$this
->
checkForValidationMessages
(
$html
,
[
'nuke-searchnotice-negmin'
]
);
$this
->
assertStringContainsString
(
'nuke-submit-list'
,
$html
);
$this
->
assertStringContainsString
(
'nuke-submit-continue'
,
$html
);
// Page should still be listed
$this
->
assertStringContainsString
(
'SomePage'
,
$html
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Oct 4 2026, 15:42 (5 w, 4 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
e8/1e/47e0033ddd90b138e53119c81a30
Default Alt Text
SpecialNukeHTMLFormTest.php (85 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment