From: jenkins-bot Date: Tue, 10 Feb 2015 10:54:43 +0000 (+0000) Subject: Merge "Common interface for ImportStreamSource and ImportStringSource." X-Git-Tag: 1.31.0-rc.0~12473 X-Git-Url: https://git.heureux-cyclage.org/index.php?a=commitdiff_plain;h=3db3d168fd58524fe0c0522b46508cc52a811011;hp=891cc28a9793ba94429020b33b6f8d85aa409ef1;p=lhc%2Fweb%2Fwiklou.git Merge "Common interface for ImportStreamSource and ImportStringSource." --- diff --git a/.jscsrc b/.jscsrc index 2ebd40eeb8..34b2435a31 100644 --- a/.jscsrc +++ b/.jscsrc @@ -3,6 +3,10 @@ "disallowKeywordsOnNewLine": null, "disallowQuotedKeysInObjects": null, + "disallowImplicitTypeConversion": null, + "requireLineBreakAfterVariableAssignment": null, + "requireSpaceAfterLineComment": null, + "requireSpacesInsideParentheses": null, "requireSpacesInsideArrayBrackets": null, "validateIndentation": null } diff --git a/autoload.php b/autoload.php index c11a5bc3f1..d78b0ffa6e 100644 --- a/autoload.php +++ b/autoload.php @@ -746,6 +746,7 @@ $wgAutoloadLocalClasses = array( 'MessageBlobStore' => __DIR__ . '/includes/MessageBlobStore.php', 'MessageCache' => __DIR__ . '/includes/cache/MessageCache.php', 'MessageContent' => __DIR__ . '/includes/content/MessageContent.php', + 'MessageSpecifier' => __DIR__ . '/includes/libs/MessageSpecifier.php', 'MigrateUserGroup' => __DIR__ . '/maintenance/migrateUserGroup.php', 'MimeMagic' => __DIR__ . '/includes/MimeMagic.php', 'MinifyScript' => __DIR__ . '/maintenance/minify.php', @@ -1152,6 +1153,7 @@ $wgAutoloadLocalClasses = array( 'StatCounter' => __DIR__ . '/includes/StatCounter.php', 'StatsOutput' => __DIR__ . '/maintenance/language/StatOutputs.php', 'Status' => __DIR__ . '/includes/Status.php', + 'StatusValue' => __DIR__ . '/includes/libs/StatusValue.php', 'StorageTypeStats' => __DIR__ . '/maintenance/storage/storageTypeStats.php', 'StoreFileOp' => __DIR__ . '/includes/filebackend/FileOp.php', 'StreamFile' => __DIR__ . '/includes/StreamFile.php', diff --git a/composer.json b/composer.json index bae3b554fb..94bec94ac0 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ }, "require-dev": { "justinrainbow/json-schema": "~1.3", - "phpunit/phpunit": "*" + "phpunit/phpunit": "~4.5" }, "suggest": { "ext-fileinfo": "*", diff --git a/docs/extension.schema.json b/docs/extension.schema.json index 4583559698..33029bd436 100644 --- a/docs/extension.schema.json +++ b/docs/extension.schema.json @@ -273,6 +273,25 @@ "Unlicense" ] }, + "ResourceFileModulePaths": { + "type": "object", + "description": "Default paths to use for all ResourceLoader file modules", + "additionalProperties": false, + "properties": { + "localBasePath": { + "type": "string", + "description": "Base path to prepend to all local paths, relative to current directory" + }, + "remoteExtPath": { + "type": "string", + "description": "Base path to prepend to all remote paths, relative to $wgExtensionAssetsPath" + }, + "remoteSkinPath": { + "type": "string", + "description": "Base path to prepend to all remote paths, relative to $wgStylePath" + } + } + }, "ResourceLoaderModules": { "type": "object", "description": "ResourceLoader modules to register", diff --git a/img_auth.php b/img_auth.php index 51470b6e6b..f44cac0b97 100644 --- a/img_auth.php +++ b/img_auth.php @@ -201,7 +201,12 @@ function wfForbidden( $msg1, $msg2 ) { header( 'Cache-Control: no-cache' ); header( 'Content-Type: text/html; charset=utf-8' ); echo << + + +$msgHdr +

$msgHdr

$detailMsg

diff --git a/includes/Message.php b/includes/Message.php index 93a37cbb4d..49437f49ae 100644 --- a/includes/Message.php +++ b/includes/Message.php @@ -156,7 +156,7 @@ * * @since 1.17 */ -class Message { +class Message implements MessageSpecifier { /** * In which language to get this message. True, which is the default, @@ -276,7 +276,7 @@ class Message { * Returns the message key. * * If a list of multiple possible keys was supplied to the constructor, this method may - * return any of these keys. After the message ahs been fetched, this method will return + * return any of these keys. After the message has been fetched, this method will return * the key that was actually used to fetch the message. * * @since 1.21 diff --git a/includes/Status.php b/includes/Status.php index fb267bdeab..61a00470a5 100644 --- a/includes/Status.php +++ b/includes/Status.php @@ -38,41 +38,58 @@ * so that a lack of error-handling will be explicit. */ class Status { - /** @var bool */ - public $ok = true; + /** @var StatusValue */ + protected $sv; /** @var mixed */ public $value; - - /** Counters for batch operations */ - /** @var int */ + /** @var array Map of (key => bool) to indicate success of each part of batch operations */ + public $success = array(); + /** @var int Counter for batch operations */ public $successCount = 0; - - /** @var int */ + /** @var int Counter for batch operations */ public $failCount = 0; - /** Array to indicate which items of the batch operations were successful */ - /** @var array */ - public $success = array(); - - /** @var array */ - public $errors = array(); - /** @var callable */ public $cleanCallback = false; + /** + * @param StatusValue $sv [optional] + */ + public function __construct( StatusValue $sv = null ) { + $this->sv = ( $sv === null ) ? new StatusValue() : $sv; + // B/C field aliases + $this->value =& $this->sv->value; + $this->successCount =& $this->sv->successCount; + $this->failCount =& $this->sv->failCount; + $this->success =& $this->sv->success; + } + + /** + * Succinct helper method to wrap a StatusValue + * + * This is is useful when formatting StatusValue objects: + * + * $this->getOutput()->addHtml( Status::wrap( $sv )->getHTML() ); + * + * + * @param StatusValue|Status $sv + * @return Status + */ + public static function wrap( $sv ) { + return $sv instanceof Status ? $sv : new self( $sv ); + } + /** * Factory function for fatal errors * * @param string|Message $message Message name or object * @return Status */ - static function newFatal( $message /*, parameters...*/ ) { - $params = func_get_args(); - $result = new self; - call_user_func_array( array( &$result, 'error' ), $params ); - $result->ok = false; - return $result; + public static function newFatal( $message /*, parameters...*/ ) { + return new self( call_user_func_array( + array( 'StatusValue', 'newFatal' ), func_get_args() + ) ); } /** @@ -81,10 +98,11 @@ class Status { * @param mixed $value * @return Status */ - static function newGood( $value = null ) { - $result = new self; - $result->value = $value; - return $result; + public static function newGood( $value = null ) { + $sv = new StatusValue(); + $sv->value = $value; + + return new self( $sv ); } /** @@ -94,8 +112,7 @@ class Status { * @param mixed $value */ public function setResult( $ok, $value = null ) { - $this->ok = $ok; - $this->value = $value; + $this->sv->setResult( $ok, $value ); } /** @@ -105,7 +122,7 @@ class Status { * @return bool */ public function isGood() { - return $this->ok && !$this->errors; + return $this->sv->isGood(); } /** @@ -114,7 +131,7 @@ class Status { * @return bool */ public function isOK() { - return $this->ok; + return $this->sv->isOK(); } /** @@ -123,11 +140,7 @@ class Status { * @param string|Message $message Message name or object */ public function warning( $message /*, parameters... */ ) { - $params = array_slice( func_get_args(), 1 ); - $this->errors[] = array( - 'type' => 'warning', - 'message' => $message, - 'params' => $params ); + call_user_func_array( array( $this->sv, 'warning' ), func_get_args() ); } /** @@ -137,11 +150,7 @@ class Status { * @param string|Message $message Message name or object */ public function error( $message /*, parameters... */ ) { - $params = array_slice( func_get_args(), 1 ); - $this->errors[] = array( - 'type' => 'error', - 'message' => $message, - 'params' => $params ); + call_user_func_array( array( $this->sv, 'error' ), func_get_args() ); } /** @@ -151,35 +160,14 @@ class Status { * @param string|Message $message Message name or object */ public function fatal( $message /*, parameters... */ ) { - $params = array_slice( func_get_args(), 1 ); - $this->errors[] = array( - 'type' => 'error', - 'message' => $message, - 'params' => $params ); - $this->ok = false; - } - - /** - * Don't save the callback when serializing, because Closures can't be - * serialized and we're going to clear it in __wakeup anyway. - */ - public function __sleep() { - $keys = array_keys( get_object_vars( $this ) ); - return array_diff( $keys, array( 'cleanCallback' ) ); - } - - /** - * Sanitize the callback parameter on wakeup, to avoid arbitrary execution. - */ - public function __wakeup() { - $this->cleanCallback = false; + call_user_func_array( array( $this->sv, 'fatal' ), func_get_args() ); } /** * @param array $params * @return array */ - protected function cleanParams( $params ) { + protected function cleanParams( array $params ) { if ( !$this->cleanCallback ) { return $params; } @@ -199,24 +187,26 @@ class Status { * @return string */ public function getWikiText( $shortContext = false, $longContext = false ) { - if ( count( $this->errors ) == 0 ) { - if ( $this->ok ) { - $this->fatal( 'internalerror_info', + $rawErrors = $this->sv->getErrors(); + if ( count( $rawErrors ) == 0 ) { + if ( $this->sv->isOK() ) { + $this->sv->fatal( 'internalerror_info', __METHOD__ . " called for a good result, this is incorrect\n" ); } else { - $this->fatal( 'internalerror_info', + $this->sv->fatal( 'internalerror_info', __METHOD__ . ": Invalid result object: no error text but not OK\n" ); } + $rawErrors = $this->sv->getErrors(); // just added a fatal } - if ( count( $this->errors ) == 1 ) { - $s = $this->getErrorMessage( $this->errors[0] )->plain(); + if ( count( $rawErrors ) == 1 ) { + $s = $this->getErrorMessage( $rawErrors[0] )->plain(); if ( $shortContext ) { $s = wfMessage( $shortContext, $s )->plain(); } elseif ( $longContext ) { $s = wfMessage( $longContext, "* $s\n" )->plain(); } } else { - $errors = $this->getErrorMessageArray( $this->errors ); + $errors = $this->getErrorMessageArray( $rawErrors ); foreach ( $errors as &$error ) { $error = $error->plain(); } @@ -241,17 +231,19 @@ class Status { * @return Message */ public function getMessage( $shortContext = false, $longContext = false ) { - if ( count( $this->errors ) == 0 ) { - if ( $this->ok ) { - $this->fatal( 'internalerror_info', + $rawErrors = $this->sv->getErrors(); + if ( count( $rawErrors ) == 0 ) { + if ( $this->sv->isOK() ) { + $this->sv->fatal( 'internalerror_info', __METHOD__ . " called for a good result, this is incorrect\n" ); } else { - $this->fatal( 'internalerror_info', + $this->sv->fatal( 'internalerror_info', __METHOD__ . ": Invalid result object: no error text but not OK\n" ); } + $rawErrors = $this->sv->getErrors(); // just added a fatal } - if ( count( $this->errors ) == 1 ) { - $s = $this->getErrorMessage( $this->errors[0] ); + if ( count( $rawErrors ) == 1 ) { + $s = $this->getErrorMessage( $rawErrors[0] ); if ( $shortContext ) { $s = wfMessage( $shortContext, $s ); } elseif ( $longContext ) { @@ -260,7 +252,7 @@ class Status { $s = wfMessage( $longContext, $wrapper ); } } else { - $msgs = $this->getErrorMessageArray( $this->errors ); + $msgs = $this->getErrorMessageArray( $rawErrors ); $msgCount = count( $msgs ); if ( $shortContext ) { @@ -339,13 +331,7 @@ class Status { * @param bool $overwriteValue Whether to override the "value" member */ public function merge( $other, $overwriteValue = false ) { - $this->errors = array_merge( $this->errors, $other->errors ); - $this->ok = $this->ok && $other->ok; - if ( $overwriteValue ) { - $this->value = $other->value; - } - $this->successCount += $other->successCount; - $this->failCount += $other->failCount; + $this->sv->merge( $other->sv, $overwriteValue ); } /** @@ -353,9 +339,10 @@ class Status { * * @return array A list in which each entry is an array with a message key as its first element. * The remaining array elements are the message parameters. + * @deprecated 1.25 */ public function getErrorsArray() { - return $this->getStatusArray( "error" ); + return $this->getStatusArray( 'error' ); } /** @@ -363,21 +350,26 @@ class Status { * * @return array A list in which each entry is an array with a message key as its first element. * The remaining array elements are the message parameters. + * @deprecated 1.25 */ public function getWarningsArray() { - return $this->getStatusArray( "warning" ); + return $this->getStatusArray( 'warning' ); } /** * Returns a list of status messages of the given type (or all if false) + * + * @note: this handles RawMessage poorly + * * @param string $type * @return array */ protected function getStatusArray( $type = false ) { $result = array(); - foreach ( $this->errors as $error ) { + + foreach ( $this->sv->getErrors() as $error ) { if ( $type === false || $error['type'] === $type ) { - if ( $error['message'] instanceof Message ) { + if ( $error['message'] instanceof MessageSpecifier ) { $result[] = array_merge( array( $error['message']->getKey() ), $error['message']->getParams() @@ -402,13 +394,7 @@ class Status { * @return array */ public function getErrorsByType( $type ) { - $result = array(); - foreach ( $this->errors as $error ) { - if ( $error['type'] === $type ) { - $result[] = $error; - } - } - return $result; + return $this->sv->getErrorsByType( $type ); } /** @@ -419,19 +405,7 @@ class Status { * @return bool */ public function hasMessage( $message ) { - if ( $message instanceof Message ) { - $message = $message->getKey(); - } - foreach ( $this->errors as $error ) { - if ( $error['message'] instanceof Message - && $error['message']->getKey() === $message - ) { - return true; - } elseif ( $error['message'] === $message ) { - return true; - } - } - return false; + return $this->sv->hasMessage( $message ); } /** @@ -446,61 +420,67 @@ class Status { * @return bool Return true if the replacement was done, false otherwise. */ public function replaceMessage( $source, $dest ) { - $replaced = false; - foreach ( $this->errors as $index => $error ) { - if ( $error['message'] === $source ) { - $this->errors[$index]['message'] = $dest; - $replaced = true; - } - } - return $replaced; + return $this->sv->replaceMessage( $source, $dest ); } /** * @return mixed */ public function getValue() { - return $this->value; + return $this->sv->getValue(); } /** - * @return string + * Backwards compatibility logic + * + * @param string $name */ - public function __toString() { - $status = $this->isOK() ? "OK" : "Error"; - if ( count( $this->errors ) ) { - $errorcount = "collected " . ( count( $this->errors ) ) . " error(s) on the way"; - } else { - $errorcount = "no errors detected"; + function __get( $name ) { + if ( $name === 'ok' ) { + return $this->sv->getOK(); + } elseif ( $name === 'errors' ) { + return $this->sv->getErrors(); } - if ( isset( $this->value ) ) { - $valstr = gettype( $this->value ) . " value set"; - if ( is_object( $this->value ) ) { - $valstr .= "\"" . get_class( $this->value ) . "\" instance"; - } + throw new Exception( "Cannot get '$name' property." ); + } + + /** + * Backwards compatibility logic + * + * @param string $name + * @param mixed $value + */ + function __set( $name, $value ) { + if ( $name === 'ok' ) { + $this->sv->setOK( $value ); + } elseif ( !property_exists( $this, $name ) ) { + // Caller is using undeclared ad-hoc properties + $this->$name = $value; } else { - $valstr = "no value set"; + throw new Exception( "Cannot set '$name' property." ); } - $out = sprintf( "<%s, %s, %s>", - $status, - $errorcount, - $valstr - ); - if ( count( $this->errors ) > 0 ) { - $hdr = sprintf( "+-%'-4s-+-%'-25s-+-%'-40s-+\n", "", "", "" ); - $i = 1; - $out .= "\n"; - $out .= $hdr; - foreach ( $this->getStatusArray() as $stat ) { - $out .= sprintf( "| %4d | %-25.25s | %-40.40s |\n", - $i, - $stat[0], - implode( " ", array_slice( $stat, 1 ) ) - ); - $i += 1; - } - $out .= $hdr; - }; - return $out; + } + + /** + * @return string + */ + public function __toString() { + return $this->sv->__toString(); + } + + /** + * Don't save the callback when serializing, because Closures can't be + * serialized and we're going to clear it in __wakeup anyway. + */ + function __sleep() { + $keys = array_keys( get_object_vars( $this ) ); + return array_diff( $keys, array( 'cleanCallback' ) ); + } + + /** + * Sanitize the callback parameter on wakeup, to avoid arbitrary execution. + */ + function __wakeup() { + $this->cleanCallback = false; } } diff --git a/includes/filerepo/FileRepo.php b/includes/filerepo/FileRepo.php index 58245a5dd2..03934165b3 100644 --- a/includes/filerepo/FileRepo.php +++ b/includes/filerepo/FileRepo.php @@ -1681,23 +1681,26 @@ class FileRepo { * Create a new fatal error * * @param string $message - * @return FileRepoStatus + * @return Status */ public function newFatal( $message /*, parameters...*/ ) { - $params = func_get_args(); - array_unshift( $params, $this ); + $status = call_user_func_array( array( 'Status', 'newFatal' ), func_get_args() ); + $status->cleanCallback = $this->getErrorCleanupFunction(); - return call_user_func_array( array( 'FileRepoStatus', 'newFatal' ), $params ); + return $status; } /** * Create a new good result * * @param null|string $value - * @return FileRepoStatus + * @return Status */ public function newGood( $value = null ) { - return FileRepoStatus::newGood( $this, $value ); + $status = Status::newGood( $this, $value ); + $status->cleanCallback = $this->getErrorCleanupFunction(); + + return $status; } /** diff --git a/includes/filerepo/FileRepoStatus.php b/includes/filerepo/FileRepoStatus.php index 56848df286..daf26ba969 100644 --- a/includes/filerepo/FileRepoStatus.php +++ b/includes/filerepo/FileRepoStatus.php @@ -24,41 +24,6 @@ /** * Generic operation result class for FileRepo-related operations * @ingroup FileRepo + * @deprecated 1.25 */ -class FileRepoStatus extends Status { - /** - * Factory function for fatal errors - * - * @param FileRepo $repo - * @return FileRepoStatus - */ - static function newFatal( $repo /*, parameters...*/ ) { - $params = array_slice( func_get_args(), 1 ); - $result = new self( $repo ); - call_user_func_array( array( &$result, 'error' ), $params ); - $result->ok = false; - - return $result; - } - - /** - * @param FileRepo|bool $repo Default: false - * @param mixed $value - * @return FileRepoStatus - */ - static function newGood( $repo = false, $value = null ) { - $result = new self( $repo ); - $result->value = $value; - - return $result; - } - - /** - * @param bool|FileRepo $repo - */ - function __construct( $repo = false ) { - if ( $repo ) { - $this->cleanCallback = $repo->getErrorCleanupFunction(); - } - } -} +class FileRepoStatus extends Status {} diff --git a/includes/jobqueue/JobQueueRedis.php b/includes/jobqueue/JobQueueRedis.php index abfdc8c74e..9368fbf734 100644 --- a/includes/jobqueue/JobQueueRedis.php +++ b/includes/jobqueue/JobQueueRedis.php @@ -24,7 +24,7 @@ /** * Class to handle job queues stored in Redis * - * This is faster, less resource intensive, queue that JobQueueDB. + * This is a faster and less resource-intensive job queue than JobQueueDB. * All data for a queue using this class is placed into one redis server. * * There are eight main redis keys used to track jobs: @@ -49,7 +49,7 @@ * * This class requires Redis 2.6 as it makes use Lua scripts for fast atomic operations. * Additionally, it should be noted that redis has different persistence modes, such - * as rdb snapshots, journaling, and no persistent. Appropriate configuration should be + * as rdb snapshots, journaling, and no persistence. Appropriate configuration should be * made on the servers based on what queues are using it and what tolerance they have. * * @ingroup JobQueue diff --git a/includes/libs/MessageSpecifier.php b/includes/libs/MessageSpecifier.php new file mode 100644 index 0000000000..b417f299ae --- /dev/null +++ b/includes/libs/MessageSpecifier.php @@ -0,0 +1,39 @@ + bool) to indicate success of each part of batch operations */ + public $success = array(); + /** @var int Counter for batch operations */ + public $successCount = 0; + /** @var int Counter for batch operations */ + public $failCount = 0; + + /** + * Factory function for fatal errors + * + * @param string|MessageSpecifier $message Message key or object + * @return Status + */ + public static function newFatal( $message /*, parameters...*/ ) { + $params = func_get_args(); + $result = new static(); + call_user_func_array( array( &$result, 'fatal' ), $params ); + return $result; + } + + /** + * Factory function for good results + * + * @param mixed $value + * @return Status + */ + public static function newGood( $value = null ) { + $result = new static(); + $result->value = $value; + return $result; + } + + /** + * Returns whether the operation completed and didn't have any error or + * warnings + * + * @return bool + */ + public function isGood() { + return $this->ok && !$this->errors; + } + + /** + * Returns whether the operation completed + * + * @return bool + */ + public function isOK() { + return $this->ok; + } + + /** + * @return mixed + */ + public function getValue() { + return $this->value; + } + + /** + * Get the list of errors + * + * Each error is a (message:string or MessageSpecifier,params:array) map + * + * @return array + */ + public function getErrors() { + return $this->errors; + } + + /** + * Change operation status + * + * @param bool $ok + */ + public function setOK( $ok ) { + $this->ok = $ok; + } + + /** + * Change operation resuklt + * + * @param bool $ok Whether the operation completed + * @param mixed $value + */ + public function setResult( $ok, $value = null ) { + $this->ok = $ok; + $this->value = $value; + } + + /** + * Add a new warning + * + * @param string|MessageSpecifier $message Message key or object + */ + public function warning( $message /*, parameters... */ ) { + $this->errors[] = array( + 'type' => 'warning', + 'message' => $message, + 'params' => array_slice( func_get_args(), 1 ) + ); + } + + /** + * Add an error, do not set fatal flag + * This can be used for non-fatal errors + * + * @param string|MessageSpecifier $message Message key or object + */ + public function error( $message /*, parameters... */ ) { + $this->errors[] = array( + 'type' => 'error', + 'message' => $message, + 'params' => array_slice( func_get_args(), 1 ) + ); + } + + /** + * Add an error and set OK to false, indicating that the operation + * as a whole was fatal + * + * @param string|MessageSpecifier $message Message key or object + */ + public function fatal( $message /*, parameters... */ ) { + $this->errors[] = array( + 'type' => 'error', + 'message' => $message, + 'params' => array_slice( func_get_args(), 1 ) + ); + $this->ok = false; + } + + /** + * Merge another status object into this one + * + * @param Status $other Other Status object + * @param bool $overwriteValue Whether to override the "value" member + */ + public function merge( $other, $overwriteValue = false ) { + $this->errors = array_merge( $this->errors, $other->errors ); + $this->ok = $this->ok && $other->ok; + if ( $overwriteValue ) { + $this->value = $other->value; + } + $this->successCount += $other->successCount; + $this->failCount += $other->failCount; + } + + /** + * Returns a list of status messages of the given type + * + * Each entry is a map of (message:string or MessageSpecifier,params:array)) + * + * @param string $type + * @return array + */ + public function getErrorsByType( $type ) { + $result = array(); + foreach ( $this->errors as $error ) { + if ( $error['type'] === $type ) { + $result[] = $error; + } + } + + return $result; + } + + /** + * Returns true if the specified message is present as a warning or error + * + * @param string|MessageSpecifier $message Message key or object to search for + * + * @return bool + */ + public function hasMessage( $message ) { + if ( $message instanceof MessageSpecifier ) { + $message = $message->getKey(); + } + foreach ( $this->errors as $error ) { + if ( $error['message'] instanceof MessageSpecifier + && $error['message']->getKey() === $message + ) { + return true; + } elseif ( $error['message'] === $message ) { + return true; + } + } + + return false; + } + + /** + * If the specified source message exists, replace it with the specified + * destination message, but keep the same parameters as in the original error. + * + * Note, due to the lack of tools for comparing IStatusMessage objects, this + * function will not work when using such an object as the search parameter. + * + * @param IStatusMessage|string $source Message key or object to search for + * @param IStatusMessage|string $dest Replacement message key or object + * @return bool Return true if the replacement was done, false otherwise. + */ + public function replaceMessage( $source, $dest ) { + $replaced = false; + + foreach ( $this->errors as $index => $error ) { + if ( $error['message'] === $source ) { + $this->errors[$index]['message'] = $dest; + $replaced = true; + } + } + + return $replaced; + } + + /** + * @return string + */ + public function __toString() { + $status = $this->isOK() ? "OK" : "Error"; + if ( count( $this->errors ) ) { + $errorcount = "collected " . ( count( $this->errors ) ) . " error(s) on the way"; + } else { + $errorcount = "no errors detected"; + } + if ( isset( $this->value ) ) { + $valstr = gettype( $this->value ) . " value set"; + if ( is_object( $this->value ) ) { + $valstr .= "\"" . get_class( $this->value ) . "\" instance"; + } + } else { + $valstr = "no value set"; + } + $out = sprintf( "<%s, %s, %s>", + $status, + $errorcount, + $valstr + ); + if ( count( $this->errors ) > 0 ) { + $hdr = sprintf( "+-%'-4s-+-%'-25s-+-%'-40s-+\n", "", "", "" ); + $i = 1; + $out .= "\n"; + $out .= $hdr; + foreach ( $this->errors as $error ) { + if ( $error['message'] instanceof MessageSpecifier ) { + $key = $error['message']->getKey(); + $params = $error['message']->getParams(); + } elseif ( $error['params'] ) { + $key = $error['message']; + $params = $error['params']; + } else { + $key = $error['message']; + $params = array(); + } + + $out .= sprintf( "| %4d | %-25.25s | %-40.40s |\n", + $i, + $key, + implode( " ", $params ) + ); + $i += 1; + } + $out .= $hdr; + } + + return $out; + } +} diff --git a/includes/registration/ExtensionProcessor.php b/includes/registration/ExtensionProcessor.php index 1462840f5f..bf42aba932 100644 --- a/includes/registration/ExtensionProcessor.php +++ b/includes/registration/ExtensionProcessor.php @@ -185,11 +185,21 @@ class ExtensionProcessor implements Processor { } protected function extractResourceLoaderModules( $dir, array $info ) { + $defaultPaths = isset( $info['ResourceFileModulePaths'] ) + ? $info['ResourceFileModulePaths'] + : false; + if ( isset( $defaultPaths['localBasePath'] ) ) { + $defaultPaths['localBasePath'] = "$dir/{$defaultPaths['localBasePath']}"; + } + if ( isset( $info['ResourceModules'] ) ) { foreach ( $info['ResourceModules'] as $name => $data ) { if ( isset( $data['localBasePath'] ) ) { $data['localBasePath'] = "$dir/{$data['localBasePath']}"; } + if ( $defaultPaths && !isset( $data['class'] ) ) { + $data += $defaultPaths; + } $this->globals['wgResourceModules'][$name] = $data; } } diff --git a/maintenance/Maintenance.php b/maintenance/Maintenance.php index 9b98b206a8..af14bb36fc 100644 --- a/maintenance/Maintenance.php +++ b/maintenance/Maintenance.php @@ -1207,7 +1207,13 @@ abstract class Maintenance { } if ( $isatty && function_exists( 'readline' ) ) { - return readline( $prompt ); + $resp = readline( $prompt ); + if ( $resp === null ) { + // Workaround for https://github.com/facebook/hhvm/issues/4776 + return false; + } else { + return $resp; + } } else { if ( $isatty ) { $st = self::readlineEmulation( $prompt ); diff --git a/maintenance/convertExtensionToRegistration.php b/maintenance/convertExtensionToRegistration.php index a0dee3cc24..76bc982459 100644 --- a/maintenance/convertExtensionToRegistration.php +++ b/maintenance/convertExtensionToRegistration.php @@ -155,12 +155,36 @@ class ConvertExtensionToRegistration extends Maintenance { } protected function handleResourceModules( $realName, $value ) { + $defaults = array(); + $remote = $this->hasOption( 'skin' ) ? 'remoteSkinPath' : 'remoteExtPath'; foreach ( $value as $name => $data ) { if ( isset( $data['localBasePath'] ) ) { $data['localBasePath'] = $this->stripPath( $data['localBasePath'], $this->dir ); + if ( !$defaults ) { + $defaults['localBasePath'] = $data['localBasePath']; + unset( $data['localBasePath'] ); + if ( isset( $data[$remote] ) ) { + $defaults[$remote] = $data[$remote]; + unset( $data[$remote] ); + } + } else { + if ( $data['localBasePath'] === $defaults['localBasePath'] ) { + unset( $data['localBasePath'] ); + } + if ( isset( $data[$remote] ) && isset( $defaults[$remote] ) + && $data[$remote] === $defaults[$remote] + ) { + unset( $data[$remote] ); + } + } } + + $this->json[$realName][$name] = $data; } + if ( $defaults ) { + $this->json['ResourceFileModulePaths'] = $defaults; + } } } diff --git a/package.json b/package.json index 6bbcf39903..4ef12bac8e 100644 --- a/package.json +++ b/package.json @@ -5,17 +5,17 @@ "test": "grunt test" }, "devDependencies": { - "grunt": "0.4.2", + "grunt": "0.4.5", "grunt-banana-checker": "0.2.0", - "grunt-contrib-jshint": "0.10.0", + "grunt-contrib-jshint": "0.11.0", "grunt-contrib-watch": "0.6.1", - "grunt-jscs": "0.8.1", + "grunt-jscs": "1.5.0", "grunt-jsonlint": "1.0.4", - "grunt-karma": "0.9.0", + "grunt-karma": "0.10.1", "karma": "0.12.31", "karma-chrome-launcher": "0.1.7", - "karma-firefox-launcher": "0.1.3", + "karma-firefox-launcher": "0.1.4", "karma-qunit": "0.1.4", - "qunitjs": "1.15.0" + "qunitjs": "1.17.1" } } diff --git a/profileinfo.php b/profileinfo.php index 4e3fb5ad28..f172cfb6f2 100644 --- a/profileinfo.php +++ b/profileinfo.php @@ -36,7 +36,7 @@ header( 'Content-Type: text/html; charset=utf-8' ); - + Profiling data