*/
use Wikimedia\Rdbms\IDatabase;
+use MediaWiki\MediaWikiServices;
/**
* This abstract class implements many basic API functions, and is the base of
/** @var array Maps extension paths to info arrays */
private static $extensionInfo = null;
+ /** @var int[][][] Cache for self::filterIDs() */
+ private static $filterIDsCache = [];
+
/** @var ApiMain */
private $mMainModule;
/** @var string */
}
$value = $this->getMain()->getCheck( $encParamName );
+ $provided = $value;
} elseif ( $type == 'upload' ) {
if ( isset( $default ) ) {
// Having a default value is not allowed
self::dieDebug( __METHOD__, "Multi-values not supported for $encParamName" );
}
$value = $this->getMain()->getUpload( $encParamName );
+ $provided = $value->exists();
if ( !$value->exists() ) {
// This will get the value without trying to normalize it
// (because trying to normalize a large binary file
}
} else {
$value = $this->getMain()->getVal( $encParamName, $default );
+ $provided = $this->getMain()->getCheck( $encParamName );
if ( isset( $value ) && $type == 'namespace' ) {
$type = MWNamespace::getValidNamespaces();
}
// Set a warning if a deprecated parameter has been passed
- if ( $deprecated && $value !== false ) {
+ if ( $deprecated && $provided ) {
$feature = $encParamName;
$m = $this;
while ( !$m->isMain() ) {
}
// Set a warning if a deprecated parameter value has been passed
- $usedDeprecatedValues = $deprecatedValues && $value !== false
+ $usedDeprecatedValues = $deprecatedValues && $provided
? array_intersect( array_keys( $deprecatedValues ), (array)$value )
: [];
if ( $usedDeprecatedValues ) {
}
}
+ /**
+ * Filter out-of-range values from a list of positive integer IDs
+ * @since 1.33
+ * @param array $fields Array of pairs of table and field to check
+ * @param (string|int)[] $ids IDs to filter. Strings in the array are
+ * expected to be stringified ints.
+ * @return (string|int)[] Filtered IDs.
+ */
+ protected function filterIDs( $fields, array $ids ) {
+ $min = INF;
+ $max = 0;
+ foreach ( $fields as list( $table, $field ) ) {
+ if ( isset( self::$filterIDsCache[$table][$field] ) ) {
+ $row = self::$filterIDsCache[$table][$field];
+ } else {
+ $row = $this->getDB()->selectRow(
+ $table,
+ [
+ 'min_id' => "MIN($field)",
+ 'max_id' => "MAX($field)",
+ ],
+ '',
+ __METHOD__
+ );
+ self::$filterIDsCache[$table][$field] = $row;
+ }
+ $min = min( $min, $row->min_id );
+ $max = max( $max, $row->max_id );
+ }
+ return array_filter( $ids, function ( $id ) use ( $min, $max ) {
+ return ( is_int( $id ) && $id >= 0 || ctype_digit( $id ) )
+ && $id >= $min && $id <= $max;
+ } );
+ }
+
/**@}*/
/************************************************************************//**
* @since 1.29
* @param StatusValue $status
* @param string[] $types 'warning' and/or 'error'
+ * @param string[] $filter Message keys to filter out (since 1.33)
*/
- public function addMessagesFromStatus( StatusValue $status, $types = [ 'warning', 'error' ] ) {
- $this->getErrorFormatter()->addMessagesFromStatus( $this->getModulePath(), $status, $types );
+ public function addMessagesFromStatus(
+ StatusValue $status, $types = [ 'warning', 'error' ], array $filter = []
+ ) {
+ $this->getErrorFormatter()->addMessagesFromStatus(
+ $this->getModulePath(), $status, $types, $filter
+ );
}
/**
foreach ( (array)$actions as $action ) {
$errors = array_merge( $errors, $title->getUserPermissionsErrors( $action, $user ) );
}
+
if ( $errors ) {
+ // track block notices
+ if ( $this->getConfig()->get( 'EnableBlockNoticeStats' ) ) {
+ $this->trackBlockNotices( $errors );
+ }
+
$this->dieStatus( $this->errorArrayToStatus( $errors, $user ) );
}
}
+ /**
+ * Keep track of errors messages resulting from a block
+ *
+ * @param array $errors
+ */
+ private function trackBlockNotices( array $errors ) {
+ $errorMessageKeys = [
+ 'blockedtext',
+ 'blockedtext-partial',
+ 'autoblockedtext',
+ 'systemblockedtext',
+ ];
+
+ $statsd = MediaWikiServices::getInstance()->getStatsdDataFactory();
+
+ foreach ( $errors as $error ) {
+ if ( in_array( $error[0], $errorMessageKeys ) ) {
+ $wiki = $this->getConfig()->get( 'DBname' );
+ $statsd->increment( 'BlockNotices.' . $wiki . '.MediaWikiApi.returned' );
+ break;
+ }
+ }
+ }
+
/**
* Will only set a warning instead of failing if the global $wgDebugAPI
* is set to true. Otherwise behaves exactly as self::dieWithError().