From: jenkins-bot Date: Wed, 12 Jun 2019 21:28:33 +0000 (+0000) Subject: Merge "Add CompositeBlock class for enforcing multiple blocks" X-Git-Tag: 1.34.0-rc.0~1439 X-Git-Url: http://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/pie.php?a=commitdiff_plain;h=ecdd1d6ff4d11d19bf446c74529cbbcca4aa1657;hp=1eaf65d0a5f551216668a9e434ce323f0ba7dafe;p=lhc%2Fweb%2Fwiklou.git Merge "Add CompositeBlock class for enforcing multiple blocks" --- diff --git a/.phpcs.xml b/.phpcs.xml index 22b74b514a..9ccf5657b7 100644 --- a/.phpcs.xml +++ b/.phpcs.xml @@ -256,6 +256,9 @@ --> */maintenance/mwdocgen\.php + + tests/phpunit/structure/* + . diff --git a/RELEASE-NOTES-1.34 b/RELEASE-NOTES-1.34 index 3d90ac8b79..33d060d477 100644 --- a/RELEASE-NOTES-1.34 +++ b/RELEASE-NOTES-1.34 @@ -202,6 +202,9 @@ because of Phabricator reports. getErrorsOrWarnings() instead. * SpecialPage::getTitle(), deprecated in 1.23, has been removed. Use SpecialPage::getPageTitle() instead. +* jquery.ui.effect-bounce, jquery.ui.effect-explode, jquery.ui.effect-fold + jquery.ui.effect-pulsate, jquery.ui.effect-slide, jquery.ui.effect-transfer, + which are no longer used, have now been removed. * … === Deprecations in 1.34 === diff --git a/autoload.php b/autoload.php index eb8ba09dd8..b26549e137 100644 --- a/autoload.php +++ b/autoload.php @@ -1246,6 +1246,7 @@ $wgAutoloadLocalClasses = [ 'ResourceLoaderLessVarFileModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLessVarFileModule.php', 'ResourceLoaderModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderModule.php', 'ResourceLoaderOOUIFileModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIFileModule.php', + 'ResourceLoaderOOUIIconPackModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIIconPackModule.php', 'ResourceLoaderOOUIImageModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIImageModule.php', 'ResourceLoaderOOUIModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIModule.php', 'ResourceLoaderSiteModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderSiteModule.php', diff --git a/includes/EditPage.php b/includes/EditPage.php index e4adb48b2c..d27ef9c7a9 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -4130,7 +4130,7 @@ ERROR; if ( !Hooks::run( 'EditPageBeforeEditToolbar', [ &$toolbar ] ) ) { return null; - }; + } // Don't add a pointless `
` to the page unless a hook caller populated it return ( $toolbar === $startingToolbar ) ? null : $toolbar; } diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 54b3ee5f68..5227aa10da 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -4214,9 +4214,7 @@ class OutputPage extends ContextSource { 'oojs-ui.styles.indicators', 'oojs-ui.styles.textures', 'mediawiki.widgets.styles', - 'oojs-ui.styles.icons-content', - 'oojs-ui.styles.icons-alerts', - 'oojs-ui.styles.icons-interactions', + 'oojs-ui-core.icons', ] ); } diff --git a/includes/Revision/RevisionStore.php b/includes/Revision/RevisionStore.php index 29d7848455..00c9d042df 100644 --- a/includes/Revision/RevisionStore.php +++ b/includes/Revision/RevisionStore.php @@ -1644,7 +1644,7 @@ class RevisionStore throw new RevisionAccessException( 'Main slot of revision ' . $revId . ' not found in database!' ); - }; + } return $slots; } diff --git a/includes/api/ApiLogin.php b/includes/api/ApiLogin.php index c3c531802a..de5257e47d 100644 --- a/includes/api/ApiLogin.php +++ b/includes/api/ApiLogin.php @@ -287,7 +287,7 @@ class ApiLogin extends ApiBase { ]; if ( $response->message ) { $ret['message'] = $response->message->inLanguage( 'en' )->plain(); - }; + } $reqs = [ 'neededRequests' => $response->neededRequests, 'createRequest' => $response->createRequest, diff --git a/includes/export/WikiExporter.php b/includes/export/WikiExporter.php index e8044af455..8b42be1315 100644 --- a/includes/export/WikiExporter.php +++ b/includes/export/WikiExporter.php @@ -320,7 +320,7 @@ class WikiExporter { } $lastLogId = $this->outputLogStream( $result ); - }; + } } /** diff --git a/includes/installer/PostgresUpdater.php b/includes/installer/PostgresUpdater.php index 008240a38c..31827a1ab7 100644 --- a/includes/installer/PostgresUpdater.php +++ b/includes/installer/PostgresUpdater.php @@ -1071,7 +1071,7 @@ END; $this->db->query( $command ); } else { $this->output( "...foreign key constraint on '$table.$field' already does not exist\n" ); - }; + } } protected function changeFkeyDeferrable( $table, $field, $clause ) { @@ -1235,7 +1235,7 @@ END; if ( $this->updateRowExists( 'patch-textsearch_bug66650.sql' ) ) { $this->output( "...T68650 already fixed or not applicable.\n" ); return; - }; + } $this->applyPatch( 'patch-textsearch_bug66650.sql', false, 'Rebuilding text search for T68650' ); } diff --git a/includes/installer/i18n/en.json b/includes/installer/i18n/en.json index 3705a8d8ae..5b9742b0ca 100644 --- a/includes/installer/i18n/en.json +++ b/includes/installer/i18n/en.json @@ -45,8 +45,8 @@ "config-env-bad": "The environment has been checked.\nYou cannot install MediaWiki.", "config-env-php": "PHP $1 is installed.", "config-env-hhvm": "HHVM $1 is installed.", - "config-unicode-using-intl": "Using the [https://pecl.php.net/intl intl PECL extension] for Unicode normalization.", - "config-unicode-pure-php-warning": "Warning: The [https://pecl.php.net/intl intl PECL extension] is not available to handle Unicode normalization, falling back to slow pure-PHP implementation.\nIf you run a high-traffic site, you should read a little on [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode normalization].", + "config-unicode-using-intl": "Using the [https://php.net/manual/en/book.intl.php PHP intl extension] for Unicode normalization.", + "config-unicode-pure-php-warning": "Warning: The [https://php.net/manual/en/book.intl.php PHP intl extension] is not available to handle Unicode normalization, falling back to slow pure-PHP implementation.\nIf you run a high-traffic site, you should read on [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode normalization].", "config-unicode-update-warning": "Warning: The installed version of the Unicode normalization wrapper uses an older version of [http://site.icu-project.org/ the ICU project's] library.\nYou should [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations upgrade] if you are at all concerned about using Unicode.", "config-no-db": "Could not find a suitable database driver! You need to install a database driver for PHP.\nThe following database {{PLURAL:$2|type is|types are}} supported: $1.\n\nIf you compiled PHP yourself, reconfigure it with a database client enabled, for example, using ./configure --with-mysqli.\nIf you installed PHP from a Debian or Ubuntu package, then you also need to install, for example, the php-mysql package.", "config-outdated-sqlite": "Warning: you have SQLite $2, which is lower than minimum required version $1. SQLite will be unavailable.", diff --git a/includes/libs/StatusValue.php b/includes/libs/StatusValue.php index 16cb1ed1d3..71a0e348dd 100644 --- a/includes/libs/StatusValue.php +++ b/includes/libs/StatusValue.php @@ -107,7 +107,7 @@ class StatusValue { } else { $errorsOnlyStatusValue->errors[] = $item; } - }; + } return [ $errorsOnlyStatusValue, $warningsOnlyStatusValue ]; } diff --git a/includes/libs/mime/MimeAnalyzer.php b/includes/libs/mime/MimeAnalyzer.php index a326df2bc2..e7dc926b1e 100644 --- a/includes/libs/mime/MimeAnalyzer.php +++ b/includes/libs/mime/MimeAnalyzer.php @@ -849,7 +849,7 @@ EOT; $callback = $this->guessCallback; if ( $callback ) { $callback( $this, $head, $tail, $file, $mime /* by reference */ ); - }; + } return $mime; } diff --git a/includes/libs/rdbms/database/Database.php b/includes/libs/rdbms/database/Database.php index fe23a384a4..ab718ec267 100644 --- a/includes/libs/rdbms/database/Database.php +++ b/includes/libs/rdbms/database/Database.php @@ -1020,7 +1020,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware * * @throws DBUnexpectedError */ - protected function assertHasConnectionHandle() { + final protected function assertHasConnectionHandle() { if ( !$this->isOpen() ) { throw new DBUnexpectedError( $this, "DB connection was already closed." ); } @@ -1029,7 +1029,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware /** * Make sure that this server is not marked as a replica nor read-only as a sanity check * - * @throws DBUnexpectedError + * @throws DBReadOnlyRoleError + * @throws DBReadOnlyError */ protected function assertIsWritableMaster() { if ( $this->getLBInfo( 'replica' ) === true ) { @@ -1064,6 +1065,17 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware /** * Run a query and return a DBMS-dependent wrapper or boolean * + * This is meant to handle the basic command of actually sending a query to the + * server via the driver. No implicit transaction, reconnection, nor retry logic + * should happen here. The higher level query() method is designed to handle those + * sorts of concerns. This method should not trigger such higher level methods. + * + * The lastError() and lastErrno() methods should meaningfully reflect what error, + * if any, occured during the last call to this method. Methods like executeQuery(), + * query(), select(), insert(), update(), delete(), and upsert() implement their calls + * to doQuery() such that an immediately subsequent call to lastError()/lastErrno() + * meaningfully reflects any error that occured during that public query method call. + * * For SELECT queries, this returns either: * - a) A driver-specific value/resource, only on success. This can be iterated * over by calling fetchObject()/fetchRow() until there are no more rows. @@ -1141,7 +1153,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware protected function isTransactableQuery( $sql ) { return !in_array( $this->getQueryVerb( $sql ), - [ 'BEGIN', 'ROLLBACK', 'COMMIT', 'SET', 'SHOW', 'CREATE', 'ALTER' ], + [ 'BEGIN', 'ROLLBACK', 'COMMIT', 'SET', 'SHOW', 'CREATE', 'ALTER', 'USE' ], true ); } @@ -1190,108 +1202,132 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } public function query( $sql, $fname = __METHOD__, $flags = 0 ) { - $this->assertTransactionStatus( $sql, $fname ); - $this->assertHasConnectionHandle(); - $flags = (int)$flags; // b/c; this field used to be a bool - $ignoreErrors = $this->hasFlags( $flags, self::QUERY_SILENCE_ERRORS ); + // Sanity check that the SQL query is appropriate in the current context and is + // allowed for an outside caller (e.g. does not break transaction/session tracking). + $this->assertQueryIsCurrentlyAllowed( $sql, $fname ); + + // Send the query to the server and fetch any corresponding errors + list( $ret, $err, $errno, $unignorable ) = $this->executeQuery( $sql, $fname, $flags ); + if ( $ret === false ) { + $ignoreErrors = $this->hasFlags( $flags, self::QUERY_SILENCE_ERRORS ); + // Throw an error unless both the ignore flag was set and a rollback is not needed + $this->reportQueryError( $err, $errno, $sql, $fname, $ignoreErrors && !$unignorable ); + } + + return $this->resultObject( $ret ); + } + + /** + * Execute a query, retrying it if there is a recoverable connection loss + * + * This is similar to query() except: + * - It does not prevent all non-ROLLBACK queries if there is a corrupted transaction + * - It does not disallow raw queries that are supposed to use dedicated IDatabase methods + * - It does not throw exceptions for common error cases + * + * This is meant for internal use with Database subclasses. + * + * @param string $sql Original SQL query + * @param string $fname Name of the calling function + * @param int $flags Bitfield of class QUERY_* constants + * @return array An n-tuple of: + * - mixed|bool: An object, resource, or true on success; false on failure + * - string: The result of calling lastError() + * - int: The result of calling lastErrno() + * - bool: Whether a rollback is needed to allow future non-rollback queries + * @throws DBUnexpectedError + */ + final protected function executeQuery( $sql, $fname, $flags ) { + $this->assertHasConnectionHandle(); $priorTransaction = $this->trxLevel; - $priorWritesPending = $this->writesOrCallbacksPending(); if ( $this->isWriteQuery( $sql ) ) { # In theory, non-persistent writes are allowed in read-only mode, but due to things # like https://bugs.mysql.com/bug.php?id=33669 that might not work anyway... $this->assertIsWritableMaster(); - # Do not treat temporary table writes as "meaningful writes" that need committing. - # Profile them as reads. Integration tests can override this behavior via $flags. + # Do not treat temporary table writes as "meaningful writes" since they are only + # visible to one session and are not permanent. Profile them as reads. Integration + # tests can override this behavior via $flags. $pseudoPermanent = $this->hasFlags( $flags, self::QUERY_PSEUDO_PERMANENT ); $tableType = $this->registerTempTableWrite( $sql, $pseudoPermanent ); - $isEffectiveWrite = ( $tableType !== self::TEMP_NORMAL ); + $isPermWrite = ( $tableType !== self::TEMP_NORMAL ); # DBConnRef uses QUERY_REPLICA_ROLE to enforce the replica role for raw SQL queries - if ( $isEffectiveWrite && $this->hasFlags( $flags, self::QUERY_REPLICA_ROLE ) ) { + if ( $isPermWrite && $this->hasFlags( $flags, self::QUERY_REPLICA_ROLE ) ) { throw new DBReadOnlyRoleError( $this, "Cannot write; target role is DB_REPLICA" ); } } else { - $isEffectiveWrite = false; + $isPermWrite = false; } - # Add trace comment to the begin of the sql string, right after the operator. - # Or, for one-word queries (like "BEGIN" or COMMIT") add it to the end (T44598) + // Add trace comment to the begin of the sql string, right after the operator. + // Or, for one-word queries (like "BEGIN" or COMMIT") add it to the end (T44598) $commentedSql = preg_replace( '/\s|$/', " /* $fname {$this->agent} */ ", $sql, 1 ); - # Send the query to the server and fetch any corresponding errors - $ret = $this->attemptQuery( $sql, $commentedSql, $isEffectiveWrite, $fname ); - $lastError = $this->lastError(); - $lastErrno = $this->lastErrno(); - - $recoverableSR = false; // recoverable statement rollback? - $recoverableCL = false; // recoverable connection loss? - - if ( $ret === false && $this->wasConnectionLoss() ) { - # Check if no meaningful session state was lost - $recoverableCL = $this->canRecoverFromDisconnect( $sql, $priorWritesPending ); - # Update session state tracking and try to restore the connection - $reconnected = $this->replaceLostConnection( __METHOD__ ); - # Silently resend the query to the server if it is safe and possible - if ( $recoverableCL && $reconnected ) { - $ret = $this->attemptQuery( $sql, $commentedSql, $isEffectiveWrite, $fname ); - $lastError = $this->lastError(); - $lastErrno = $this->lastErrno(); - - if ( $ret === false && $this->wasConnectionLoss() ) { - # Query probably causes disconnects; reconnect and do not re-run it - $this->replaceLostConnection( __METHOD__ ); - } else { - $recoverableCL = false; // connection does not need recovering - $recoverableSR = $this->wasKnownStatementRollbackError(); - } - } - } else { - $recoverableSR = $this->wasKnownStatementRollbackError(); + // Send the query to the server and fetch any corresponding errors + list( $ret, $err, $errno, $recoverableSR, $recoverableCL, $reconnected ) = + $this->executeQueryAttempt( $sql, $commentedSql, $isPermWrite, $fname, $flags ); + // Check if the query failed due to a recoverable connection loss + if ( $ret === false && $recoverableCL && $reconnected ) { + // Silently resend the query to the server since it is safe and possible + list( $ret, $err, $errno, $recoverableSR, $recoverableCL ) = + $this->executeQueryAttempt( $sql, $commentedSql, $isPermWrite, $fname, $flags ); } + $corruptedTrx = false; + if ( $ret === false ) { if ( $priorTransaction ) { if ( $recoverableSR ) { # We're ignoring an error that caused just the current query to be aborted. # But log the cause so we can log a deprecation notice if a caller actually # does ignore it. - $this->trxStatusIgnoredCause = [ $lastError, $lastErrno, $fname ]; + $this->trxStatusIgnoredCause = [ $err, $errno, $fname ]; } elseif ( !$recoverableCL ) { # Either the query was aborted or all queries after BEGIN where aborted. # In the first case, the only options going forward are (a) ROLLBACK, or # (b) ROLLBACK TO SAVEPOINT (if one was set). If the later case, the only # option is ROLLBACK, since the snapshots would have been released. + $corruptedTrx = true; // cannot recover $this->trxStatus = self::STATUS_TRX_ERROR; $this->trxStatusCause = - $this->getQueryExceptionAndLog( $lastError, $lastErrno, $sql, $fname ); - $ignoreErrors = false; // cannot recover + $this->getQueryExceptionAndLog( $err, $errno, $sql, $fname ); $this->trxStatusIgnoredCause = null; } } - - $this->reportQueryError( $lastError, $lastErrno, $sql, $fname, $ignoreErrors ); } - return $this->resultObject( $ret ); + return [ $ret, $err, $errno, $corruptedTrx ]; } /** - * Wrapper for query() that also handles profiling, logging, and affected row count updates + * Wrapper for doQuery() that handles DBO_TRX, profiling, logging, affected row count + * tracking, and reconnects (without retry) on query failure due to connection loss * * @param string $sql Original SQL query * @param string $commentedSql SQL query with debugging/trace comment - * @param bool $isEffectiveWrite Whether the query is a (non-temporary table) write + * @param bool $isPermWrite Whether the query is a (non-temporary table) write * @param string $fname Name of the calling function - * @return bool|IResultWrapper True for a successful write query, ResultWrapper - * object for a successful read query, or false on failure + * @param int $flags Bitfield of class QUERY_* constants + * @return array An n-tuple of: + * - mixed|bool: An object, resource, or true on success; false on failure + * - string: The result of calling lastError() + * - int: The result of calling lastErrno() + * - bool: Whether a statement rollback error occured + * - bool: Whether a disconnect *both* happened *and* was recoverable + * - bool: Whether a reconnection attempt was *both* made *and* succeeded + * @throws DBUnexpectedError */ - private function attemptQuery( $sql, $commentedSql, $isEffectiveWrite, $fname ) { - $this->beginIfImplied( $sql, $fname ); + private function executeQueryAttempt( $sql, $commentedSql, $isPermWrite, $fname, $flags ) { + $priorWritesPending = $this->writesOrCallbacksPending(); + + if ( ( $flags & self::QUERY_IGNORE_DBO_TRX ) == 0 ) { + $this->beginIfImplied( $sql, $fname ); + } // Keep track of whether the transaction has write queries pending - if ( $isEffectiveWrite ) { + if ( $isPermWrite ) { $this->lastWriteTime = microtime( true ); if ( $this->trxLevel && !$this->trxDoneWrites ) { $this->trxDoneWrites = true; @@ -1310,16 +1346,31 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $this->affectedRowCount = null; $this->lastQuery = $sql; $ret = $this->doQuery( $commentedSql ); + $lastError = $this->lastError(); + $lastErrno = $this->lastErrno(); + $this->affectedRowCount = $this->affectedRows(); unset( $ps ); // profile out (if set) $queryRuntime = max( microtime( true ) - $startTime, 0.0 ); + $recoverableSR = false; // recoverable statement rollback? + $recoverableCL = false; // recoverable connection loss? + $reconnected = false; // reconnection both attempted and succeeded? + if ( $ret !== false ) { $this->lastPing = $startTime; - if ( $isEffectiveWrite && $this->trxLevel ) { + if ( $isPermWrite && $this->trxLevel ) { $this->updateTrxWriteQueryTime( $sql, $queryRuntime, $this->affectedRows() ); $this->trxWriteCallers[] = $fname; } + } elseif ( $this->wasConnectionError( $lastErrno ) ) { + # Check if no meaningful session state was lost + $recoverableCL = $this->canRecoverFromDisconnect( $sql, $priorWritesPending ); + # Update session state tracking and try to restore the connection + $reconnected = $this->replaceLostConnection( __METHOD__ ); + } else { + # Check if only the last query was rolled back + $recoverableSR = $this->wasKnownStatementRollbackError(); } if ( $sql === self::PING_QUERY ) { @@ -1329,8 +1380,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $this->trxProfiler->recordQueryCompletion( $generalizedSql, $startTime, - $isEffectiveWrite, - $isEffectiveWrite ? $this->affectedRows() : $this->numRows( $ret ) + $isPermWrite, + $isPermWrite ? $this->affectedRows() : $this->numRows( $ret ) ); // Avoid the overhead of logging calls unless debug mode is enabled @@ -1346,7 +1397,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware ); } - return $ret; + return [ $ret, $lastError, $lastErrno, $recoverableSR, $recoverableCL, $reconnected ]; } /** @@ -1407,7 +1458,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware * @param string $fname * @throws DBTransactionStateError */ - private function assertTransactionStatus( $sql, $fname ) { + private function assertQueryIsCurrentlyAllowed( $sql, $fname ) { $verb = $this->getQueryVerb( $sql ); if ( $verb === 'USE' ) { throw new DBUnexpectedError( $this, "Got USE query; use selectDomain() instead." ); diff --git a/includes/libs/rdbms/database/DatabaseMssql.php b/includes/libs/rdbms/database/DatabaseMssql.php index a532ec2810..56320273f6 100644 --- a/includes/libs/rdbms/database/DatabaseMssql.php +++ b/includes/libs/rdbms/database/DatabaseMssql.php @@ -1167,10 +1167,13 @@ class DatabaseMssql extends Database { $database = $domain->getDatabase(); if ( $database !== $this->getDBname() ) { - $encDatabase = $this->addIdentifierQuotes( $database ); - $res = $this->doQuery( "USE $encDatabase" ); - if ( !$res ) { - throw new DBExpectedError( $this, "Could not select database '$database'." ); + $sql = 'USE ' . $this->addIdentifierQuotes( $database ); + list( $res, $err, $errno ) = + $this->executeQuery( $sql, __METHOD__, self::QUERY_IGNORE_DBO_TRX ); + + if ( $res === false ) { + $this->reportQueryError( $err, $errno, $sql, __METHOD__ ); + return false; // unreachable } } // Update that domain fields on success (no exception thrown) diff --git a/includes/libs/rdbms/database/DatabaseMysqlBase.php b/includes/libs/rdbms/database/DatabaseMysqlBase.php index 6d28717abf..b9d1df040f 100644 --- a/includes/libs/rdbms/database/DatabaseMysqlBase.php +++ b/includes/libs/rdbms/database/DatabaseMysqlBase.php @@ -244,11 +244,12 @@ abstract class DatabaseMysqlBase extends Database { if ( $database !== $this->getDBname() ) { $sql = 'USE ' . $this->addIdentifierQuotes( $database ); - $ret = $this->doQuery( $sql ); - if ( $ret === false ) { - $error = $this->lastError(); - $errno = $this->lastErrno(); - $this->reportQueryError( $error, $errno, $sql, __METHOD__ ); + list( $res, $err, $errno ) = + $this->executeQuery( $sql, __METHOD__, self::QUERY_IGNORE_DBO_TRX ); + + if ( $res === false ) { + $this->reportQueryError( $err, $errno, $sql, __METHOD__ ); + return false; // unreachable } } @@ -952,21 +953,22 @@ abstract class DatabaseMysqlBase extends Database { $gtidArg = $this->addQuotes( implode( ',', $gtidsWait ) ); if ( strpos( $gtidArg, ':' ) !== false ) { // MySQL GTIDs, e.g "source_id:transaction_id" - $res = $this->doQuery( "SELECT WAIT_FOR_EXECUTED_GTID_SET($gtidArg, $timeout)" ); + $sql = "SELECT WAIT_FOR_EXECUTED_GTID_SET($gtidArg, $timeout)"; } else { // MariaDB GTIDs, e.g."domain:server:sequence" - $res = $this->doQuery( "SELECT MASTER_GTID_WAIT($gtidArg, $timeout)" ); + $sql = "SELECT MASTER_GTID_WAIT($gtidArg, $timeout)"; } } else { // Wait on the binlog coordinates $encFile = $this->addQuotes( $pos->getLogFile() ); $encPos = intval( $pos->getLogPosition()[$pos::CORD_EVENT] ); - $res = $this->doQuery( "SELECT MASTER_POS_WAIT($encFile, $encPos, $timeout)" ); + $sql = "SELECT MASTER_POS_WAIT($encFile, $encPos, $timeout)"; } + list( $res, $err ) = $this->executeQuery( $sql, __METHOD__, self::QUERY_IGNORE_DBO_TRX ); $row = $res ? $this->fetchRow( $res ) : false; if ( !$row ) { - throw new DBExpectedError( $this, "Replication wait failed: {$this->lastError()}" ); + throw new DBExpectedError( $this, "Replication wait failed: {$err}" ); } // Result can be NULL (error), -1 (timeout), or 0+ per the MySQL manual diff --git a/includes/libs/rdbms/database/IDatabase.php b/includes/libs/rdbms/database/IDatabase.php index 90e30fa08e..09a8090611 100644 --- a/includes/libs/rdbms/database/IDatabase.php +++ b/includes/libs/rdbms/database/IDatabase.php @@ -115,6 +115,8 @@ interface IDatabase { const QUERY_PSEUDO_PERMANENT = 2; /** @var int Enforce that a query does not make effective writes */ const QUERY_REPLICA_ROLE = 4; + /** @var int Ignore the current presence of any DBO_TRX flag */ + const QUERY_IGNORE_DBO_TRX = 8; /** @var bool Parameter to unionQueries() for UNION ALL */ const UNION_ALL = true; diff --git a/includes/page/ImagePage.php b/includes/page/ImagePage.php index e929ed8a73..12cfe831f5 100644 --- a/includes/page/ImagePage.php +++ b/includes/page/ImagePage.php @@ -935,7 +935,7 @@ EOT ) . "\n" ); - }; + } $out->addHTML( Html::closeElement( 'ul' ) . "\n" ); $res->free(); diff --git a/includes/password/LayeredParameterizedPassword.php b/includes/password/LayeredParameterizedPassword.php index 841305481a..f3d8d03e30 100644 --- a/includes/password/LayeredParameterizedPassword.php +++ b/includes/password/LayeredParameterizedPassword.php @@ -109,7 +109,7 @@ class LayeredParameterizedPassword extends ParameterizedPassword { foreach ( $this->config['types'] as $i => $type ) { if ( $i == 0 ) { continue; - }; + } // Construct pseudo-hash based on params and arguments /** @var ParameterizedPassword $passObj */ diff --git a/includes/resourceloader/ResourceLoaderFileModule.php b/includes/resourceloader/ResourceLoaderFileModule.php index 031541b559..015c8285f1 100644 --- a/includes/resourceloader/ResourceLoaderFileModule.php +++ b/includes/resourceloader/ResourceLoaderFileModule.php @@ -617,7 +617,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule { 'raw', ] as $member ) { $options[$member] = $this->{$member}; - }; + } $summary[] = [ 'options' => $options, diff --git a/includes/resourceloader/ResourceLoaderImageModule.php b/includes/resourceloader/ResourceLoaderImageModule.php index 9b50d80f69..db292ccdda 100644 --- a/includes/resourceloader/ResourceLoaderImageModule.php +++ b/includes/resourceloader/ResourceLoaderImageModule.php @@ -113,7 +113,7 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { * @throws InvalidArgumentException */ public function __construct( $options = [], $localBasePath = null ) { - $this->localBasePath = self::extractLocalBasePath( $options, $localBasePath ); + $this->localBasePath = static::extractLocalBasePath( $options, $localBasePath ); $this->definition = $options; } diff --git a/includes/resourceloader/ResourceLoaderOOUIIconPackModule.php b/includes/resourceloader/ResourceLoaderOOUIIconPackModule.php new file mode 100644 index 0000000000..c860362af7 --- /dev/null +++ b/includes/resourceloader/ResourceLoaderOOUIIconPackModule.php @@ -0,0 +1,81 @@ +definition['icons'] ) || !$this->definition['icons'] ) { + throw new InvalidArgumentException( "Parameter 'icons' must be given." ); + } + + // A few things check for the "icons" prefix on this value, so specify it even though + // we don't use it for actually loading the data, like in the other modules. + $this->definition['themeImages'] = 'icons'; + } + + private function getIcons() { + return $this->definition['icons']; + } + + protected function loadOOUIDefinition( $theme, $unused ) { + // This is shared between instances of this class, so we only have to load the JSON files once + static $data = []; + + if ( !isset( $data[$theme] ) ) { + $data[$theme] = []; + // Load and merge the JSON data for all "icons-foo" modules + foreach ( self::$knownImagesModules as $module ) { + if ( substr( $module, 0, 5 ) === 'icons' ) { + $moreData = $this->readJSONFile( $this->getThemeImagesPath( $theme, $module ) ); + if ( $moreData ) { + $data[$theme] = array_replace_recursive( $data[$theme], $moreData ); + } + } + } + } + + $definition = $data[$theme]; + + // Filter out the data for all other icons, leaving only the ones we want for this module + $iconsNames = $this->getIcons(); + foreach ( array_keys( $definition['images'] ) as $iconName ) { + if ( !in_array( $iconName, $iconsNames ) ) { + unset( $definition['images'][$iconName] ); + } + } + + return $definition; + } + + public static function extractLocalBasePath( $options, $localBasePath = null ) { + global $IP; + if ( $localBasePath === null ) { + $localBasePath = $IP; + } + // Ignore any 'localBasePath' present in $options, this always refers to files in MediaWiki core + return $localBasePath; + } +} diff --git a/includes/resourceloader/ResourceLoaderOOUIImageModule.php b/includes/resourceloader/ResourceLoaderOOUIImageModule.php index 313d789249..34079c3b7b 100644 --- a/includes/resourceloader/ResourceLoaderOOUIImageModule.php +++ b/includes/resourceloader/ResourceLoaderOOUIImageModule.php @@ -19,7 +19,8 @@ */ /** - * Secret special sauce. + * Loads the module definition from JSON files in the format that OOUI uses, converting it to the + * format we use. (Previously known as secret special sauce.) * * @since 1.26 */ @@ -39,36 +40,12 @@ class ResourceLoaderOOUIImageModule extends ResourceLoaderImageModule { $definition = []; foreach ( $themes as $skin => $theme ) { - // Find the path to the JSON file which contains the actual image definitions for this theme - if ( $module ) { - $dataPath = $this->getThemeImagesPath( $theme, $module ); - } else { - // Backwards-compatibility for things that probably shouldn't have used this class... - $dataPath = - $this->definition['rootPath'] . '/' . - strtolower( $theme ) . '/' . - $this->definition['name'] . '.json'; - } - $localDataPath = $this->localBasePath . '/' . $dataPath; + $data = $this->loadOOUIDefinition( $theme, $module ); - // If there's no file for this module of this theme, that's okay, it will just use the defaults - if ( !file_exists( $localDataPath ) ) { + if ( !$data ) { + // If there's no file for this module of this theme, that's okay, it will just use the defaults continue; } - $data = json_decode( file_get_contents( $localDataPath ), true ); - - // Expand the paths to images (since they are relative to the JSON file that defines them, not - // our base directory) - $fixPath = function ( &$path ) use ( $dataPath ) { - $path = dirname( $dataPath ) . '/' . $path; - }; - array_walk( $data['images'], function ( &$value ) use ( $fixPath ) { - if ( is_string( $value['file'] ) ) { - $fixPath( $value['file'] ); - } elseif ( is_array( $value['file'] ) ) { - array_walk_recursive( $value['file'], $fixPath ); - } - } ); // Convert into a definition compatible with the parent vanilla ResourceLoaderImageModule foreach ( $data as $key => $value ) { @@ -107,4 +84,59 @@ class ResourceLoaderOOUIImageModule extends ResourceLoaderImageModule { parent::loadFromDefinition(); } + + /** + * Load the module definition from the JSON file(s) for the given theme and module. + * + * @since 1.34 + * @param string $theme + * @param string $module + * @return array + */ + protected function loadOOUIDefinition( $theme, $module ) { + // Find the path to the JSON file which contains the actual image definitions for this theme + if ( $module ) { + $dataPath = $this->getThemeImagesPath( $theme, $module ); + } else { + // Backwards-compatibility for things that probably shouldn't have used this class... + $dataPath = + $this->definition['rootPath'] . '/' . + strtolower( $theme ) . '/' . + $this->definition['name'] . '.json'; + } + + return $this->readJSONFile( $dataPath ); + } + + /** + * Read JSON from a file, and transform all paths in it to be relative to the module's base path. + * + * @since 1.34 + * @param string $dataPath Path relative to the module's base bath + * @return array|false + */ + protected function readJSONFile( $dataPath ) { + $localDataPath = $this->localBasePath . '/' . $dataPath; + + if ( !file_exists( $localDataPath ) ) { + return false; + } + + $data = json_decode( file_get_contents( $localDataPath ), true ); + + // Expand the paths to images (since they are relative to the JSON file that defines them, not + // our base directory) + $fixPath = function ( &$path ) use ( $dataPath ) { + $path = dirname( $dataPath ) . '/' . $path; + }; + array_walk( $data['images'], function ( &$value ) use ( $fixPath ) { + if ( is_string( $value['file'] ) ) { + $fixPath( $value['file'] ); + } elseif ( is_array( $value['file'] ) ) { + array_walk_recursive( $value['file'], $fixPath ); + } + } ); + + return $data; + } } diff --git a/maintenance/cleanupPreferences.php b/maintenance/cleanupPreferences.php index 66fc6d374e..bed3956a88 100644 --- a/maintenance/cleanupPreferences.php +++ b/maintenance/cleanupPreferences.php @@ -34,7 +34,9 @@ require_once __DIR__ . '/Maintenance.php'; class CleanupPreferences extends Maintenance { public function __construct() { parent::__construct(); - $this->mDescription = 'Clean up hidden preferences, removed preferences, and normalizes values'; + $this->addDescription( + 'Clean up hidden preferences, removed preferences, and normalizes values' + ); $this->setBatchSize( 50 ); $this->addOption( 'dry-run', 'Print debug info instead of actually deleting' ); $this->addOption( 'hidden', 'Drop hidden preferences ($wgHiddenPrefs)' ); diff --git a/maintenance/importTextFiles.php b/maintenance/importTextFiles.php index c99aa15531..0b5cdf99bd 100644 --- a/maintenance/importTextFiles.php +++ b/maintenance/importTextFiles.php @@ -76,7 +76,7 @@ class ImportTextFiles extends Maintenance { $this->fatalError( "Fatal error: The file '$arg' does not exist!" ); } } - }; + } $count = count( $files ); $this->output( "Importing $count pages...\n" ); diff --git a/maintenance/includes/DeleteLocalPasswords.php b/maintenance/includes/DeleteLocalPasswords.php index a79d9f3170..c9b3b66960 100644 --- a/maintenance/includes/DeleteLocalPasswords.php +++ b/maintenance/includes/DeleteLocalPasswords.php @@ -50,7 +50,7 @@ class DeleteLocalPasswords extends Maintenance { public function __construct() { parent::__construct(); - $this->mDescription = "Deletes local password for users."; + $this->addDescription( "Deletes local password for users." ); $this->setBatchSize( 1000 ); $this->addOption( 'user', 'If specified, only checks the given user', false, true ); diff --git a/resources/Resources.php b/resources/Resources.php index ecdd43fb83..b90ead4c45 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -615,11 +615,6 @@ return [ 'dependencies' => 'jquery.effects.core', 'group' => 'jquery.ui', ], - 'jquery.effects.bounce' => [ - 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-bounce.js', - 'dependencies' => 'jquery.effects.core', - 'group' => 'jquery.ui', - ], 'jquery.effects.clip' => [ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-clip.js', 'dependencies' => 'jquery.effects.core', @@ -630,31 +625,11 @@ return [ 'dependencies' => 'jquery.effects.core', 'group' => 'jquery.ui', ], - 'jquery.effects.explode' => [ - 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-explode.js', - 'dependencies' => 'jquery.effects.core', - 'group' => 'jquery.ui', - ], - 'jquery.effects.fade' => [ - 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-fade.js', - 'dependencies' => 'jquery.effects.core', - 'group' => 'jquery.ui', - ], - 'jquery.effects.fold' => [ - 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-fold.js', - 'dependencies' => 'jquery.effects.core', - 'group' => 'jquery.ui', - ], 'jquery.effects.highlight' => [ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-highlight.js', 'dependencies' => 'jquery.effects.core', 'group' => 'jquery.ui', ], - 'jquery.effects.pulsate' => [ - 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-pulsate.js', - 'dependencies' => 'jquery.effects.core', - 'group' => 'jquery.ui', - ], 'jquery.effects.scale' => [ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-scale.js', 'dependencies' => 'jquery.effects.core', @@ -665,16 +640,6 @@ return [ 'dependencies' => 'jquery.effects.core', 'group' => 'jquery.ui', ], - 'jquery.effects.slide' => [ - 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-slide.js', - 'dependencies' => 'jquery.effects.core', - 'group' => 'jquery.ui', - ], - 'jquery.effects.transfer' => [ - 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-transfer.js', - 'dependencies' => 'jquery.effects.core', - 'group' => 'jquery.ui', - ], /* Moment.js */ @@ -2932,12 +2897,10 @@ return [ 'dependencies' => [ 'oojs', 'oojs-ui-core.styles', + 'oojs-ui-core.icons', 'oojs-ui.styles.indicators', 'oojs-ui.styles.textures', 'mediawiki.language', - 'oojs-ui.styles.icons-content', - 'oojs-ui.styles.icons-alerts', - 'oojs-ui.styles.icons-interactions', ], 'messages' => [ 'ooui-field-help', @@ -2954,6 +2917,11 @@ return [ 'themeStyles' => 'core', 'targets' => [ 'desktop', 'mobile' ], ], + 'oojs-ui-core.icons' => [ + 'class' => ResourceLoaderOOUIIconPackModule::class, + 'icons' => [ 'add', 'alert', 'notice', 'error', 'check', 'close', 'info', 'search', 'subtract' ], + 'targets' => [ 'desktop', 'mobile' ], + ], // Additional widgets and layouts module. 'oojs-ui-widgets' => [ 'class' => ResourceLoaderOOUIFileModule::class, @@ -2961,11 +2929,7 @@ return [ 'themeStyles' => 'widgets', 'dependencies' => [ 'oojs-ui-core', - 'oojs-ui.styles.icons-interactions', - 'oojs-ui.styles.icons-content', - 'oojs-ui.styles.icons-editing-advanced', - 'oojs-ui.styles.icons-movement', - 'oojs-ui.styles.icons-moderation', + 'oojs-ui-widgets.icons', ], 'messages' => [ 'ooui-item-remove', @@ -2987,6 +2951,12 @@ return [ 'themeStyles' => 'widgets', 'targets' => [ 'desktop', 'mobile' ], ], + 'oojs-ui-widgets.icons' => [ + 'class' => ResourceLoaderOOUIIconPackModule::class, + // Do not repeat icons already used in 'oojs-ui-core.icons' + 'icons' => [ 'attachment', 'collapse', 'expand', 'trash', 'upload' ], + 'targets' => [ 'desktop', 'mobile' ], + ], // Toolbar and tools module. 'oojs-ui-toolbars' => [ 'class' => ResourceLoaderOOUIFileModule::class, @@ -2994,7 +2964,7 @@ return [ 'themeStyles' => 'toolbars', 'dependencies' => [ 'oojs-ui-core', - 'oojs-ui.styles.icons-movement', + 'oojs-ui-toolbars.icons', ], 'messages' => [ 'ooui-toolbar-more', @@ -3003,6 +2973,12 @@ return [ ], 'targets' => [ 'desktop', 'mobile' ], ], + 'oojs-ui-toolbars.icons' => [ + 'class' => ResourceLoaderOOUIIconPackModule::class, + // Do not repeat icons already used in 'oojs-ui-core.icons': 'check' + 'icons' => [ 'collapse', 'expand' ], + 'targets' => [ 'desktop', 'mobile' ], + ], // Windows and dialogs module. 'oojs-ui-windows' => [ 'class' => ResourceLoaderOOUIFileModule::class, @@ -3010,7 +2986,7 @@ return [ 'themeStyles' => 'windows', 'dependencies' => [ 'oojs-ui-core', - 'oojs-ui.styles.icons-movement', + 'oojs-ui-windows.icons', ], 'messages' => [ 'ooui-dialog-message-accept', @@ -3022,6 +2998,12 @@ return [ ], 'targets' => [ 'desktop', 'mobile' ], ], + 'oojs-ui-windows.icons' => [ + 'class' => ResourceLoaderOOUIIconPackModule::class, + // Do not repeat icons already used in 'oojs-ui-core.icons': 'close' + 'icons' => [ 'previous' ], + 'targets' => [ 'desktop', 'mobile' ], + ], 'oojs-ui.styles.indicators' => [ 'class' => ResourceLoaderOOUIImageModule::class, diff --git a/resources/lib/jquery.ui/jquery.ui.effect-bounce.js b/resources/lib/jquery.ui/jquery.ui.effect-bounce.js deleted file mode 100644 index ab1977ef68..0000000000 --- a/resources/lib/jquery.ui/jquery.ui.effect-bounce.js +++ /dev/null @@ -1,113 +0,0 @@ -/*! - * jQuery UI Effects Bounce 1.9.2 - * http://jqueryui.com - * - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/bounce-effect/ - * - * Depends: - * jquery.ui.effect.js - */ -(function( $, undefined ) { - -$.effects.effect.bounce = function( o, done ) { - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "height", "width" ], - - // defaults: - mode = $.effects.setMode( el, o.mode || "effect" ), - hide = mode === "hide", - show = mode === "show", - direction = o.direction || "up", - distance = o.distance, - times = o.times || 5, - - // number of internal animations - anims = times * 2 + ( show || hide ? 1 : 0 ), - speed = o.duration / anims, - easing = o.easing, - - // utility: - ref = ( direction === "up" || direction === "down" ) ? "top" : "left", - motion = ( direction === "up" || direction === "left" ), - i, - upAnim, - downAnim, - - // we will need to re-assemble the queue to stack our animations in place - queue = el.queue(), - queuelen = queue.length; - - // Avoid touching opacity to prevent clearType and PNG issues in IE - if ( show || hide ) { - props.push( "opacity" ); - } - - $.effects.save( el, props ); - el.show(); - $.effects.createWrapper( el ); // Create Wrapper - - // default distance for the BIGGEST bounce is the outer Distance / 3 - if ( !distance ) { - distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; - } - - if ( show ) { - downAnim = { opacity: 1 }; - downAnim[ ref ] = 0; - - // if we are showing, force opacity 0 and set the initial position - // then do the "first" animation - el.css( "opacity", 0 ) - .css( ref, motion ? -distance * 2 : distance * 2 ) - .animate( downAnim, speed, easing ); - } - - // start at the smallest distance if we are hiding - if ( hide ) { - distance = distance / Math.pow( 2, times - 1 ); - } - - downAnim = {}; - downAnim[ ref ] = 0; - // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here - for ( i = 0; i < times; i++ ) { - upAnim = {}; - upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; - - el.animate( upAnim, speed, easing ) - .animate( downAnim, speed, easing ); - - distance = hide ? distance * 2 : distance / 2; - } - - // Last Bounce when Hiding - if ( hide ) { - upAnim = { opacity: 0 }; - upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; - - el.animate( upAnim, speed, easing ); - } - - el.queue(function() { - if ( hide ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - }); - - // inject all the animations we just queued to be first in line (after "inprogress") - if ( queuelen > 1) { - queue.splice.apply( queue, - [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); - } - el.dequeue(); - -}; - -})(jQuery); diff --git a/resources/lib/jquery.ui/jquery.ui.effect-explode.js b/resources/lib/jquery.ui/jquery.ui.effect-explode.js deleted file mode 100644 index 98d5be5c0b..0000000000 --- a/resources/lib/jquery.ui/jquery.ui.effect-explode.js +++ /dev/null @@ -1,97 +0,0 @@ -/*! - * jQuery UI Effects Explode 1.9.2 - * http://jqueryui.com - * - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/explode-effect/ - * - * Depends: - * jquery.ui.effect.js - */ -(function( $, undefined ) { - -$.effects.effect.explode = function( o, done ) { - - var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, - cells = rows, - el = $( this ), - mode = $.effects.setMode( el, o.mode || "hide" ), - show = mode === "show", - - // show and then visibility:hidden the element before calculating offset - offset = el.show().css( "visibility", "hidden" ).offset(), - - // width and height of a piece - width = Math.ceil( el.outerWidth() / cells ), - height = Math.ceil( el.outerHeight() / rows ), - pieces = [], - - // loop - i, j, left, top, mx, my; - - // children animate complete: - function childComplete() { - pieces.push( this ); - if ( pieces.length === rows * cells ) { - animComplete(); - } - } - - // clone the element for each row and cell. - for( i = 0; i < rows ; i++ ) { // ===> - top = offset.top + i * height; - my = i - ( rows - 1 ) / 2 ; - - for( j = 0; j < cells ; j++ ) { // ||| - left = offset.left + j * width; - mx = j - ( cells - 1 ) / 2 ; - - // Create a clone of the now hidden main element that will be absolute positioned - // within a wrapper div off the -left and -top equal to size of our pieces - el - .clone() - .appendTo( "body" ) - .wrap( "
" ) - .css({ - position: "absolute", - visibility: "visible", - left: -j * width, - top: -i * height - }) - - // select the wrapper - make it overflow: hidden and absolute positioned based on - // where the original was located +left and +top equal to the size of pieces - .parent() - .addClass( "ui-effects-explode" ) - .css({ - position: "absolute", - overflow: "hidden", - width: width, - height: height, - left: left + ( show ? mx * width : 0 ), - top: top + ( show ? my * height : 0 ), - opacity: show ? 0 : 1 - }).animate({ - left: left + ( show ? 0 : mx * width ), - top: top + ( show ? 0 : my * height ), - opacity: show ? 1 : 0 - }, o.duration || 500, o.easing, childComplete ); - } - } - - function animComplete() { - el.css({ - visibility: "visible" - }); - $( pieces ).remove(); - if ( !show ) { - el.hide(); - } - done(); - } -}; - -})(jQuery); diff --git a/resources/lib/jquery.ui/jquery.ui.effect-fold.js b/resources/lib/jquery.ui/jquery.ui.effect-fold.js deleted file mode 100644 index 9452c5da22..0000000000 --- a/resources/lib/jquery.ui/jquery.ui.effect-fold.js +++ /dev/null @@ -1,76 +0,0 @@ -/*! - * jQuery UI Effects Fold 1.9.2 - * http://jqueryui.com - * - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/fold-effect/ - * - * Depends: - * jquery.ui.effect.js - */ -(function( $, undefined ) { - -$.effects.effect.fold = function( o, done ) { - - // Create element - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "height", "width" ], - mode = $.effects.setMode( el, o.mode || "hide" ), - show = mode === "show", - hide = mode === "hide", - size = o.size || 15, - percent = /([0-9]+)%/.exec( size ), - horizFirst = !!o.horizFirst, - widthFirst = show !== horizFirst, - ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], - duration = o.duration / 2, - wrapper, distance, - animation1 = {}, - animation2 = {}; - - $.effects.save( el, props ); - el.show(); - - // Create Wrapper - wrapper = $.effects.createWrapper( el ).css({ - overflow: "hidden" - }); - distance = widthFirst ? - [ wrapper.width(), wrapper.height() ] : - [ wrapper.height(), wrapper.width() ]; - - if ( percent ) { - size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; - } - if ( show ) { - wrapper.css( horizFirst ? { - height: 0, - width: size - } : { - height: size, - width: 0 - }); - } - - // Animation - animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; - animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; - - // Animate - wrapper - .animate( animation1, duration, o.easing ) - .animate( animation2, duration, o.easing, function() { - if ( hide ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - }); - -}; - -})(jQuery); diff --git a/resources/lib/jquery.ui/jquery.ui.effect-pulsate.js b/resources/lib/jquery.ui/jquery.ui.effect-pulsate.js deleted file mode 100644 index 20f84dd3e3..0000000000 --- a/resources/lib/jquery.ui/jquery.ui.effect-pulsate.js +++ /dev/null @@ -1,63 +0,0 @@ -/*! - * jQuery UI Effects Pulsate 1.9.2 - * http://jqueryui.com - * - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/pulsate-effect/ - * - * Depends: - * jquery.ui.effect.js - */ -(function( $, undefined ) { - -$.effects.effect.pulsate = function( o, done ) { - var elem = $( this ), - mode = $.effects.setMode( elem, o.mode || "show" ), - show = mode === "show", - hide = mode === "hide", - showhide = ( show || mode === "hide" ), - - // showing or hiding leaves of the "last" animation - anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), - duration = o.duration / anims, - animateTo = 0, - queue = elem.queue(), - queuelen = queue.length, - i; - - if ( show || !elem.is(":visible")) { - elem.css( "opacity", 0 ).show(); - animateTo = 1; - } - - // anims - 1 opacity "toggles" - for ( i = 1; i < anims; i++ ) { - elem.animate({ - opacity: animateTo - }, duration, o.easing ); - animateTo = 1 - animateTo; - } - - elem.animate({ - opacity: animateTo - }, duration, o.easing); - - elem.queue(function() { - if ( hide ) { - elem.hide(); - } - done(); - }); - - // We just queued up "anims" animations, we need to put them next in the queue - if ( queuelen > 1 ) { - queue.splice.apply( queue, - [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); - } - elem.dequeue(); -}; - -})(jQuery); diff --git a/resources/lib/jquery.ui/jquery.ui.effect-slide.js b/resources/lib/jquery.ui/jquery.ui.effect-slide.js deleted file mode 100644 index 445ec48ec7..0000000000 --- a/resources/lib/jquery.ui/jquery.ui.effect-slide.js +++ /dev/null @@ -1,64 +0,0 @@ -/*! - * jQuery UI Effects Slide 1.9.2 - * http://jqueryui.com - * - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/slide-effect/ - * - * Depends: - * jquery.ui.effect.js - */ -(function( $, undefined ) { - -$.effects.effect.slide = function( o, done ) { - - // Create element - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "width", "height" ], - mode = $.effects.setMode( el, o.mode || "show" ), - show = mode === "show", - direction = o.direction || "left", - ref = (direction === "up" || direction === "down") ? "top" : "left", - positiveMotion = (direction === "up" || direction === "left"), - distance, - animation = {}; - - // Adjust - $.effects.save( el, props ); - el.show(); - distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); - - $.effects.createWrapper( el ).css({ - overflow: "hidden" - }); - - if ( show ) { - el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); - } - - // Animation - animation[ ref ] = ( show ? - ( positiveMotion ? "+=" : "-=") : - ( positiveMotion ? "-=" : "+=")) + - distance; - - // Animate - el.animate( animation, { - queue: false, - duration: o.duration, - easing: o.easing, - complete: function() { - if ( mode === "hide" ) { - el.hide(); - } - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - done(); - } - }); -}; - -})(jQuery); diff --git a/resources/lib/jquery.ui/jquery.ui.effect-transfer.js b/resources/lib/jquery.ui/jquery.ui.effect-transfer.js deleted file mode 100644 index f133c04ba8..0000000000 --- a/resources/lib/jquery.ui/jquery.ui.effect-transfer.js +++ /dev/null @@ -1,47 +0,0 @@ -/*! - * jQuery UI Effects Transfer 1.9.2 - * http://jqueryui.com - * - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/transfer-effect/ - * - * Depends: - * jquery.ui.effect.js - */ -(function( $, undefined ) { - -$.effects.effect.transfer = function( o, done ) { - var elem = $( this ), - target = $( o.to ), - targetFixed = target.css( "position" ) === "fixed", - body = $("body"), - fixTop = targetFixed ? body.scrollTop() : 0, - fixLeft = targetFixed ? body.scrollLeft() : 0, - endPosition = target.offset(), - animation = { - top: endPosition.top - fixTop , - left: endPosition.left - fixLeft , - height: target.innerHeight(), - width: target.innerWidth() - }, - startPosition = elem.offset(), - transfer = $( '
' ) - .appendTo( document.body ) - .addClass( o.className ) - .css({ - top: startPosition.top - fixTop , - left: startPosition.left - fixLeft , - height: elem.innerHeight(), - width: elem.innerWidth(), - position: targetFixed ? "fixed" : "absolute" - }) - .animate( animation, o.duration, o.easing, function() { - transfer.remove(); - done(); - }); -}; - -})(jQuery); diff --git a/resources/src/jquery/jquery.suggestions.js b/resources/src/jquery/jquery.suggestions.js index 26028e7b65..3083b0f58c 100644 --- a/resources/src/jquery/jquery.suggestions.js +++ b/resources/src/jquery/jquery.suggestions.js @@ -767,7 +767,7 @@ } ); // Load suggestions if the value is changed because there are already // typed characters before the JavaScript is loaded. - if ( this.value !== this.defaultValue ) { + if ( $( this ).is( ':focus' ) && this.value !== this.defaultValue ) { update( context, false ); } } diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less index 198c8209e9..70a81631f8 100644 --- a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less +++ b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less @@ -17,6 +17,7 @@ &-body { max-height: 70vh; + min-width: 100%; } &-footer { diff --git a/resources/src/mediawiki.rcfilters/ui/FilterTagMultiselectWidget.js b/resources/src/mediawiki.rcfilters/ui/FilterTagMultiselectWidget.js index 085e22b0ac..ab75653db7 100644 --- a/resources/src/mediawiki.rcfilters/ui/FilterTagMultiselectWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/FilterTagMultiselectWidget.js @@ -267,11 +267,6 @@ OO.inheritClass( FilterTagMultiselectWidget, OO.ui.MenuTagMultiselectWidget ); /* Methods */ -/** - * Override parent method to avoid unnecessary resize events. - */ -FilterTagMultiselectWidget.prototype.updateIfHeightChanged = function () { }; - /** * Respond to view select widget choose event * diff --git a/tests/phpunit/ResourceLoaderTestCase.php b/tests/phpunit/ResourceLoaderTestCase.php index bd6df5f39c..3e4531cd5c 100644 --- a/tests/phpunit/ResourceLoaderTestCase.php +++ b/tests/phpunit/ResourceLoaderTestCase.php @@ -160,12 +160,13 @@ class ResourceLoaderTestModule extends ResourceLoaderModule { class ResourceLoaderFileTestModule extends ResourceLoaderFileModule { protected $lessVars = []; - public function __construct( $options = [], $test = [] ) { - parent::__construct( $options ); - - foreach ( $test as $key => $value ) { - $this->$key = $value; + public function __construct( $options = [] ) { + if ( isset( $options['lessVars'] ) ) { + $this->lessVars = $options['lessVars']; + unset( $options['lessVars'] ); } + + parent::__construct( $options ); } public function getLessVars( ResourceLoaderContext $context ) { diff --git a/tests/phpunit/includes/ActorMigrationTest.php b/tests/phpunit/includes/ActorMigrationTest.php index de70f261e4..40c45dc683 100644 --- a/tests/phpunit/includes/ActorMigrationTest.php +++ b/tests/phpunit/includes/ActorMigrationTest.php @@ -18,15 +18,6 @@ class ActorMigrationTest extends MediaWikiLangTestCase { 'actor', ]; - /** - * Create an ActorMigration for a particular stage - * @param int $stage - * @return ActorMigration - */ - protected function makeMigration( $stage ) { - return new ActorMigration( $stage ); - } - /** * @dataProvider provideConstructor * @param int $stage @@ -81,7 +72,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { * @param array $expect */ public function testGetJoin( $stage, $key, $expect ) { - $m = $this->makeMigration( $stage ); + $m = new ActorMigration( $stage ); $result = $m->getJoin( $key ); $this->assertEquals( $expect, $result ); } @@ -260,7 +251,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { $users = reset( $users ); } - $m = $this->makeMigration( $stage ); + $m = new ActorMigration( $stage ); $result = $m->getWhere( $this->db, $key, $users, $useId ); $this->assertEquals( $expect, $result ); } @@ -510,7 +501,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { $extraFields['ipb_address'] = __CLASS__ . "#{$stageNames[$writeStage]}"; } - $w = $this->makeMigration( $writeStage ); + $w = new ActorMigration( $writeStage ); $usesTemp = $key === 'rev_user'; if ( $usesTemp ) { @@ -543,7 +534,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { } foreach ( $possibleReadStages as $readStage ) { - $r = $this->makeMigration( $readStage ); + $r = new ActorMigration( $readStage ); $queryInfo = $r->getJoin( $key ); $row = $this->db->selectRow( @@ -615,7 +606,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { * @expectedExceptionMessage Must use getInsertValuesWithTempTable() for rev_user */ public function testInsertWrong( $stage ) { - $m = $this->makeMigration( $stage ); + $m = new ActorMigration( $stage ); $m->getInsertValues( $this->db, 'rev_user', $this->getTestUser()->getUser() ); } @@ -626,7 +617,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { * @expectedExceptionMessage Must use getInsertValues() for rc_user */ public function testInsertWithTempTableWrong( $stage ) { - $m = $this->makeMigration( $stage ); + $m = new ActorMigration( $stage ); $m->getInsertValuesWithTempTable( $this->db, 'rc_user', $this->getTestUser()->getUser() ); } @@ -639,7 +630,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { $wrap->formerTempTables += [ 'rc_user' => '1.30' ]; $this->hideDeprecated( 'ActorMigration::getInsertValuesWithTempTable for rc_user' ); - $m = $this->makeMigration( $stage ); + $m = new ActorMigration( $stage ); list( $fields, $callback ) = $m->getInsertValuesWithTempTable( $this->db, 'rc_user', $this->getTestUser()->getUser() ); $this->assertTrue( is_callable( $callback ) ); @@ -652,7 +643,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { * @expectedExceptionMessage $extra[rev_timestamp] is not provided */ public function testInsertWithTempTableCallbackMissingFields( $stage ) { - $m = $this->makeMigration( $stage ); + $m = new ActorMigration( $stage ); list( $fields, $callback ) = $m->getInsertValuesWithTempTable( $this->db, 'rev_user', $this->getTestUser()->getUser() ); $callback( 1, [] ); @@ -677,7 +668,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { list( $cFields, $cCallback ) = MediaWikiServices::getInstance()->getCommentStore() ->insertWithTempTable( $this->db, 'rev_comment', '' ); - $m = $this->makeMigration( $stage ); + $m = new ActorMigration( $stage ); list( $fields, $callback ) = $m->getInsertValuesWithTempTable( $this->db, 'rev_user', $userIdentity ); $extraFields = [ @@ -701,7 +692,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { (int)$row->rev_actor ); - $m = $this->makeMigration( $stage ); + $m = new ActorMigration( $stage ); $fields = $m->getInsertValues( $this->db, 'dummy_user', $userIdentity ); if ( $stage & SCHEMA_COMPAT_WRITE_OLD ) { $this->assertSame( $user->getId(), $fields['dummy_user'] ); @@ -730,7 +721,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase { * @param string $isNotAnon */ public function testIsAnon( $stage, $isAnon, $isNotAnon ) { - $m = $this->makeMigration( $stage ); + $m = new ActorMigration( $stage ); $this->assertSame( $isAnon, $m->isAnon( 'foo' ) ); $this->assertSame( $isNotAnon, $m->isNotAnon( 'foo' ) ); } diff --git a/tests/phpunit/includes/TitleArrayFromResultTest.php b/tests/phpunit/includes/TitleArrayFromResultTest.php index af49ecf73a..32c757101a 100644 --- a/tests/phpunit/includes/TitleArrayFromResultTest.php +++ b/tests/phpunit/includes/TitleArrayFromResultTest.php @@ -30,10 +30,6 @@ class TitleArrayFromResultTest extends PHPUnit\Framework\TestCase { return $row; } - private function getTitleArrayFromResult( $resultWrapper ) { - return new TitleArrayFromResult( $resultWrapper ); - } - /** * @covers TitleArrayFromResult::__construct */ @@ -41,7 +37,7 @@ class TitleArrayFromResultTest extends PHPUnit\Framework\TestCase { $row = false; $resultWrapper = $this->getMockResultWrapper( $row ); - $object = $this->getTitleArrayFromResult( $resultWrapper ); + $object = new TitleArrayFromResult( $resultWrapper ); $this->assertEquals( $resultWrapper, $object->res ); $this->assertSame( 0, $object->key ); @@ -57,7 +53,7 @@ class TitleArrayFromResultTest extends PHPUnit\Framework\TestCase { $row = $this->getRowWithTitle( $namespace, $title ); $resultWrapper = $this->getMockResultWrapper( $row ); - $object = $this->getTitleArrayFromResult( $resultWrapper ); + $object = new TitleArrayFromResult( $resultWrapper ); $this->assertEquals( $resultWrapper, $object->res ); $this->assertSame( 0, $object->key ); @@ -79,7 +75,7 @@ class TitleArrayFromResultTest extends PHPUnit\Framework\TestCase { * @covers TitleArrayFromResult::count */ public function testCountWithVaryingValues( $numRows ) { - $object = $this->getTitleArrayFromResult( $this->getMockResultWrapper( + $object = new TitleArrayFromResult( $this->getMockResultWrapper( $this->getRowWithTitle(), $numRows ) ); @@ -93,7 +89,7 @@ class TitleArrayFromResultTest extends PHPUnit\Framework\TestCase { $namespace = 0; $title = 'foo'; $row = $this->getRowWithTitle( $namespace, $title ); - $object = $this->getTitleArrayFromResult( $this->getMockResultWrapper( $row ) ); + $object = new TitleArrayFromResult( $this->getMockResultWrapper( $row ) ); $this->assertInstanceOf( Title::class, $object->current() ); $this->assertEquals( $namespace, $object->current->mNamespace ); $this->assertEquals( $title, $object->current->mTextform ); @@ -111,7 +107,7 @@ class TitleArrayFromResultTest extends PHPUnit\Framework\TestCase { * @covers TitleArrayFromResult::valid */ public function testValid( $input, $expected ) { - $object = $this->getTitleArrayFromResult( $this->getMockResultWrapper( $input ) ); + $object = new TitleArrayFromResult( $this->getMockResultWrapper( $input ) ); $this->assertEquals( $expected, $object->valid() ); } diff --git a/tests/phpunit/includes/api/ApiQueryLanguageinfoTest.php b/tests/phpunit/includes/api/ApiQueryLanguageinfoTest.php index f4bab029f5..6bbdd3bd53 100644 --- a/tests/phpunit/includes/api/ApiQueryLanguageinfoTest.php +++ b/tests/phpunit/includes/api/ApiQueryLanguageinfoTest.php @@ -1,10 +1,8 @@ getDataSource( $xml ); + $source = new ImportStringSource( $xml ); $importer = new WikiImporter( $source, @@ -82,7 +78,7 @@ EOF * @param string|null $redirectTitle */ public function testHandlePageContainsRedirect( $xml, $redirectTitle ) { - $source = $this->getDataSource( $xml ); + $source = new ImportStringSource( $xml ); $redirect = null; $callback = function ( Title $title, ForeignTitle $foreignTitle, $revCount, @@ -168,7 +164,7 @@ EOF * @param array|null $namespaces */ public function testSiteInfoContainsNamespaces( $xml, $namespaces ) { - $source = $this->getDataSource( $xml ); + $source = new ImportStringSource( $xml ); $importNamespaces = null; $callback = function ( array $siteinfo, $innerImporter ) use ( &$importNamespaces ) { @@ -253,7 +249,7 @@ EOF $n = ( $assign ? 1 : 0 ) + ( $create ? 2 : 0 ); // phpcs:disable Generic.Files.LineLength - $source = $this->getDataSource( << TestImportPage diff --git a/tests/phpunit/includes/jobqueue/JobQueueTest.php b/tests/phpunit/includes/jobqueue/JobQueueTest.php index ce07f78bab..8f8dde5559 100644 --- a/tests/phpunit/includes/jobqueue/JobQueueTest.php +++ b/tests/phpunit/includes/jobqueue/JobQueueTest.php @@ -48,7 +48,7 @@ class JobQueueTest extends MediaWikiTestCase { } catch ( MWException $e ) { // unsupported? // @todo What if it was another error? - }; + } } } diff --git a/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php b/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php index c0d25553dc..0e133d8c2c 100644 --- a/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php +++ b/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php @@ -1878,7 +1878,7 @@ class DatabaseSQLTest extends PHPUnit\Framework\TestCase { /** * @expectedException \Wikimedia\Rdbms\DBTransactionStateError - * @covers \Wikimedia\Rdbms\Database::assertTransactionStatus + * @covers \Wikimedia\Rdbms\Database::assertQueryIsCurrentlyAllowed */ public function testTransactionErrorState1() { $wrapper = TestingAccessWrapper::newFromObject( $this->database ); diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php index fbef12ea36..2aa0d27f99 100644 --- a/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php +++ b/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php @@ -347,7 +347,6 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase { $module = new ResourceLoaderFileTestModule( [ 'localBasePath' => $basePath, 'styles' => [ 'styles.less' ], - ], [ 'lessVars' => [ 'foo' => '2px', 'Foo' => '#eeeeee' ] ] ); $module->setName( 'test.less' ); @@ -355,27 +354,48 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase { $this->assertStringEqualsFile( $basePath . '/styles.css', $styles['all'] ); } + public function provideGetVersionHash() { + $a = []; + $b = [ + 'lessVars' => [ 'key' => 'value' ], + ]; + yield 'with and without Less variables' => [ $a, $b, false ]; + + $a = [ + 'lessVars' => [ 'key' => 'value1' ], + ]; + $b = [ + 'lessVars' => [ 'key' => 'value2' ], + ]; + yield 'different Less variables' => [ $a, $b, false ]; + + $x = [ + 'lessVars' => [ 'key' => 'value' ], + ]; + yield 'identical Less variables' => [ $x, $x, true ]; + } + /** + * @dataProvider provideGetVersionHash * @covers ResourceLoaderFileModule::getDefinitionSummary * @covers ResourceLoaderFileModule::getFileHashes */ - public function testGetVersionHash() { + public function testGetVersionHash( $a, $b, $isEqual ) { $context = $this->getResourceLoaderContext(); - // Less variables - $module = new ResourceLoaderFileTestModule(); - $version = $module->getVersionHash( $context ); - $module = new ResourceLoaderFileTestModule( [], [ - 'lessVars' => [ 'key' => 'value' ], - ] ); - $this->assertNotEquals( - $version, - $module->getVersionHash( $context ), - 'Using less variables is significant' + $moduleA = new ResourceLoaderFileTestModule( $a ); + $versionA = $moduleA->getVersionHash( $context ); + $moduleB = new ResourceLoaderFileTestModule( $b ); + $versionB = $moduleB->getVersionHash( $context ); + + $this->assertSame( + $isEqual, + ( $versionA === $versionB ), + 'Whether versions hashes are equal' ); } - public function providerGetScriptPackageFiles() { + public function provideGetScriptPackageFiles() { $basePath = __DIR__ . '/../../data/resourceloader'; $base = [ 'localBasePath' => $basePath ]; $commentScript = file_get_contents( "$basePath/script-comment.js" ); @@ -559,7 +579,7 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase { } /** - * @dataProvider providerGetScriptPackageFiles + * @dataProvider provideGetScriptPackageFiles * @covers ResourceLoaderFileModule::getScript * @covers ResourceLoaderFileModule::getPackageFiles * @covers ResourceLoaderFileModule::expandPackageFiles diff --git a/tests/phpunit/includes/user/UserArrayFromResultTest.php b/tests/phpunit/includes/user/UserArrayFromResultTest.php index beaacec800..4cbfe462dd 100644 --- a/tests/phpunit/includes/user/UserArrayFromResultTest.php +++ b/tests/phpunit/includes/user/UserArrayFromResultTest.php @@ -27,10 +27,6 @@ class UserArrayFromResultTest extends MediaWikiTestCase { return $row; } - private function getUserArrayFromResult( $resultWrapper ) { - return new UserArrayFromResult( $resultWrapper ); - } - /** * @covers UserArrayFromResult::__construct */ @@ -38,7 +34,7 @@ class UserArrayFromResultTest extends MediaWikiTestCase { $row = false; $resultWrapper = $this->getMockResultWrapper( $row ); - $object = $this->getUserArrayFromResult( $resultWrapper ); + $object = new UserArrayFromResult( $resultWrapper ); $this->assertEquals( $resultWrapper, $object->res ); $this->assertSame( 0, $object->key ); @@ -53,7 +49,7 @@ class UserArrayFromResultTest extends MediaWikiTestCase { $row = $this->getRowWithUsername( $username ); $resultWrapper = $this->getMockResultWrapper( $row ); - $object = $this->getUserArrayFromResult( $resultWrapper ); + $object = new UserArrayFromResult( $resultWrapper ); $this->assertEquals( $resultWrapper, $object->res ); $this->assertSame( 0, $object->key ); @@ -74,7 +70,7 @@ class UserArrayFromResultTest extends MediaWikiTestCase { * @covers UserArrayFromResult::count */ public function testCountWithVaryingValues( $numRows ) { - $object = $this->getUserArrayFromResult( $this->getMockResultWrapper( + $object = new UserArrayFromResult( $this->getMockResultWrapper( $this->getRowWithUsername(), $numRows ) ); @@ -87,7 +83,7 @@ class UserArrayFromResultTest extends MediaWikiTestCase { public function testCurrentAfterConstruction() { $username = 'addshore'; $userRow = $this->getRowWithUsername( $username ); - $object = $this->getUserArrayFromResult( $this->getMockResultWrapper( $userRow ) ); + $object = new UserArrayFromResult( $this->getMockResultWrapper( $userRow ) ); $this->assertInstanceOf( User::class, $object->current() ); $this->assertEquals( $username, $object->current()->mName ); } @@ -104,7 +100,7 @@ class UserArrayFromResultTest extends MediaWikiTestCase { * @covers UserArrayFromResult::valid */ public function testValid( $input, $expected ) { - $object = $this->getUserArrayFromResult( $this->getMockResultWrapper( $input ) ); + $object = new UserArrayFromResult( $this->getMockResultWrapper( $input ) ); $this->assertEquals( $expected, $object->valid() ); } diff --git a/tests/phpunit/structure/ApiPrefixUniquenessTest.php b/tests/phpunit/structure/ApiPrefixUniquenessTest.php index 4f95fbbb3e..4329867030 100644 --- a/tests/phpunit/structure/ApiPrefixUniquenessTest.php +++ b/tests/phpunit/structure/ApiPrefixUniquenessTest.php @@ -4,7 +4,6 @@ * Checks that all API query modules, core and extensions, have unique prefixes. * * @group API - * @coversNothing */ class ApiPrefixUniquenessTest extends MediaWikiTestCase { diff --git a/tests/phpunit/structure/ApiStructureTest.php b/tests/phpunit/structure/ApiStructureTest.php index 0d10a20b22..6b64b409c2 100644 --- a/tests/phpunit/structure/ApiStructureTest.php +++ b/tests/phpunit/structure/ApiStructureTest.php @@ -11,7 +11,6 @@ use Wikimedia\TestingAccessWrapper; * - do not have inconsistencies in the parameter definitions * * @group API - * @coversNothing */ class ApiStructureTest extends MediaWikiTestCase { diff --git a/tests/phpunit/structure/AutoLoaderStructureTest.php b/tests/phpunit/structure/AutoLoaderStructureTest.php index 4e1b00abba..37babcef14 100644 --- a/tests/phpunit/structure/AutoLoaderStructureTest.php +++ b/tests/phpunit/structure/AutoLoaderStructureTest.php @@ -1,8 +1,5 @@ getAllVisibleRights(), @@ -69,8 +66,6 @@ class AvailableRightsTest extends PHPUnit\Framework\TestCase { * Test, if for all rights a right- message exist, * which is used on Special:ListGroupRights as help text * Extensions and core - * - * @coversNothing */ public function testAllRightsWithMessage() { $this->checkMessagesExist( 'right-' ); diff --git a/tests/phpunit/structure/ContentHandlerSanityTest.php b/tests/phpunit/structure/ContentHandlerSanityTest.php index c75a9d02a3..c8bcd60de3 100644 --- a/tests/phpunit/structure/ContentHandlerSanityTest.php +++ b/tests/phpunit/structure/ContentHandlerSanityTest.php @@ -32,7 +32,6 @@ class ContentHandlerSanityTest extends MediaWikiTestCase { } /** - * @coversNothing * @dataProvider provideHandlers * @param ContentHandler $handler */ diff --git a/tests/phpunit/structure/DatabaseIntegrationTest.php b/tests/phpunit/structure/DatabaseIntegrationTest.php index 9c0a73de8d..b0c1c8f1f5 100644 --- a/tests/phpunit/structure/DatabaseIntegrationTest.php +++ b/tests/phpunit/structure/DatabaseIntegrationTest.php @@ -5,7 +5,6 @@ use Wikimedia\Rdbms\Database; /** * @group Database - * @coversNothing */ class DatabaseIntegrationTest extends MediaWikiTestCase { /** diff --git a/tests/phpunit/structure/ExtensionJsonValidationTest.php b/tests/phpunit/structure/ExtensionJsonValidationTest.php index dea8f5a541..60c97ccfac 100644 --- a/tests/phpunit/structure/ExtensionJsonValidationTest.php +++ b/tests/phpunit/structure/ExtensionJsonValidationTest.php @@ -19,8 +19,6 @@ /** * Validates all loaded extensions and skins using the ExtensionRegistry * against the extension.json schema in the docs/ folder. - * - * @coversNothing */ class ExtensionJsonValidationTest extends PHPUnit\Framework\TestCase { diff --git a/tests/phpunit/structure/PasswordPolicyStructureTest.php b/tests/phpunit/structure/PasswordPolicyStructureTest.php index 60ce575e4c..d7f865d2e7 100644 --- a/tests/phpunit/structure/PasswordPolicyStructureTest.php +++ b/tests/phpunit/structure/PasswordPolicyStructureTest.php @@ -1,8 +1,5 @@ mDescription = 'Create a specification for message parsing ini JSON format'; + $this->addDescription( 'Create a specification for message parsing ini JSON format' ); // add any other options here }