X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Fapi%2FApiUpload.php;h=7b44f409932c476f626334e3d4472da448253c77;hp=89d9af8ee85f244c38d3e9c9cbcf71753cf03577;hb=f43fa6f4f0e2cb60b8543daad661b48a3e0653a9;hpb=dcd211106c88fcb3b9565045c6b2264dba6be13c diff --git a/includes/api/ApiUpload.php b/includes/api/ApiUpload.php index 89d9af8ee8..7b44f40993 100644 --- a/includes/api/ApiUpload.php +++ b/includes/api/ApiUpload.php @@ -109,16 +109,19 @@ class ApiUpload extends ApiBase { // 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(); } @@ -240,7 +243,7 @@ class ApiUpload extends ApiBase { 'offset' => $this->mUpload->getOffset(), ]; - $this->dieUsage( $status->getWikiText( false, false, 'en' ), 'stashfailed', 0, $extradata ); + $this->dieStatusWithCode( $status, 'stashfailed', $extradata ); } } @@ -271,14 +274,20 @@ class ApiUpload extends ApiBase { $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'; } @@ -315,8 +324,9 @@ class ApiUpload extends ApiBase { * @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... @@ -381,6 +391,29 @@ class ApiUpload extends ApiBase { $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; @@ -403,13 +436,30 @@ class ApiUpload extends ApiBase { 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; } @@ -421,7 +471,7 @@ class ApiUpload extends ApiBase { 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' ); @@ -654,6 +704,30 @@ class ApiUpload extends ApiBase { : $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; @@ -712,7 +786,7 @@ class ApiUpload extends ApiBase { $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,