Merge "FormatJson: cleanup after PHP 5.5 support removal"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sun, 10 Jun 2018 07:58:40 +0000 (07:58 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sun, 10 Jun 2018 07:58:40 +0000 (07:58 +0000)
72 files changed:
RELEASE-NOTES-1.32
includes/Linker.php
includes/MediaWikiServices.php
includes/MergeHistory.php
includes/MovePage.php
includes/OutputPage.php
includes/ServiceWiring.php
includes/SiteConfiguration.php
includes/Storage/RevisionRecord.php
includes/api/ApiQueryLinks.php
includes/api/ApiQueryTokens.php
includes/api/ApiQueryUserContribs.php
includes/auth/ButtonAuthenticationRequest.php
includes/exception/MWExceptionHandler.php
includes/filerepo/RepoGroup.php
includes/htmlform/HTMLForm.php
includes/htmlform/HTMLFormField.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.php
includes/installer/WebInstaller.php
includes/installer/i18n/en.json
includes/installer/i18n/qqq.json
includes/libs/ArrayUtils.php
includes/libs/CryptHKDF.php
includes/libs/CryptRand.php
includes/libs/MemoizedCallable.php
includes/libs/StatusValue.php
includes/libs/StringUtils.php
includes/libs/filebackend/FileBackend.php
includes/libs/filebackend/SwiftFileBackend.php
includes/libs/lockmanager/MemcLockManager.php
includes/libs/lockmanager/RedisLockManager.php
includes/libs/objectcache/CachedBagOStuff.php
includes/libs/objectcache/MultiWriteBagOStuff.php
includes/libs/objectcache/WANObjectCache.php
includes/libs/rdbms/database/DBConnRef.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseSqlite.php
includes/libs/rdbms/lbfactory/LBFactory.php
includes/libs/rdbms/lbfactory/LBFactoryMulti.php
includes/libs/rdbms/lbfactory/LBFactorySimple.php
includes/libs/rdbms/lbfactory/LBFactorySingle.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
includes/libs/redis/RedisConnRef.php
includes/logging/LogEventsList.php
includes/media/BitmapHandler.php
includes/media/SvgHandler.php
includes/page/Article.php
includes/parser/Parser.php
includes/parser/ParserDiffTest.php
includes/parser/ParserOutput.php
includes/password/BcryptPassword.php
includes/password/EncryptedPassword.php
includes/password/Pbkdf2Password.php
includes/poolcounter/PoolCounterWorkViaCallback.php
includes/resourceloader/ResourceLoaderContext.php
includes/services/ServiceContainer.php
includes/session/Session.php
includes/skins/BaseTemplate.php
includes/specialpage/AuthManagerSpecialPage.php
includes/specialpage/ChangesListSpecialPage.php
includes/specialpage/LoginSignupSpecialPage.php
includes/specialpage/SpecialPage.php
includes/specials/SpecialBlock.php
includes/upload/UploadBase.php
includes/upload/UploadFromChunks.php
includes/utils/MWCryptRand.php
maintenance/backup.inc
maintenance/storage/recompressTracked.php
tests/phan/config.php
tests/phpunit/includes/session/SessionTest.php
tests/phpunit/mocks/MockMessageLocalizer.php

index 4e2bdfa..cdc2582 100644 (file)
@@ -186,6 +186,9 @@ because of Phabricator reports.
 * The ApiQueryContributions class has been renamed to ApiQueryUserContribs.
 * The XMPInfo, XMPReader, and XMPValidate classes have been deprecated in favor
   of the namespaced classes provided by the wikimedia/xmp-reader library.
+* Class CryptRand, everything in MWCryptRand except generateHex() and function
+  MediaWikiServices::getCryptRand() are deprecated, use random_bytes() to
+  generate cryptographically secure random byte sequences.
 
 === Other changes in 1.32 ===
 * …
index 6634127..9638502 100644 (file)
@@ -826,7 +826,7 @@ class Linker {
                        $key = strtolower( $name );
                }
 
-               return self::linkKnown( SpecialPage::getTitleFor( $name ), wfMessage( $key )->text() );
+               return self::linkKnown( SpecialPage::getTitleFor( $name ), wfMessage( $key )->escaped() );
        }
 
        /**
index ac98683..dbb18a7 100644 (file)
@@ -539,6 +539,7 @@ class MediaWikiServices extends ServiceContainer {
 
        /**
         * @since 1.28
+        * @deprecated since 1.32, use random_bytes()/random_int()
         * @return CryptRand
         */
        public function getCryptRand() {
index 0e9bb46..4c655eb 100644 (file)
@@ -167,7 +167,7 @@ class MergeHistory {
                // Convert into a Status object
                if ( $errors ) {
                        foreach ( $errors as $error ) {
-                               call_user_func_array( [ $status, 'fatal' ], $error );
+                               $status->fatal( ...$error );
                        }
                }
 
index 1e9570d..614ea7d 100644 (file)
@@ -57,7 +57,7 @@ class MovePage {
                // Convert into a Status object
                if ( $errors ) {
                        foreach ( $errors as $error ) {
-                               call_user_func_array( [ $status, 'fatal' ], $error );
+                               $status->fatal( ...$error );
                        }
                }
 
index c51f6f8..6700cdb 100644 (file)
@@ -2645,13 +2645,13 @@ class OutputPage extends ContextSource {
 
                        foreach ( $errors as $error ) {
                                $text .= '<li>';
-                               $text .= call_user_func_array( [ $this, 'msg' ], $error )->plain();
+                               $text .= $this->msg( ...$error )->plain();
                                $text .= "</li>\n";
                        }
                        $text .= '</ul>';
                } else {
                        $text .= "<div class=\"permissions-errors\">\n" .
-                                       call_user_func_array( [ $this, 'msg' ], reset( $errors ) )->plain() .
+                                       $this->msg( ...reset( $errors ) )->plain() .
                                        "\n</div>";
                }
 
@@ -4018,8 +4018,8 @@ class OutputPage extends ContextSource {
                }
                if ( $this->CSPNonce === null ) {
                        // XXX It might be expensive to generate randomness
-                       // on every request, on windows.
-                       $rand = MWCryptRand::generate( 15 );
+                       // on every request, on Windows.
+                       $rand = random_bytes( 15 );
                        $this->CSPNonce = base64_encode( $rand );
                }
                return $this->CSPNonce;
index ace64ab..3f8ba18 100644 (file)
@@ -188,29 +188,8 @@ return [
                );
        },
 
-       'CryptRand' => function ( MediaWikiServices $services ) {
-               $secretKey = $services->getMainConfig()->get( 'SecretKey' );
-               return new CryptRand(
-                       [
-                               // To try vary the system information of the state a bit more
-                               // by including the system's hostname into the state
-                               'wfHostname',
-                               // It's mostly worthless but throw the wiki's id into the data
-                               // for a little more variance
-                               'wfWikiID',
-                               // If we have a secret key set then throw it into the state as well
-                               function () use ( $secretKey ) {
-                                       return $secretKey ?: '';
-                               }
-                       ],
-                       // The config file is likely the most often edited file we know should
-                       // be around so include its stat info into the state.
-                       // The constant with its location will almost always be defined, as
-                       // WebStart.php defines MW_CONFIG_FILE to $IP/LocalSettings.php unless
-                       // being configured with MW_CONFIG_CALLBACK (e.g. the installer).
-                       defined( 'MW_CONFIG_FILE' ) ? [ MW_CONFIG_FILE ] : [],
-                       LoggerFactory::getInstance( 'CryptRand' )
-               );
+       'CryptRand' => function () {
+               return new CryptRand();
        },
 
        'CryptHKDF' => function ( MediaWikiServices $services ) {
@@ -231,9 +210,7 @@ return [
                        $cache = ObjectCache::getLocalClusterInstance();
                }
 
-               return new CryptHKDF( $secret, $config->get( 'HKDFAlgorithm' ),
-                       $cache, $context, $services->getCryptRand()
-               );
+               return new CryptHKDF( $secret, $config->get( 'HKDFAlgorithm' ), $cache, $context );
        },
 
        'MediaHandlerFactory' => function ( MediaWikiServices $services ) {
index 6bd179a..8e77956 100644 (file)
@@ -432,7 +432,7 @@ class SiteConfiguration {
                        return $default;
                }
 
-               $ret = call_user_func_array( $this->siteParamsCallback, [ $this, $wiki ] );
+               $ret = ( $this->siteParamsCallback )( $this, $wiki );
                # Validate the returned value
                if ( !is_array( $ret ) ) {
                        return $default;
@@ -606,7 +606,7 @@ class SiteConfiguration {
 
        public function loadFullData() {
                if ( $this->fullLoadCallback && !$this->fullLoadDone ) {
-                       call_user_func( $this->fullLoadCallback, $this );
+                       ( $this->fullLoadCallback )( $this );
                        $this->fullLoadDone = true;
                }
        }
index ff0a70d..66ec2c0 100644 (file)
@@ -474,7 +474,7 @@ abstract class RevisionRecord {
                        $permissionlist = implode( ', ', $permissions );
                        if ( $title === null ) {
                                wfDebug( "Checking for $permissionlist due to $field match on $bitfield\n" );
-                               return call_user_func_array( [ $user, 'isAllowedAny' ], $permissions );
+                               return $user->isAllowedAny( ...$permissions );
                        } else {
                                $text = $title->getPrefixedText();
                                wfDebug( "Checking for $permissionlist on $text due to $field match on $bitfield\n" );
index 67bf619..144c758 100644 (file)
@@ -103,7 +103,7 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
                        if ( $cond ) {
                                $this->addWhere( $cond );
                                $multiNS = count( $lb->data ) !== 1;
-                               $multiTitle = count( call_user_func_array( 'array_merge', $lb->data ) ) !== 1;
+                               $multiTitle = count( array_merge( ...$lb->data ) ) !== 1;
                        } else {
                                // No titles so no results
                                return;
index e86fdf3..8854aac 100644 (file)
@@ -94,7 +94,7 @@ class ApiQueryTokens extends ApiQueryBase {
        public static function getToken( User $user, MediaWiki\Session\Session $session, $salt ) {
                if ( is_array( $salt ) ) {
                        $session->persist();
-                       return call_user_func_array( [ $session, 'getToken' ], $salt );
+                       return $session->getToken( ...$salt );
                } else {
                        return $user->getEditTokenObject( $salt, $session->getRequest() );
                }
index 420d138..fdcaa76 100644 (file)
@@ -306,9 +306,11 @@ class ApiQueryUserContribs extends ApiQueryBase {
                                foreach ( $res as $row ) {
                                        $names[$row->user_name] = $row;
                                }
-                               call_user_func_array(
-                                       $this->params['dir'] == 'newer' ? 'ksort' : 'krsort', [ &$names, SORT_STRING ]
-                               );
+                               if ( $this->params['dir'] == 'newer' ) {
+                                       ksort( $names, SORT_STRING );
+                               } else {
+                                       krsort( $names, SORT_STRING );
+                               }
                                $neg = $op === '>' ? -1 : 1;
                                $userIter = call_user_func( function () use ( $names, $fromName, $neg ) {
                                        foreach ( $names as $name => $row ) {
index d274e18..1268e68 100644 (file)
@@ -90,14 +90,14 @@ class ButtonAuthenticationRequest extends AuthenticationRequest {
                } elseif ( is_string( $data['label'] ) ) {
                        $data['label'] = new \Message( $data['label'] );
                } elseif ( is_array( $data['label'] ) ) {
-                       $data['label'] = call_user_func_array( 'Message::newFromKey', $data['label'] );
+                       $data['label'] = Message::newFromKey( ...$data['label'] );
                }
                if ( !isset( $data['help'] ) ) {
                        $data['help'] = new \RawMessage( '$1', $data['name'] );
                } elseif ( is_string( $data['help'] ) ) {
                        $data['help'] = new \Message( $data['help'] );
                } elseif ( is_array( $data['help'] ) ) {
-                       $data['help'] = call_user_func_array( 'Message::newFromKey', $data['help'] );
+                       $data['help'] = Message::newFromKey( ...$data['help'] );
                }
                $ret = new static( $data['name'], $data['label'], $data['help'] );
                foreach ( $data as $k => $v ) {
index 79f0a23..9039cfc 100644 (file)
@@ -173,9 +173,7 @@ class MWExceptionHandler {
                global $wgPropagateErrors;
 
                if ( in_array( $level, self::$fatalErrorTypes ) ) {
-                       return call_user_func_array(
-                               'MWExceptionHandler::handleFatalError', func_get_args()
-                       );
+                       return self::handleFatalError( ...func_get_args() );
                }
 
                // Map error constant to error name (reverse-engineer PHP error
index 0056181..7dd8b25 100644 (file)
@@ -372,8 +372,7 @@ class RepoGroup {
                        $this->initialiseRepos();
                }
                foreach ( $this->foreignRepos as $repo ) {
-                       $args = array_merge( [ $repo ], $params );
-                       if ( call_user_func_array( $callback, $args ) ) {
+                       if ( $callback( $repo, ...$params ) ) {
                                return true;
                        }
                }
index 785d30f..e72faa0 100644 (file)
@@ -607,7 +607,7 @@ class HTMLForm extends ContextSource {
                $hoistedErrors = Status::newGood();
                if ( $this->mValidationErrorMessage ) {
                        foreach ( (array)$this->mValidationErrorMessage as $error ) {
-                               call_user_func_array( [ $hoistedErrors, 'fatal' ], $error );
+                               $hoistedErrors->fatal( ...$error );
                        }
                } else {
                        $hoistedErrors->fatal( 'htmlform-invalid-input' );
index cd4d4b7..a701575 100644 (file)
@@ -81,12 +81,9 @@ abstract class HTMLFormField {
                $args = func_get_args();
 
                if ( $this->mParent ) {
-                       $callback = [ $this->mParent, 'msg' ];
-               } else {
-                       $callback = 'wfMessage';
+                       return $this->mParent->msg( ...$args );
                }
-
-               return call_user_func_array( $callback, $args );
+               return wfMessage( ...$args );
        }
 
        /**
@@ -315,7 +312,7 @@ abstract class HTMLFormField {
                }
 
                if ( isset( $this->mValidationCallback ) ) {
-                       return call_user_func( $this->mValidationCallback, $value, $alldata, $this->mParent );
+                       return ( $this->mValidationCallback )( $value, $alldata, $this->mParent );
                }
 
                return true;
@@ -323,7 +320,7 @@ abstract class HTMLFormField {
 
        public function filter( $value, $alldata ) {
                if ( isset( $this->mFilterCallback ) ) {
-                       $value = call_user_func( $this->mFilterCallback, $value, $alldata, $this->mParent );
+                       $value = ( $this->mFilterCallback )( $value, $alldata, $this->mParent );
                }
 
                return $value;
index 4fc04db..1cd76b9 100644 (file)
@@ -410,9 +410,9 @@ abstract class DatabaseUpdater {
 
                foreach ( $updates as $funcList ) {
                        $func = $funcList[0];
-                       $arg = $funcList[1];
+                       $args = $funcList[1];
                        $origParams = $funcList[2];
-                       call_user_func_array( $func, $arg );
+                       $func( ...$args );
                        flush();
                        $this->updatesSkipped[] = $origParams;
                }
@@ -479,7 +479,7 @@ abstract class DatabaseUpdater {
                        } elseif ( $passSelf ) {
                                array_unshift( $params, $this );
                        }
-                       $ret = call_user_func_array( $func, $params );
+                       $ret = $func( ...$params );
                        flush();
                        if ( $ret !== false ) {
                                $updatesDone[] = $origParams;
index 05da0db..0890bc4 100644 (file)
@@ -1597,23 +1597,11 @@ abstract class Installer {
        protected function doGenerateKeys( $keys ) {
                $status = Status::newGood();
 
-               $strong = true;
                foreach ( $keys as $name => $length ) {
-                       $secretKey = MWCryptRand::generateHex( $length, true );
-                       if ( !MWCryptRand::wasStrong() ) {
-                               $strong = false;
-                       }
-
+                       $secretKey = MWCryptRand::generateHex( $length );
                        $this->setVar( $name, $secretKey );
                }
 
-               if ( !$strong ) {
-                       $names = array_keys( $keys );
-                       $names = preg_replace( '/^(.*)$/', '\$$1', $names );
-                       global $wgLang;
-                       $status->warning( 'config-insecure-keys', $wgLang->listToText( $names ), count( $names ) );
-               }
-
                return $status;
        }
 
index 8fb9807..306afc4 100644 (file)
@@ -717,7 +717,7 @@ class WebInstaller extends Installer {
         */
        public function showHelpBox( $msg /*, ... */ ) {
                $args = func_get_args();
-               $html = call_user_func_array( [ $this, 'getHelpBox' ], $args );
+               $html = $this->getHelpBox( ...$args );
                $this->output->addHTML( $html );
        }
 
@@ -742,7 +742,7 @@ class WebInstaller extends Installer {
        public function showStatusMessage( Status $status ) {
                $errors = array_merge( $status->getErrorsArray(), $status->getWarningsArray() );
                foreach ( $errors as $error ) {
-                       call_user_func_array( [ $this, 'showMessage' ], $error );
+                       $this->showMessage( ...$error );
                }
        }
 
index 005fef6..dbc1849 100644 (file)
        "config-install-interwiki-exists": "<strong>Warning:</strong> The interwiki table seems to already have entries.\nSkipping default list.",
        "config-install-stats": "Initializing statistics",
        "config-install-keys": "Generating secret keys",
-       "config-insecure-keys": "<strong>Warning:</strong> {{PLURAL:$2|A secure key|Secure keys}} ($1) generated during installation {{PLURAL:$2|is|are}} not completely safe. Consider changing {{PLURAL:$2|it|them}} manually.",
        "config-install-updates": "Prevent running unneeded updates",
        "config-install-updates-failed": "<strong>Error:</strong> Inserting update keys into tables failed with the following error: $1",
        "config-install-sysop": "Creating administrator user account",
index 0779204..d9edde5 100644 (file)
        "config-install-interwiki-exists": "Error notice during the installation saying that one of the database tables is already set up, so it's continuing without taking that step.",
        "config-install-stats": "*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
        "config-install-keys": "*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
-       "config-insecure-keys": "Parameters:\n* $1 - A list of names of the secret keys that were generated.\n* $2 - the number of items in the list $1, to be used with PLURAL.",
        "config-install-updates": "Message indicating that the updatelog table is filled with keys of updates that won't be run when running database updates.\n\nSee also:\n*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-updates}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
        "config-install-updates-failed": "Used as error message. Parameters:\n* $1 - detailed error message",
        "config-install-sysop": "Message indicates that the administrator user account is being created\n\nSee also:\n*{{msg-mw|Config-install-database}}\n*{{msg-mw|Config-install-tables}}\n*{{msg-mw|Config-install-schema}}\n*{{msg-mw|Config-install-user}}\n*{{msg-mw|Config-install-interwiki}}\n*{{msg-mw|Config-install-stats}}\n*{{msg-mw|Config-install-keys}}\n*{{msg-mw|Config-install-sysop}}\n*{{msg-mw|Config-install-mainpage}}",
index 0413ea0..e238887 100644 (file)
@@ -120,8 +120,8 @@ class ArrayUtils {
                $max = $valueCount;
                do {
                        $mid = $min + ( ( $max - $min ) >> 1 );
-                       $item = call_user_func( $valueCallback, $mid );
-                       $comparison = call_user_func( $comparisonCallback, $target, $item );
+                       $item = $valueCallback( $mid );
+                       $comparison = $comparisonCallback( $target, $item );
                        if ( $comparison > 0 ) {
                                $min = $mid;
                        } elseif ( $comparison == 0 ) {
@@ -133,8 +133,8 @@ class ArrayUtils {
                } while ( $min < $max - 1 );
 
                if ( $min == 0 ) {
-                       $item = call_user_func( $valueCallback, $min );
-                       $comparison = call_user_func( $comparisonCallback, $target, $item );
+                       $item = $valueCallback( $min );
+                       $comparison = $comparisonCallback( $target, $item );
                        if ( $comparison < 0 ) {
                                // Before the first item
                                return false;
@@ -168,7 +168,7 @@ class ArrayUtils {
                                                $args[] = $array[$key];
                                        }
                                }
-                               $valueret = call_user_func_array( __METHOD__, $args );
+                               $valueret = self::arrayDiffAssocRecursive( ...$args );
                                if ( count( $valueret ) ) {
                                        $ret[$key] = $valueret;
                                }
index c41aab3..0478a33 100644 (file)
@@ -99,22 +99,14 @@ class CryptHKDF {
                'whirlpool' => 64,
        ];
 
-       /**
-        * @var CryptRand
-        */
-       private $cryptRand;
-
        /**
         * @param string $secretKeyMaterial
         * @param string $algorithm Name of hashing algorithm
         * @param BagOStuff $cache
         * @param string|array $context Context to mix into HKDF context
-        * @param CryptRand $cryptRand
         * @throws InvalidArgumentException if secret key material is too short
         */
-       public function __construct( $secretKeyMaterial, $algorithm, BagOStuff $cache, $context,
-               CryptRand $cryptRand
-       ) {
+       public function __construct( $secretKeyMaterial, $algorithm, BagOStuff $cache, $context ) {
                if ( strlen( $secretKeyMaterial ) < 16 ) {
                        throw new InvalidArgumentException( "secret was too short." );
                }
@@ -122,7 +114,6 @@ class CryptHKDF {
                $this->algorithm = $algorithm;
                $this->cache = $cache;
                $this->context = is_array( $context ) ? $context : [ $context ];
-               $this->cryptRand = $cryptRand;
 
                // To prevent every call from hitting the same memcache server, pick
                // from a set of keys to use. mt_rand is only use to pick a random
@@ -150,12 +141,12 @@ class CryptHKDF {
                        $lastSalt = $this->cache->get( $this->cacheKey );
                        if ( $lastSalt === false ) {
                                // If we don't have a previous value to use as our salt, we use
-                               // 16 bytes from CryptRand, which will use a small amount of
+                               // 16 bytes from random_bytes(), which will use a small amount of
                                // entropy from our pool. Note, "XTR may be deterministic or keyed
                                // via an optional “salt value”  (i.e., a non-secret random
                                // value)..." - http://eprint.iacr.org/2010/264.pdf. However, we
                                // use a strongly random value since we can.
-                               $lastSalt = $this->cryptRand->generate( 16 );
+                               $lastSalt = random_bytes( 16 );
                        }
                        // Get a binary string that is hashLen long
                        $this->salt = hash( $this->algorithm, $lastSalt, true );
index f7702dd..a1bbd09 100644 (file)
  * @author Daniel Friesen
  * @file
  */
-use Psr\Log\LoggerInterface;
 
+/**
+ * @deprecated since 1.32, use random_bytes()/random_int()
+ */
 class CryptRand {
        /**
-        * Minimum number of iterations we want to make in our drift calculations.
+        * @deprecated since 1.32, unused
         */
        const MIN_ITERATIONS = 1000;
 
        /**
-        * Number of milliseconds we want to spend generating each separate byte
-        * of the final generated bytes.
-        * This is used in combination with the hash length to determine the duration
-        * we should spend doing drift calculations.
+        * @deprecated since 1.32, unused
         */
        const MSEC_PER_BYTE = 0.5;
 
        /**
-        * A boolean indicating whether the previous random generation was done using
-        * cryptographically strong random number generator or not.
-        */
-       protected $strong = null;
-
-       /**
-        * List of functions to call to generate some random state
+        * Initialize an initial random state based off of whatever we can find
         *
-        * @var callable[]
-        */
-       protected $randomFuncs = [];
-
-       /**
-        * List of files to generate some random state from
+        * @deprecated since 1.32, unused and does nothing
         *
-        * @var string[]
-        */
-       protected $randomFiles = [];
-
-       /**
-        * @var LoggerInterface
-        */
-       protected $logger;
-
-       public function __construct( array $randomFuncs, array $randomFiles, LoggerInterface $logger ) {
-               $this->randomFuncs = $randomFuncs;
-               $this->randomFiles = $randomFiles;
-               $this->logger = $logger;
-       }
-
-       /**
-        * Initialize an initial random state based off of whatever we can find
         * @return string
         */
        protected function initialRandomState() {
-               // $_SERVER contains a variety of unstable user and system specific information
-               // It'll vary a little with each page, and vary even more with separate users
-               // It'll also vary slightly across different machines
-               $state = serialize( $_SERVER );
-
-               // Try to gather a little entropy from the different php rand sources
-               $state .= rand() . uniqid( mt_rand(), true );
-
-               // Include some information about the filesystem's current state in the random state
-               $files = $this->randomFiles;
-
-               // We know this file is here so grab some info about ourselves
-               $files[] = __FILE__;
-
-               // We must also have a parent folder, and with the usual file structure, a grandparent
-               $files[] = __DIR__;
-               $files[] = dirname( __DIR__ );
-
-               foreach ( $files as $file ) {
-                       Wikimedia\suppressWarnings();
-                       $stat = stat( $file );
-                       Wikimedia\restoreWarnings();
-                       if ( $stat ) {
-                               // stat() duplicates data into numeric and string keys so kill off all the numeric ones
-                               foreach ( $stat as $k => $v ) {
-                                       if ( is_numeric( $k ) ) {
-                                               unset( $k );
-                                       }
-                               }
-                               // The absolute filename itself will differ from install to install so don't leave it out
-                               $path = realpath( $file );
-                               if ( $path !== false ) {
-                                       $state .= $path;
-                               } else {
-                                       $state .= $file;
-                               }
-                               $state .= implode( '', $stat );
-                       } else {
-                               // The fact that the file isn't there is worth at least a
-                               // minuscule amount of entropy.
-                               $state .= '0';
-                       }
-               }
-
-               // Try and make this a little more unstable by including the varying process
-               // id of the php process we are running inside of if we are able to access it
-               if ( function_exists( 'getmypid' ) ) {
-                       $state .= getmypid();
-               }
-
-               // If available try to increase the instability of the data by throwing in
-               // the precise amount of memory that we happen to be using at the moment.
-               if ( function_exists( 'memory_get_usage' ) ) {
-                       $state .= memory_get_usage( true );
-               }
-
-               foreach ( $this->randomFuncs as $randomFunc ) {
-                       $state .= call_user_func( $randomFunc );
-               }
-
-               return $state;
+               return '';
        }
 
        /**
         * Randomly hash data while mixing in clock drift data for randomness
         *
+        * @deprecated since 1.32, unused and does nothing
+        *
         * @param string $data The data to randomly hash.
         * @return string The hashed bytes
         * @author Tim Starling
         */
        protected function driftHash( $data ) {
-               // Minimum number of iterations (to avoid slow operations causing the
-               // loop to gather little entropy)
-               $minIterations = self::MIN_ITERATIONS;
-               // Duration of time to spend doing calculations (in seconds)
-               $duration = ( self::MSEC_PER_BYTE / 1000 ) * MWCryptHash::hashLength();
-               // Create a buffer to use to trigger memory operations
-               $bufLength = 10000000;
-               $buffer = str_repeat( ' ', $bufLength );
-               $bufPos = 0;
-
-               // Iterate for $duration seconds or at least $minIterations number of iterations
-               $iterations = 0;
-               $startTime = microtime( true );
-               $currentTime = $startTime;
-               while ( $iterations < $minIterations || $currentTime - $startTime < $duration ) {
-                       // Trigger some memory writing to trigger some bus activity
-                       // This may create variance in the time between iterations
-                       $bufPos = ( $bufPos + 13 ) % $bufLength;
-                       $buffer[$bufPos] = ' ';
-                       // Add the drift between this iteration and the last in as entropy
-                       $nextTime = microtime( true );
-                       $delta = (int)( ( $nextTime - $currentTime ) * 1000000 );
-                       $data .= $delta;
-                       // Every 100 iterations hash the data and entropy
-                       if ( $iterations % 100 === 0 ) {
-                               $data = sha1( $data );
-                       }
-                       $currentTime = $nextTime;
-                       $iterations++;
-               }
-               $timeTaken = $currentTime - $startTime;
-               $data = MWCryptHash::hash( $data );
-
-               $this->logger->debug( "Clock drift calculation " .
-                       "(time-taken=" . ( $timeTaken * 1000 ) . "ms, " .
-                       "iterations=$iterations, " .
-                       "time-per-iteration=" . ( $timeTaken / $iterations * 1e6 ) . "us)" );
-
-               return $data;
+               return '';
        }
 
        /**
         * Return a rolling random state initially build using data from unstable sources
+        *
+        * @deprecated since 1.32, unused and does nothing
+        *
         * @return string A new weak random state
         */
        protected function randomState() {
-               static $state = null;
-               if ( is_null( $state ) ) {
-                       // Initialize the state with whatever unstable data we can find
-                       // It's important that this data is hashed right afterwards to prevent
-                       // it from being leaked into the output stream
-                       $state = MWCryptHash::hash( $this->initialRandomState() );
-               }
-               // Generate a new random state based on the initial random state or previous
-               // random state by combining it with clock drift
-               $state = $this->driftHash( $state );
-
-               return $state;
+               return '';
        }
 
        /**
@@ -211,191 +78,36 @@ class CryptRand {
         * random bytes generation in the previously run generate* call
         * was cryptographically strong.
         *
-        * @return bool Returns true if the source was strong, false if not.
+        * @deprecated since 1.32, always returns true
+        *
+        * @return bool Always true
         */
        public function wasStrong() {
-               if ( is_null( $this->strong ) ) {
-                       throw new RuntimeException( __METHOD__ . ' called before generation of random data' );
-               }
-
-               return $this->strong;
+               return true;
        }
 
        /**
-        * Generate a run of (ideally) cryptographically random data and return
+        * Generate a run of cryptographically random data and return
         * it in raw binary form.
         * You can use CryptRand::wasStrong() if you wish to know if the source used
         * was cryptographically strong.
         *
         * @param int $bytes The number of bytes of random data to generate
-        * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
-        *                          strong sources of entropy even if reading from them may steal
-        *                          more entropy from the system than optimal.
         * @return string Raw binary random data
         */
-       public function generate( $bytes, $forceStrong = false ) {
+       public function generate( $bytes ) {
                $bytes = floor( $bytes );
-               static $buffer = '';
-               if ( is_null( $this->strong ) ) {
-                       // Set strength to false initially until we know what source data is coming from
-                       $this->strong = true;
-               }
-
-               if ( strlen( $buffer ) < $bytes ) {
-                       // If available make use of PHP 7's random_bytes
-                       // On Linux, getrandom syscall will be used if available.
-                       // On Windows CryptGenRandom will always be used
-                       // On other platforms, /dev/urandom will be used.
-                       // Avoids polyfills from before php 7.0
-                       // All error situations will throw Exceptions and or Errors
-                       if ( PHP_VERSION_ID >= 70000
-                               || ( defined( 'HHVM_VERSION_ID' ) && HHVM_VERSION_ID >= 31101 )
-                       ) {
-                               $rem = $bytes - strlen( $buffer );
-                               $buffer .= random_bytes( $rem );
-                       }
-                       if ( strlen( $buffer ) >= $bytes ) {
-                               $this->strong = true;
-                       }
-               }
-
-               if ( strlen( $buffer ) < $bytes && function_exists( 'mcrypt_create_iv' ) ) {
-                       // If available make use of mcrypt_create_iv URANDOM source to generate randomness
-                       // On unix-like systems this reads from /dev/urandom but does it without any buffering
-                       // and bypasses openbasedir restrictions, so it's preferable to reading directly
-                       // On Windows starting in PHP 5.3.0 Windows' native CryptGenRandom is used to generate
-                       // entropy so this is also preferable to just trying to read urandom because it may work
-                       // on Windows systems as well.
-                       $rem = $bytes - strlen( $buffer );
-                       $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM );
-                       if ( $iv === false ) {
-                               $this->logger->debug( "mcrypt_create_iv returned false." );
-                       } else {
-                               $buffer .= $iv;
-                               $this->logger->debug( "mcrypt_create_iv generated " . strlen( $iv ) .
-                                       " bytes of randomness." );
-                       }
-               }
-
-               if ( strlen( $buffer ) < $bytes && function_exists( 'openssl_random_pseudo_bytes' ) ) {
-                       $rem = $bytes - strlen( $buffer );
-                       $openssl_strong = false;
-                       $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong );
-                       if ( $openssl_bytes === false ) {
-                               $this->logger->debug( "openssl_random_pseudo_bytes returned false." );
-                       } else {
-                               $buffer .= $openssl_bytes;
-                               $this->logger->debug( "openssl_random_pseudo_bytes generated " .
-                                       strlen( $openssl_bytes ) . " bytes of " .
-                                       ( $openssl_strong ? "strong" : "weak" ) . " randomness." );
-                       }
-                       if ( strlen( $buffer ) >= $bytes ) {
-                               // openssl tells us if the random source was strong, if some of our data was generated
-                               // using it use it's say on whether the randomness is strong
-                               $this->strong = !!$openssl_strong;
-                       }
-               }
-
-               // Only read from urandom if we can control the buffer size or were passed forceStrong
-               if ( strlen( $buffer ) < $bytes &&
-                       ( function_exists( 'stream_set_read_buffer' ) || $forceStrong )
-               ) {
-                       $rem = $bytes - strlen( $buffer );
-                       if ( !function_exists( 'stream_set_read_buffer' ) && $forceStrong ) {
-                               $this->logger->debug( "Was forced to read from /dev/urandom " .
-                                       "without control over the buffer size." );
-                       }
-                       // /dev/urandom is generally considered the best possible commonly
-                       // available random source, and is available on most *nix systems.
-                       Wikimedia\suppressWarnings();
-                       $urandom = fopen( "/dev/urandom", "rb" );
-                       Wikimedia\restoreWarnings();
-
-                       // Attempt to read all our random data from urandom
-                       // php's fread always does buffered reads based on the stream's chunk_size
-                       // so in reality it will usually read more than the amount of data we're
-                       // asked for and not storing that risks depleting the system's random pool.
-                       // If stream_set_read_buffer is available set the chunk_size to the amount
-                       // of data we need. Otherwise read 8k, php's default chunk_size.
-                       if ( $urandom ) {
-                               // php's default chunk_size is 8k
-                               $chunk_size = 1024 * 8;
-                               if ( function_exists( 'stream_set_read_buffer' ) ) {
-                                       // If possible set the chunk_size to the amount of data we need
-                                       stream_set_read_buffer( $urandom, $rem );
-                                       $chunk_size = $rem;
-                               }
-                               $random_bytes = fread( $urandom, max( $chunk_size, $rem ) );
-                               $buffer .= $random_bytes;
-                               fclose( $urandom );
-                               $this->logger->debug( "/dev/urandom generated " . strlen( $random_bytes ) .
-                                       " bytes of randomness." );
-
-                               if ( strlen( $buffer ) >= $bytes ) {
-                                       // urandom is always strong, set to true if all our data was generated using it
-                                       $this->strong = true;
-                               }
-                       } else {
-                               $this->logger->debug( "/dev/urandom could not be opened." );
-                       }
-               }
-
-               // If we cannot use or generate enough data from a secure source
-               // use this loop to generate a good set of pseudo random data.
-               // This works by initializing a random state using a pile of unstable data
-               // and continually shoving it through a hash along with a variable salt.
-               // We hash the random state with more salt to avoid the state from leaking
-               // out and being used to predict the /randomness/ that follows.
-               if ( strlen( $buffer ) < $bytes ) {
-                       $this->logger->debug( __METHOD__ .
-                               ": Falling back to using a pseudo random state to generate randomness." );
-               }
-               while ( strlen( $buffer ) < $bytes ) {
-                       $buffer .= MWCryptHash::hmac( $this->randomState(), strval( mt_rand() ) );
-                       // This code is never really cryptographically strong, if we use it
-                       // at all, then set strong to false.
-                       $this->strong = false;
-               }
-
-               // Once the buffer has been filled up with enough random data to fulfill
-               // the request shift off enough data to handle the request and leave the
-               // unused portion left inside the buffer for the next request for random data
-               $generated = substr( $buffer, 0, $bytes );
-               $buffer = substr( $buffer, $bytes );
-
-               $this->logger->debug( strlen( $buffer ) .
-                       " bytes of randomness leftover in the buffer." );
-
-               return $generated;
+               return random_bytes( $bytes );
        }
 
        /**
-        * Generate a run of (ideally) cryptographically random data and return
+        * Generate a run of cryptographically random data and return
         * it in hexadecimal string format.
-        * You can use CryptRand::wasStrong() if you wish to know if the source used
-        * was cryptographically strong.
         *
         * @param int $chars The number of hex chars of random data to generate
-        * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
-        *                          strong sources of entropy even if reading from them may steal
-        *                          more entropy from the system than optimal.
         * @return string Hexadecimal random data
         */
-       public function generateHex( $chars, $forceStrong = false ) {
-               // hex strings are 2x the length of raw binary so we divide the length in half
-               // odd numbers will result in a .5 that leads the generate() being 1 character
-               // short, so we use ceil() to ensure that we always have enough bytes
-               $bytes = ceil( $chars / 2 );
-               // Generate the data and then convert it to a hex string
-               $hex = bin2hex( $this->generate( $bytes, $forceStrong ) );
-
-               // A bit of paranoia here, the caller asked for a specific length of string
-               // here, and it's possible (eg when given an odd number) that we may actually
-               // have at least 1 char more than they asked for. Just in case they made this
-               // call intending to insert it into a database that does truncation we don't
-               // want to give them too much and end up with their database and their live
-               // code having two different values because part of what we gave them is truncated
-               // hence, we strip out any run of characters longer than what we were asked for.
-               return substr( $hex, 0, $chars );
+       public function generateHex( $chars ) {
+               return MWCryptRand::generateHex( $chars );
        }
 }
index 14462f1..e9d1fc1 100644 (file)
@@ -123,7 +123,7 @@ class MemoizedCallable {
                $success = false;
                $result = $this->fetchResult( $key, $success );
                if ( !$success ) {
-                       $result = call_user_func_array( $this->callable, $args );
+                       $result = ( $this->callable )( ...$args );
                        $this->storeResult( $key, $result );
                }
 
index 6f348c2..3bdafe1 100644 (file)
@@ -68,7 +68,7 @@ class StatusValue {
        public static function newFatal( $message /*, parameters...*/ ) {
                $params = func_get_args();
                $result = new static();
-               call_user_func_array( [ &$result, 'fatal' ], $params );
+               $result->fatal( ...$params );
                return $result;
        }
 
index 7915ccf..d91ac85 100644 (file)
@@ -206,7 +206,7 @@ class StringUtils {
                        } elseif ( $tokenType == 'end' ) {
                                if ( $foundStart ) {
                                        # Found match
-                                       $output .= call_user_func( $callback, [
+                                       $output .= $callback( [
                                                substr( $subject, $outputPos, $tokenOffset + $tokenLength - $outputPos ),
                                                substr( $subject, $contentPos, $tokenOffset - $contentPos )
                                        ] );
index 2d4a772..785cb72 100644 (file)
@@ -1590,7 +1590,7 @@ abstract class FileBackend implements LoggerAwareInterface {
        final protected function newStatus() {
                $args = func_get_args();
                if ( count( $args ) ) {
-                       $sv = call_user_func_array( [ StatusValue::class, 'newFatal' ], $args );
+                       $sv = StatusValue::newFatal( ...$args );
                } else {
                        $sv = StatusValue::newGood();
                }
index 3cd973e..2f7bc1e 100644 (file)
@@ -1103,7 +1103,7 @@ class SwiftFileBackend extends FileBackendStore {
 
                if ( empty( $params['allowOB'] ) ) {
                        // Cancel output buffering and gzipping if set
-                       call_user_func( $this->obResetFunc );
+                       ( $this->obResetFunc )();
                }
 
                $handle = fopen( 'php://output', 'wb' );
@@ -1317,7 +1317,7 @@ class SwiftFileBackend extends FileBackendStore {
                        foreach ( $httpReqs as $index => $httpReq ) {
                                // Run the callback for each request of this operation
                                $callback = $fileOpHandles[$index]->callback;
-                               call_user_func_array( $callback, [ $httpReq, $statuses[$index] ] );
+                               $callback( $httpReq, $statuses[$index] );
                                // On failure, abort all remaining requests for this operation
                                // (e.g. abort the DELETE request if the COPY request fails for a move)
                                if ( !$statuses[$index]->isOK() ) {
index ebd72de..f1f749f 100644 (file)
@@ -89,7 +89,7 @@ class MemcLockManager extends QuorumLockManager {
 
                $memc = $this->getCache( $lockSrv );
                // List of affected paths
-               $paths = call_user_func_array( 'array_merge', array_values( $pathsByType ) );
+               $paths = array_merge( ...array_values( $pathsByType ) );
                $paths = array_unique( $paths );
                // List of affected lock record keys
                $keys = array_map( [ $this, 'recordKeyForPath' ], $paths );
@@ -164,7 +164,7 @@ class MemcLockManager extends QuorumLockManager {
 
                $memc = $this->getCache( $lockSrv );
                // List of affected paths
-               $paths = call_user_func_array( 'array_merge', array_values( $pathsByType ) );
+               $paths = array_merge( ...array_values( $pathsByType ) );
                $paths = array_unique( $paths );
                // List of affected lock record keys
                $keys = array_map( [ $this, 'recordKeyForPath' ], $paths );
index ea9dde7..a624f0a 100644 (file)
@@ -76,7 +76,7 @@ class RedisLockManager extends QuorumLockManager {
        protected function getLocksOnServer( $lockSrv, array $pathsByType ) {
                $status = StatusValue::newGood();
 
-               $pathList = call_user_func_array( 'array_merge', array_values( $pathsByType ) );
+               $pathList = array_merge( ...array_values( $pathsByType ) );
 
                $server = $this->lockServers[$lockSrv];
                $conn = $this->redisPool->getConnection( $server, $this->logger );
@@ -171,7 +171,7 @@ LUA;
        protected function freeLocksOnServer( $lockSrv, array $pathsByType ) {
                $status = StatusValue::newGood();
 
-               $pathList = call_user_func_array( 'array_merge', array_values( $pathsByType ) );
+               $pathList = array_merge( ...array_values( $pathsByType ) );
 
                $server = $this->lockServers[$lockSrv];
                $conn = $this->redisPool->getConnection( $server, $this->logger );
index ae434c1..dbab593 100644 (file)
@@ -87,11 +87,11 @@ class CachedBagOStuff extends HashBagOStuff {
        }
 
        public function makeKey( $class, $component = null ) {
-               return call_user_func_array( [ $this->backend, __FUNCTION__ ], func_get_args() );
+               return $this->backend->makeKey( ...func_get_args() );
        }
 
        public function makeGlobalKey( $class, $component = null ) {
-               return call_user_func_array( [ $this->backend, __FUNCTION__ ], func_get_args() );
+               return $this->backend->makeGlobalKey( ...func_get_args() );
        }
 
        // These just call the backend (tested elsewhere)
index b030522..edd5fbc 100644 (file)
@@ -195,16 +195,15 @@ class MultiWriteBagOStuff extends BagOStuff {
 
                        if ( $i == 0 || !$asyncWrites ) {
                                // First store or in sync mode: write now and get result
-                               if ( !call_user_func_array( [ $cache, $method ], $args ) ) {
+                               if ( !$cache->$method( ...$args ) ) {
                                        $ret = false;
                                }
                        } else {
                                // Secondary write in async mode: do not block this HTTP request
                                $logger = $this->logger;
-                               call_user_func(
-                                       $this->asyncHandler,
+                               ( $this->asyncHandler )(
                                        function () use ( $cache, $method, $args, $logger ) {
-                                               if ( !call_user_func_array( [ $cache, $method ], $args ) ) {
+                                               if ( !$cache->$method( ...$args ) ) {
                                                        $logger->warning( "Async $method op failed" );
                                                }
                                        }
@@ -235,10 +234,10 @@ class MultiWriteBagOStuff extends BagOStuff {
        }
 
        public function makeKey( $class, $component = null ) {
-               return call_user_func_array( [ $this->caches[0], __FUNCTION__ ], func_get_args() );
+               return $this->caches[0]->makeKey( ...func_get_args() );
        }
 
        public function makeGlobalKey( $class, $component = null ) {
-               return call_user_func_array( [ $this->caches[0], __FUNCTION__ ], func_get_args() );
+               return $this->caches[0]->makeGlobalKey( ...func_get_args() );
        }
 }
index 97e0456..927a1e3 100644 (file)
@@ -1603,7 +1603,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
         * @since 1.27
         */
        public function makeKey( $class, $component = null ) {
-               return call_user_func_array( [ $this->cache, __FUNCTION__ ], func_get_args() );
+               return $this->cache->makeKey( ...func_get_args() );
        }
 
        /**
@@ -1614,7 +1614,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
         * @since 1.27
         */
        public function makeGlobalKey( $class, $component = null ) {
-               return call_user_func_array( [ $this->cache, __FUNCTION__ ], func_get_args() );
+               return $this->cache->makeGlobalKey( ...func_get_args() );
        }
 
        /**
index dedf6ea..b414a2a 100644 (file)
@@ -46,7 +46,7 @@ class DBConnRef implements IDatabase {
                        $this->conn = $this->lb->getConnection( $db, $groups, $wiki, $flags );
                }
 
-               return call_user_func_array( [ $this->conn, $name ], $arguments );
+               return $this->conn->$name( ...$arguments );
        }
 
        public function getServerInfo() {
index 16e654f..57e5907 100644 (file)
@@ -1214,13 +1214,13 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
                $startTime = microtime( true );
                if ( $this->profiler ) {
-                       call_user_func( [ $this->profiler, 'profileIn' ], $queryProf );
+                       $this->profiler->profileIn( $queryProf );
                }
                $this->affectedRowCount = null;
                $ret = $this->doQuery( $commentedSql );
                $this->affectedRowCount = $this->affectedRows();
                if ( $this->profiler ) {
-                       call_user_func( [ $this->profiler, 'profileOut' ], $queryProf );
+                       $this->profiler->profileOut( $queryProf );
                }
                $queryRuntime = max( microtime( true ) - $startTime, 0.0 );
 
@@ -3230,7 +3230,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                $e = null;
                do {
                        try {
-                               $retVal = call_user_func_array( $function, $args );
+                               $retVal = $function( ...$args );
                                break;
                        } catch ( DBQueryError $e ) {
                                if ( $this->wasDeadlock() ) {
@@ -3310,7 +3310,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        // No transaction is active nor will start implicitly, so make one for this callback
                        $this->startAtomic( __METHOD__, self::ATOMIC_CANCELABLE );
                        try {
-                               call_user_func( $callback, $this );
+                               $callback( $this );
                                $this->endAtomic( __METHOD__ );
                        } catch ( Exception $e ) {
                                $this->cancelAtomic( __METHOD__ );
@@ -3486,9 +3486,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                                try {
                                        ++$count;
                                        list( $phpCallback ) = $callback;
-                                       call_user_func( $phpCallback, $this );
+                                       $phpCallback( $this );
                                } catch ( Exception $ex ) {
-                                       call_user_func( $this->errorLogger, $ex );
+                                       $this->errorLogger( $ex );
                                        $e = $e ?: $ex;
                                }
                        }
@@ -3522,7 +3522,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        try {
                                $phpCallback( $trigger, $this );
                        } catch ( Exception $ex ) {
-                               call_user_func( $this->errorLogger, $ex );
+                               ( $this->errorLogger )( $ex );
                                $e = $e ?: $ex;
                        }
                }
@@ -3723,7 +3723,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        ) {
                $sectionId = $this->startAtomic( $fname, $cancelable );
                try {
-                       $res = call_user_func_array( $callback, [ $this, $fname ] );
+                       $res = $callback( $this, $fname );
                } catch ( Exception $e ) {
                        $this->cancelAtomic( $fname, $sectionId );
 
@@ -4249,7 +4249,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                                $cmd = $this->replaceVars( $cmd );
 
                                if ( $inputCallback ) {
-                                       $callbackResult = call_user_func( $inputCallback, $cmd );
+                                       $callbackResult = $inputCallback( $cmd );
 
                                        if ( is_string( $callbackResult ) || !$callbackResult ) {
                                                $cmd = $callbackResult;
@@ -4260,7 +4260,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                                        $res = $this->query( $cmd, $fname );
 
                                        if ( $resultCallback ) {
-                                               call_user_func( $resultCallback, $res, $this );
+                                               $resultCallback( $res, $this );
                                        }
 
                                        if ( false === $res ) {
index 2125c70..4b925e6 100644 (file)
@@ -865,7 +865,7 @@ class DatabaseSqlite extends Database {
                $args = func_get_args();
                $function = array_shift( $args );
 
-               return call_user_func_array( $function, $args );
+               return $function( ...$args );
        }
 
        /**
index 52c2df7..34436fb 100644 (file)
@@ -202,7 +202,7 @@ abstract class LBFactory implements ILBFactory {
        protected function forEachLBCallMethod( $methodName, array $args = [] ) {
                $this->forEachLB(
                        function ( ILoadBalancer $loadBalancer, $methodName, array $args ) {
-                               call_user_func_array( [ $loadBalancer, $methodName ], $args );
+                               $loadBalancer->$methodName( ...$args );
                        },
                        [ $methodName, $args ]
                );
index cfa2647..30074ec 100644 (file)
@@ -422,10 +422,10 @@ class LBFactoryMulti extends LBFactory {
         */
        public function forEachLB( $callback, array $params = [] ) {
                foreach ( $this->mainLBs as $lb ) {
-                       call_user_func_array( $callback, array_merge( [ $lb ], $params ) );
+                       $callback( $lb, ...$params );
                }
                foreach ( $this->extLBs as $lb ) {
-                       call_user_func_array( $callback, array_merge( [ $lb ], $params ) );
+                       $callback( $lb, ...$params );
                }
        }
 }
index 0d7b812..6a6bb8d 100644 (file)
@@ -149,10 +149,10 @@ class LBFactorySimple extends LBFactory {
         */
        public function forEachLB( $callback, array $params = [] ) {
                if ( isset( $this->mainLB ) ) {
-                       call_user_func_array( $callback, array_merge( [ $this->mainLB ], $params ) );
+                       $callback( $this->mainLB, ...$params );
                }
                foreach ( $this->extLBs as $lb ) {
-                       call_user_func_array( $callback, array_merge( [ $lb ], $params ) );
+                       $callback( $lb, ...$params );
                }
        }
 }
index 587ab23..2c1a782 100644 (file)
@@ -103,7 +103,7 @@ class LBFactorySingle extends LBFactory {
         */
        public function forEachLB( $callback, array $params = [] ) {
                if ( isset( $this->lb ) ) { // may not be set during _destruct()
-                       call_user_func_array( $callback, array_merge( [ $this->lb ], $params ) );
+                       $callback( $this->lb, ...$params );
                }
        }
 }
index 221bca4..6b271a7 100644 (file)
@@ -864,7 +864,7 @@ class LoadBalancer implements ILoadBalancer {
                        $this->connLogger->debug( __METHOD__ . ': calling initLB() before first connection.' );
                        // Load any "waitFor" positions before connecting so that doWait() is triggered
                        $this->connectionAttempted = true;
-                       call_user_func( $this->chronologyCallback, $this );
+                       ( $this->chronologyCallback )( $this );
                }
 
                // Check if an auto-commit connection is being requested. If so, it will not reuse the
@@ -1370,7 +1370,7 @@ class LoadBalancer implements ILoadBalancer {
                                try {
                                        $conn->commit( $fname, $conn::FLUSHING_ALL_PEERS );
                                } catch ( DBError $e ) {
-                                       call_user_func( $this->errorLogger, $e );
+                                       ( $this->errorLogger )( $e );
                                        $failures[] = "{$conn->getServer()}: {$e->getMessage()}";
                                }
                        }
@@ -1723,8 +1723,7 @@ class LoadBalancer implements ILoadBalancer {
                foreach ( $this->conns as $connsByServer ) {
                        foreach ( $connsByServer as $serverConns ) {
                                foreach ( $serverConns as $conn ) {
-                                       $mergedParams = array_merge( [ $conn ], $params );
-                                       call_user_func_array( $callback, $mergedParams );
+                                       $callback( $conn, ...$params );
                                }
                        }
                }
@@ -1736,8 +1735,7 @@ class LoadBalancer implements ILoadBalancer {
                        if ( isset( $connsByServer[$masterIndex] ) ) {
                                /** @var IDatabase $conn */
                                foreach ( $connsByServer[$masterIndex] as $conn ) {
-                                       $mergedParams = array_merge( [ $conn ], $params );
-                                       call_user_func_array( $callback, $mergedParams );
+                                       $callback( $conn, ...$params );
                                }
                        }
                }
@@ -1750,8 +1748,7 @@ class LoadBalancer implements ILoadBalancer {
                                        continue; // skip master
                                }
                                foreach ( $serverConns as $conn ) {
-                                       $mergedParams = array_merge( [ $conn ], $params );
-                                       call_user_func_array( $callback, $mergedParams );
+                                       $callback( $conn, ...$params );
                                }
                        }
                }
index ede35fa..bbcb267 100644 (file)
@@ -133,10 +133,10 @@ class RedisConnRef implements LoggerAwareInterface {
        private function tryCall( $method, $arguments ) {
                $this->conn->clearLastError();
                try {
-                       $res = call_user_func_array( [ $this->conn, $method ], $arguments );
+                       $res = $this->conn->$method( ...$arguments );
                        $authError = $this->checkAuthentication();
                        if ( $authError === self::AUTH_ERROR_TEMPORARY ) {
-                               $res = call_user_func_array( [ $this->conn, $method ], $arguments );
+                               $res = $this->conn->$method( ...$arguments );
                        }
                        if ( $authError === self::AUTH_ERROR_PERMANENT ) {
                                throw new RedisException( "Failure reauthenticating to Redis." );
index 9e4a630..40498cd 100644 (file)
@@ -553,7 +553,7 @@ class LogEventsList extends ContextSource {
                        }
                        $permissionlist = implode( ', ', $permissions );
                        wfDebug( "Checking for $permissionlist due to $field match on $bitfield\n" );
-                       return call_user_func_array( [ $user, 'isAllowedAny' ], $permissions );
+                       return $user->isAllowedAny( ...$permissions );
                }
                return true;
        }
index cda037c..e2d32cf 100644 (file)
@@ -228,7 +228,7 @@ class BitmapHandler extends TransformationalImageHandler {
                $rotation = isset( $params['disableRotation'] ) ? 0 : $this->getRotation( $image );
                list( $width, $height ) = $this->extractPreRotationDimensions( $params, $rotation );
 
-               $cmd = call_user_func_array( 'wfEscapeShellArg', array_merge(
+               $cmd = wfEscapeShellArg( ...array_merge(
                        [ $wgImageMagickConvertCommand ],
                        $quality,
                        // Specify white background color, will be used for transparent images
@@ -449,7 +449,7 @@ class BitmapHandler extends TransformationalImageHandler {
                        return $this->getMediaTransformError( $params, $errMsg );
                }
 
-               $src_image = call_user_func( $loader, $params['srcPath'] );
+               $src_image = $loader( $params['srcPath'] );
 
                $rotation = function_exists( 'imagerotate' ) && !isset( $params['disableRotation'] ) ?
                        $this->getRotation( $image ) :
@@ -489,7 +489,7 @@ class BitmapHandler extends TransformationalImageHandler {
                if ( $useQuality && isset( $params['quality'] ) ) {
                        $funcParams[] = $params['quality'];
                }
-               call_user_func_array( $saveType, $funcParams );
+               $saveType( ...$funcParams );
 
                imagedestroy( $dst_image );
                imagedestroy( $src_image );
index a589dbf..a9c7b4f 100644 (file)
@@ -291,12 +291,16 @@ class SvgHandler extends ImageHandler {
                        if ( is_array( $wgSVGConverters[$wgSVGConverter] ) ) {
                                // This is a PHP callable
                                $func = $wgSVGConverters[$wgSVGConverter][0];
-                               $args = array_merge( [ $srcPath, $dstPath, $width, $height, $lang ],
-                                       array_slice( $wgSVGConverters[$wgSVGConverter], 1 ) );
                                if ( !is_callable( $func ) ) {
                                        throw new MWException( "$func is not callable" );
                                }
-                               $err = call_user_func_array( $func, $args );
+                               $err = $func( $srcPath,
+                                       $dstPath,
+                                       $width,
+                                       $height,
+                                       $lang,
+                                       ...array_slice( $wgSVGConverters[$wgSVGConverter], 1 )
+                               );
                                $retval = (bool)$err;
                        } else {
                                // External command
index c865d4e..1abf974 100644 (file)
@@ -279,8 +279,8 @@ class Article implements Page {
                                if ( $this->mRevision !== null ) {
                                        // Revision title doesn't match the page title given?
                                        if ( $this->mPage->getId() != $this->mRevision->getPage() ) {
-                                               $function = [ get_class( $this->mPage ), 'newFromID' ];
-                                               $this->mPage = call_user_func( $function, $this->mRevision->getPage() );
+                                               $function = get_class( $this->mPage ). '::newFromID';
+                                               $this->mPage = $function( $this->mRevision->getPage() );
                                        }
                                }
                        }
index 8df5b5b..15ed93c 100644 (file)
@@ -3435,7 +3435,7 @@ class Parser {
                        }
                }
 
-               $result = call_user_func_array( $callback, $allArgs );
+               $result = $callback( ...$allArgs );
 
                # The interface for function hooks allows them to return a wikitext
                # string or an array containing the string and any flags. This mungs
index 353825a..93f4246 100644 (file)
@@ -61,12 +61,9 @@ class ParserDiffTest {
                $results = [];
                $mismatch = false;
                $lastResult = null;
-               $first = true;
-               foreach ( $this->parsers as $i => $parser ) {
-                       $currentResult = call_user_func_array( [ &$this->parsers[$i], $name ], $args );
-                       if ( $first ) {
-                               $first = false;
-                       } else {
+               foreach ( $this->parsers as $parser ) {
+                       $currentResult = $parser->$name( ...$args );
+                       if ( count( $results ) > 0 ) {
                                if ( is_object( $lastResult ) ) {
                                        if ( $lastResult != $currentResult ) {
                                                $mismatch = true;
@@ -77,7 +74,7 @@ class ParserDiffTest {
                                        }
                                }
                        }
-                       $results[$i] = $currentResult;
+                       $results[] = $currentResult;
                        $lastResult = $currentResult;
                }
                if ( $mismatch ) {
index 9ec6cf8..265d151 100644 (file)
@@ -311,10 +311,10 @@ class ParserOutput extends CacheTime {
                                        }
 
                                        $skin = $wgOut->getSkin();
-                                       return call_user_func_array(
-                                               [ $skin, 'doEditSectionLink' ],
-                                               [ $editsectionPage, $editsectionSection,
-                                                       $editsectionContent, $wgLang->getCode() ]
+                                       return $skin->doEditSectionLink( $editsectionPage,
+                                               $editsectionSection,
+                                               $editsectionContent,
+                                               $wgLang->getCode()
                                        );
                                },
                                $text
index f811e3f..4ba34ef 100644 (file)
@@ -65,7 +65,7 @@ class BcryptPassword extends ParameterizedPassword {
                                // Replace + with ., because bcrypt uses a non-MIME base64 format
                                strtr(
                                        // Random base64 encoded string
-                                       base64_encode( MWCryptRand::generate( 16, true ) ),
+                                       base64_encode( random_bytes( 16 ) ),
                                        '+', '.'
                                ),
                                0, 22
index 0ea3c63..d1774ba 100644 (file)
@@ -60,7 +60,7 @@ class EncryptedPassword extends ParameterizedPassword {
                if ( count( $this->args ) ) {
                        $iv = base64_decode( $this->args[0] );
                } else {
-                       $iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
+                       $iv = random_bytes( openssl_cipher_iv_length( $this->params['cipher'] ) );
                }
 
                $this->hash = openssl_encrypt(
@@ -102,7 +102,7 @@ class EncryptedPassword extends ParameterizedPassword {
                $this->params = $this->getDefaultParams();
 
                // Check the key size with the new params
-               $iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
+               $iv = random_bytes( openssl_cipher_iv_length( $this->params['cipher'] ) );
                $this->hash = openssl_encrypt(
                                $underlyingHash,
                                $this->params['cipher'],
index 541fd0e..6065045 100644 (file)
@@ -47,7 +47,7 @@ class Pbkdf2Password extends ParameterizedPassword {
 
        public function crypt( $password ) {
                if ( count( $this->args ) == 0 ) {
-                       $this->args[] = base64_encode( MWCryptRand::generate( 16, true ) );
+                       $this->args[] = base64_encode( random_bytes( 16 ) );
                }
 
                if ( $this->shouldUseHashExtension() ) {
index 834b8b1..aed52d1 100644 (file)
@@ -66,26 +66,26 @@ class PoolCounterWorkViaCallback extends PoolCounterWork {
        }
 
        public function doWork() {
-               return call_user_func_array( $this->doWork, [] );
+               return ( $this->doWork )();
        }
 
        public function getCachedWork() {
                if ( $this->doCachedWork ) {
-                       return call_user_func_array( $this->doCachedWork, [] );
+                       return ( $this->doCachedWork )();
                }
                return false;
        }
 
        public function fallback() {
                if ( $this->fallback ) {
-                       return call_user_func_array( $this->fallback, [] );
+                       return ( $this->fallback )();
                }
                return false;
        }
 
        public function error( $status ) {
                if ( $this->error ) {
-                       return call_user_func_array( $this->error, [ $status ] );
+                       return ( $this->error )( $status );
                }
                return false;
        }
index d41198a..3ceb915 100644 (file)
@@ -226,7 +226,7 @@ class ResourceLoaderContext implements MessageLocalizer {
         * @return Message
         */
        public function msg( $key ) {
-               return call_user_func_array( 'wfMessage', func_get_args() )
+               return wfMessage( ...func_get_args() )
                        ->inLanguage( $this->getLanguage() )
                        // Use a dummy title because there is no real title
                        // for this endpoint, and the cache won't vary on it
index 4c52693..c98b7da 100644 (file)
@@ -355,9 +355,8 @@ class ServiceContainer implements DestructibleService {
         */
        private function createService( $name ) {
                if ( isset( $this->serviceInstantiators[$name] ) ) {
-                       $service = call_user_func_array(
-                               $this->serviceInstantiators[$name],
-                               array_merge( [ $this ], $this->extraInstantiationParams )
+                       $service = ( $this->serviceInstantiators[$name] )(
+                               $this, ...$this->extraInstantiationParams
                        );
                        // NOTE: when adding more wiring logic here, make sure copyWiring() is kept in sync!
                } else {
index 024bf9a..e9a03f2 100644 (file)
@@ -481,7 +481,7 @@ final class Session implements \Countable, \Iterator, \ArrayAccess {
 
                // Encrypt
                // @todo: import a pure-PHP library for AES instead of doing $wgSessionInsecureSecrets
-               $iv = \MWCryptRand::generate( 16, true );
+               $iv = random_bytes( 16 );
                $algorithm = self::getEncryptionAlgorithm();
                switch ( $algorithm[0] ) {
                        case 'openssl':
index d1bea8d..c1c856d 100644 (file)
@@ -36,7 +36,7 @@ abstract class BaseTemplate extends QuickTemplate {
         * @return Message
         */
        public function getMsg( $name /* ... */ ) {
-               return call_user_func_array( [ $this->getSkin(), 'msg' ], func_get_args() );
+               return $this->getSkin()->msg( ...func_get_args() );
        }
 
        function msg( $str ) {
@@ -597,10 +597,7 @@ abstract class BaseTemplate extends QuickTemplate {
 
                if ( $option == 'flat' ) {
                        // fold footerlinks into a single array using a bit of trickery
-                       $validFooterLinks = call_user_func_array(
-                               'array_merge',
-                               array_values( $validFooterLinks )
-                       );
+                       $validFooterLinks = array_merge( ...array_values( $validFooterLinks ) );
                }
 
                return $validFooterLinks;
index 81e13f0..557bd9c 100644 (file)
@@ -432,11 +432,11 @@ abstract class AuthManagerSpecialPage extends SpecialPage {
                                $status = Status::newFatal( new RawMessage( '$1', $status ) );
                        } elseif ( is_array( $status ) ) {
                                if ( is_string( reset( $status ) ) ) {
-                                       $status = call_user_func_array( 'Status::newFatal', $status );
+                                       $status = Status::newFatal( ...$status );
                                } elseif ( is_array( reset( $status ) ) ) {
                                        $status = Status::newGood();
                                        foreach ( $status as $message ) {
-                                               call_user_func_array( [ $status, 'fatal' ], $message );
+                                               $status->fatal( ...$message );
                                        }
                                } else {
                                        throw new UnexpectedValueException( 'invalid HTMLForm::trySubmit() return value: '
index 0622584..831644e 100644 (file)
@@ -704,9 +704,8 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                        return;
                }
 
-               $knownParams = call_user_func_array(
-                       [ $this->getRequest(), 'getValues' ],
-                       array_keys( $this->getOptions()->getAllValues() )
+               $knownParams = $this->getRequest()->getValues(
+                       ...array_keys( $this->getOptions()->getAllValues() )
                );
 
                // HACK: Temporarily until we can properly define "sticky" filters and parameters,
index 45e9684..3082101 100644 (file)
@@ -1062,7 +1062,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                                        // 'id' => 'mw-userlogin-help', // FIXME HTMLInfoField ignores this
                                        'raw' => true,
                                        'default' => Html::element( 'a', [
-                                               'href' => Skin::makeInternalOrExternalUrl( wfMessage( 'helplogin-url' )
+                                               'href' => Skin::makeInternalOrExternalUrl( $this->msg( 'helplogin-url' )
                                                        ->inContentLanguage()
                                                        ->text() ),
                                        ], $this->msg( 'userlogin-helplink2' )->text() ),
index 317aa0d..5db8066 100644 (file)
@@ -791,10 +791,7 @@ class SpecialPage implements MessageLocalizer {
         * @see wfMessage
         */
        public function msg( $key /* $args */ ) {
-               $message = call_user_func_array(
-                       [ $this->getContext(), 'msg' ],
-                       func_get_args()
-               );
+               $message = $this->getContext()->msg( ...func_get_args() );
                // RequestContext passes context to wfMessage, and the language is set from
                // the context, but setting the language for Message class removes the
                // interface message status, which breaks for example usernameless gender
index efe354a..bc632b1 100644 (file)
@@ -553,7 +553,7 @@ class SpecialBlock extends FormSpecialPage {
                if ( !$status->isOK() ) {
                        $errors = $status->getErrorsArray();
 
-                       return call_user_func_array( [ $form, 'msg' ], $errors[0] );
+                       return $form->msg( ...$errors[0] );
                } else {
                        return true;
                }
index 6a471ba..5352d95 100644 (file)
@@ -854,7 +854,7 @@ abstract class UploadBase {
                        if ( !is_array( $error ) ) {
                                $error = [ $error ];
                        }
-                       return call_user_func_array( 'Status::newFatal', $error );
+                       return Status::newFatal( ...$error );
                }
 
                $status = $this->getLocalFile()->upload(
@@ -1063,7 +1063,7 @@ abstract class UploadBase {
                if ( !$isPartial ) {
                        $error = $this->runUploadStashFileHook( $user );
                        if ( $error ) {
-                               return call_user_func_array( 'Status::newFatal', $error );
+                               return Status::newFatal( ...$error );
                        }
                }
                try {
index 68bcb9d..ee6f250 100644 (file)
@@ -210,7 +210,7 @@ class UploadFromChunks extends UploadFromFile {
                // override doStashFile() with completely different functionality in this class...
                $error = $this->runUploadStashFileHook( $this->user );
                if ( $error ) {
-                       call_user_func_array( [ $status, 'fatal' ], $error );
+                       $status->fatal( ...$error );
                        return $status;
                }
                try {
@@ -422,9 +422,9 @@ class UploadChunkFileException extends MWException {
 
 class UploadChunkVerificationException extends MWException {
        public $msg;
-       public function __construct( $res ) {
-               $this->msg = call_user_func_array( 'wfMessage', $res );
-               parent::__construct( call_user_func_array( 'wfMessage', $res )
+       public function __construct( array $res ) {
+               $this->msg = wfMessage( ...$res );
+               parent::__construct( wfMessage( ...$res )
                        ->inLanguage( 'en' )->useDatabase( false )->text() );
        }
 }
index 5818958..0fc45f7 100644 (file)
@@ -28,6 +28,7 @@ use MediaWiki\MediaWikiServices;
 
 class MWCryptRand {
        /**
+        * @deprecated since 1.32
         * @return CryptRand
         */
        protected static function singleton() {
@@ -39,41 +40,49 @@ class MWCryptRand {
         * random bytes generation in the previously run generate* call
         * was cryptographically strong.
         *
-        * @return bool Returns true if the source was strong, false if not.
+        * @deprecated since 1.32, always returns true
+        *
+        * @return bool Always true
         */
        public static function wasStrong() {
-               return self::singleton()->wasStrong();
+               return true;
        }
 
        /**
-        * Generate a run of (ideally) cryptographically random data and return
+        * Generate a run of cryptographically random data and return
         * it in raw binary form.
-        * You can use MWCryptRand::wasStrong() if you wish to know if the source used
-        * was cryptographically strong.
+        *
+        * @deprecated since 1.32, use random_bytes()
         *
         * @param int $bytes The number of bytes of random data to generate
-        * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
-        *                          strong sources of entropy even if reading from them may steal
-        *                          more entropy from the system than optimal.
         * @return string Raw binary random data
         */
-       public static function generate( $bytes, $forceStrong = false ) {
-               return self::singleton()->generate( $bytes, $forceStrong );
+       public static function generate( $bytes ) {
+               return random_bytes( floor( $bytes ) );
        }
 
        /**
-        * Generate a run of (ideally) cryptographically random data and return
+        * Generate a run of cryptographically random data and return
         * it in hexadecimal string format.
-        * You can use MWCryptRand::wasStrong() if you wish to know if the source used
-        * was cryptographically strong.
         *
         * @param int $chars The number of hex chars of random data to generate
-        * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
-        *                          strong sources of entropy even if reading from them may steal
-        *                          more entropy from the system than optimal.
         * @return string Hexadecimal random data
         */
-       public static function generateHex( $chars, $forceStrong = false ) {
-               return self::singleton()->generateHex( $chars, $forceStrong );
+       public static function generateHex( $chars ) {
+               // hex strings are 2x the length of raw binary so we divide the length in half
+               // odd numbers will result in a .5 that leads the generate() being 1 character
+               // short, so we use ceil() to ensure that we always have enough bytes
+               $bytes = ceil( $chars / 2 );
+               // Generate the data and then convert it to a hex string
+               $hex = bin2hex( random_bytes( $bytes ) );
+
+               // A bit of paranoia here, the caller asked for a specific length of string
+               // here, and it's possible (eg when given an odd number) that we may actually
+               // have at least 1 char more than they asked for. Just in case they made this
+               // call intending to insert it into a database that does truncation we don't
+               // want to give them too much and end up with their database and their live
+               // code having two different values because part of what we gave them is truncated
+               // hence, we strip out any run of characters longer than what we were asked for.
+               return substr( $hex, 0, $chars );
        }
 }
index 0fdd417..21d9bb1 100644 (file)
@@ -142,7 +142,7 @@ class BackupDumper extends Maintenance {
                        require_once $file;
                }
                $register = [ $class, 'register' ];
-               call_user_func_array( $register, [ $this ] );
+               $register( $this );
        }
 
        function execute() {
index 49b8e0a..271cbf3 100644 (file)
@@ -226,7 +226,7 @@ class RecompressTracked {
                }
                $cmd .= ' --child' .
                        ' --wiki ' . wfEscapeShellArg( wfWikiID() ) .
-                       ' ' . call_user_func_array( 'wfEscapeShellArg', $this->destClusters );
+                       ' ' . wfEscapeShellArg( ...$this->destClusters );
 
                $this->replicaPipes = $this->replicaProcs = [];
                for ( $i = 0; $i < $this->numProcs; $i++ ) {
@@ -426,12 +426,12 @@ class RecompressTracked {
                                $args = array_slice( $ids, 0, $this->orphanBatchSize );
                                $ids = array_slice( $ids, $this->orphanBatchSize );
                                array_unshift( $args, 'doOrphanList' );
-                               call_user_func_array( [ $this, 'dispatch' ], $args );
+                               $this->dispatch( ...$args );
                        }
                        if ( count( $ids ) ) {
                                $args = $ids;
                                array_unshift( $args, 'doOrphanList' );
-                               call_user_func_array( [ $this, 'dispatch' ], $args );
+                               $this->dispatch( ...$args );
                        }
 
                        $this->report( 'orphans', $i, $numOrphans );
index 5f71287..61d86bd 100644 (file)
@@ -305,8 +305,6 @@ return [
                "PhanDeprecatedProperty",
                // approximate error count: 17
                "PhanNonClassMethodCall",
-               // approximate error count: 11
-               "PhanParamReqAfterOpt",
                // approximate error count: 888
                "PhanParamSignatureMismatch",
                // approximate error count: 7
index f84d435..a74056d 100644 (file)
@@ -358,7 +358,7 @@ class SessionTest extends MediaWikiTestCase {
                $logger->clearBuffer();
 
                // Unserializable data
-               $iv = \MWCryptRand::generate( 16, true );
+               $iv = random_bytes( 16 );
                list( $encKey, $hmacKey ) = TestingAccessWrapper::newFromObject( $session )->getSecretKeys();
                $ciphertext = openssl_encrypt( 'foobar', 'aes-256-ctr', $encKey, OPENSSL_RAW_DATA, $iv );
                $sealed = base64_encode( $iv ) . '.' . base64_encode( $ciphertext );
index 143a419..4d35930 100644 (file)
@@ -37,7 +37,7 @@ class MockMessageLocalizer implements MessageLocalizer {
                $args = func_get_args();
 
                /** @var Message $message */
-               $message = call_user_func_array( 'wfMessage', $args );
+               $message = wfMessage( ...$args );
 
                if ( $this->languageCode !== null ) {
                        $message->inLanguage( $this->languageCode );