// Get the result based on the current upload context:
try {
$result = $this->getContextResult();
- if ( $result['result'] === 'Success' ) {
- $result['imageinfo'] = $this->mUpload->getImageInfo( $this->getResult() );
- }
} catch ( UploadStashException $e ) { // XXX: don't spam exception log
list( $msg, $code ) = $this->handleStashException( get_class( $e ), $e->getMessage() );
$this->dieUsage( $msg, $code );
}
-
$this->getResult()->addValue( null, $this->getModuleName(), $result );
+ // Add 'imageinfo' in a separate addValue() call. File metadata can be unreasonably large,
+ // so otherwise when it exceeded $wgAPIMaxResultSize, no result would be returned (T143993).
+ if ( $result['result'] === 'Success' ) {
+ $imageinfo = $this->mUpload->getImageInfo( $this->getResult() );
+ $this->getResult()->addValue( $this->getModuleName(), 'imageinfo', $imageinfo );
+ }
+
// Cleanup any temporary mess
$this->mUpload->cleanupTempFile();
}
'offset' => $this->mUpload->getOffset(),
];
- $this->dieUsage( $status->getWikiText( false, false, 'en' ), 'stashfailed', 0, $extradata );
+ $this->dieStatusWithCode( $status, 'stashfailed', $extradata );
}
}
$filekey,
[ 'result' => 'Failure', 'stage' => 'assembling', 'status' => $status ]
);
- $this->dieUsage( $status->getWikiText( false, false, 'en' ), 'stashfailed' );
+ $this->dieStatusWithCode( $status, 'stashfailed' );
+ }
+
+ // We can only get warnings like 'duplicate' after concatenating the chunks
+ $warnings = $this->getApiWarnings();
+ if ( $warnings ) {
+ $result['warnings'] = $warnings;
}
// The fully concatenated file has a new filekey. So remove
// the old filekey and fetch the new one.
UploadBase::setSessionStatus( $this->getUser(), $filekey, false );
$this->mUpload->stash->removeFile( $filekey );
- $filekey = $this->mUpload->getLocalFile()->getFileKey();
+ $filekey = $this->mUpload->getStashFile()->getFileKey();
$result['result'] = 'Success';
}
* @return string|null File key
*/
private function performStash( $failureMode, &$data = null ) {
+ $isPartial = (bool)$this->mParams['chunk'];
try {
- $status = $this->mUpload->tryStashFile( $this->getUser() );
+ $status = $this->mUpload->tryStashFile( $this->getUser(), $isPartial );
if ( $status->isGood() && !$status->getValue() ) {
// Not actually a 'good' status...
$this->dieUsage( $parsed['info'], $parsed['code'], 0, $data );
}
+ /**
+ * Like dieStatus(), but always uses $overrideCode for the error code, unless the code comes from
+ * IApiMessage.
+ *
+ * @param Status $status
+ * @param string $overrideCode Error code to use if there isn't one from IApiMessage
+ * @param array|null $moreExtraData
+ * @throws UsageException
+ */
+ public function dieStatusWithCode( $status, $overrideCode, $moreExtraData = null ) {
+ $extraData = null;
+ list( $code, $msg ) = $this->getErrorFromStatus( $status, $extraData );
+ $errors = $status->getErrorsByType( 'error' ) ?: $status->getErrorsByType( 'warning' );
+ if ( !( $errors[0]['message'] instanceof IApiMessage ) ) {
+ $code = $overrideCode;
+ }
+ if ( $moreExtraData ) {
+ $extraData = $extraData ?: [];
+ $extraData += $moreExtraData;
+ }
+ $this->dieUsage( $msg, $code, 0, $extraData );
+ }
+
/**
* Select an upload module and set it to mUpload. Dies on failure. If the
* request was a status request and not a true upload, returns false;
if ( !$progress ) {
$this->dieUsage( 'No result in status data', 'missingresult' );
} elseif ( !$progress['status']->isGood() ) {
- $this->dieUsage( $progress['status']->getWikiText( false, false, 'en' ), 'stashfailed' );
+ $this->dieStatusWithCode( $progress['status'], 'stashfailed' );
}
if ( isset( $progress['status']->value['verification'] ) ) {
$this->checkVerification( $progress['status']->value['verification'] );
}
+ if ( isset( $progress['status']->value['warnings'] ) ) {
+ $warnings = $this->transformWarnings( $progress['status']->value['warnings'] );
+ if ( $warnings ) {
+ $progress['warnings'] = $warnings;
+ }
+ }
unset( $progress['status'] ); // remove Status object
+ $imageinfo = null;
+ if ( isset( $progress['imageinfo'] ) ) {
+ $imageinfo = $progress['imageinfo'];
+ unset( $progress['imageinfo'] );
+ }
+
$this->getResult()->addValue( null, $this->getModuleName(), $progress );
+ // Add 'imageinfo' in a separate addValue() call. File metadata can be unreasonably large,
+ // so otherwise when it exceeded $wgAPIMaxResultSize, no result would be returned (T143993).
+ if ( $imageinfo ) {
+ $this->getResult()->addValue( $this->getModuleName(), 'imageinfo', $imageinfo );
+ }
return false;
}
if ( $this->mParams['chunk'] ) {
// Chunk upload
- $this->mUpload = new UploadFromChunks();
+ $this->mUpload = new UploadFromChunks( $this->getUser() );
if ( isset( $this->mParams['filekey'] ) ) {
if ( $this->mParams['offset'] === 0 ) {
$this->dieUsage( 'Cannot supply a filekey when offset is 0', 'badparams' );
: $warning['file'];
$warnings[$warning['warning']] = $localFile->getName();
}
+
+ if ( isset( $warnings['no-change'] ) ) {
+ /** @var File $file */
+ $file = $warnings['no-change'];
+ unset( $warnings['no-change'] );
+
+ $warnings['nochange'] = [
+ 'timestamp' => wfTimestamp( TS_ISO_8601, $file->getTimestamp() )
+ ];
+ }
+
+ if ( isset( $warnings['duplicate-version'] ) ) {
+ $dupes = [];
+ /** @var File $dupe */
+ foreach ( $warnings['duplicate-version'] as $dupe ) {
+ $dupes[] = [
+ 'timestamp' => wfTimestamp( TS_ISO_8601, $dupe->getTimestamp() )
+ ];
+ }
+ unset( $warnings['duplicate-version'] );
+
+ ApiResult::setIndexedTagName( $dupes, 'ver' );
+ $warnings['duplicateversions'] = $dupes;
+ }
}
return $warnings;
$this->mParams['text'] = $this->mParams['comment'];
}
- /** @var $file File */
+ /** @var $file LocalFile */
$file = $this->mUpload->getLocalFile();
// For preferences mode, we want to watch if 'watchdefault' is set,