X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2Fapi%2FApiBase.php;h=9ea8c6df4340bdf9a5feacd9e147a4054b685854;hb=e1b2dd4720b88f987bed3a23a1b5ebb2ecc74407;hp=1149d1ea3cb0f71f04f5057434d984fa55a414f4;hpb=dd6b5515bf8d3c10a3161d04a58a4ee701d90b09;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 1149d1ea3c..9ea8c6df43 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -21,6 +21,7 @@ */ use Wikimedia\Rdbms\IDatabase; +use MediaWiki\MediaWikiServices; /** * This abstract class implements many basic API functions, and is the base of @@ -267,6 +268,9 @@ abstract class ApiBase extends ContextSource { /** @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 */ @@ -1831,6 +1835,41 @@ abstract class ApiBase extends ContextSource { } } + /** + * 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)", + ], + null, + __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; + } ); + } + /**@}*/ /************************************************************************//** @@ -2069,11 +2108,41 @@ abstract class ApiBase extends ContextSource { 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().