protected $mParams;
public function execute() {
+ global $wgEnableAsyncUploads;
+
// Check whether upload is enabled
if ( !UploadBase::isEnabled() ) {
$this->dieUsageMsg( 'uploaddisabled' );
// Parameter handling
$this->mParams = $this->extractRequestParams();
$request = $this->getMain()->getRequest();
- // Check if async mode is actually supported
- $this->mParams['async'] = ( $this->mParams['async'] && !wfIsWindows() );
- $this->mParams['async'] = false; // XXX: disabled per bug 44080
+ // Check if async mode is actually supported (jobs done in cli mode)
+ $this->mParams['async'] = ( $this->mParams['async'] && $wgEnableAsyncUploads );
// Add the uploaded file to the params array
$this->mParams['file'] = $request->getFileName( 'file' );
$this->mParams['chunk'] = $request->getFileName( 'chunk' );
$this->checkPermissions( $user );
// Fetch the file (usually a no-op)
+ /** @var $status Status */
$status = $this->mUpload->fetchFile();
if ( !$status->isGood() ) {
$errors = $status->getErrorsArray();
}
/**
- * Get an uplaod result based on upload context
+ * Get an upload result based on upload context
* @return array
*/
private function getContextResult() {
$warnings = $this->getApiWarnings();
if ( $warnings && !$this->mParams['ignorewarnings'] ) {
- // Get warnings formated in result array format
+ // Get warnings formatted in result array format
return $this->getWarningsResult( $warnings );
} elseif ( $this->mParams['chunk'] ) {
// Add chunk, and get result
}
/**
- * Get Stash Result, throws an expetion if the file could not be stashed.
+ * Get Stash Result, throws an exception if the file could not be stashed.
* @param $warnings array Array of Api upload warnings
* @return array
*/
* @return array
*/
private function getChunkResult( $warnings ) {
- global $IP;
-
$result = array();
$result['result'] = 'Continue';
$chunkPath = $request->getFileTempname( 'chunk' );
$chunkSize = $request->getUpload( 'chunk' )->getSize();
if ( $this->mParams['offset'] == 0 ) {
- $result['filekey'] = $this->performStash();
+ $filekey = $this->performStash();
} else {
+ $filekey = $this->mParams['filekey'];
+ /** @var $status Status */
$status = $this->mUpload->addChunk(
$chunkPath, $chunkSize, $this->mParams['offset'] );
if ( !$status->isGood() ) {
$this->dieUsage( $status->getWikiText(), 'stashfailed' );
return array();
}
+ }
- // Check we added the last chunk:
- if( $this->mParams['offset'] + $chunkSize == $this->mParams['filesize'] ) {
- if ( $this->mParams['async'] && !wfIsWindows() ) {
- $progress = UploadBase::getSessionStatus( $this->mParams['filekey'] );
- if ( $progress && $progress['result'] === 'Poll' ) {
- $this->dieUsage( "Chunk assembly already in progress.", 'stashfailed' );
- }
- UploadBase::setSessionStatus(
- $this->mParams['filekey'],
- array( 'result' => 'Poll',
- 'stage' => 'queued', 'status' => Status::newGood() )
- );
- $retVal = 1;
- $cmd = wfShellWikiCmd(
- "$IP/includes/upload/AssembleUploadChunks.php",
- array(
- '--wiki', wfWikiID(),
- '--filename', $this->mParams['filename'],
- '--filekey', $this->mParams['filekey'],
- '--userid', $this->getUser()->getId(),
- '--sessionid', session_id(),
- '--quiet'
- )
- ) . " < " . wfGetNull() . " > " . wfGetNull() . " 2>&1 &";
- // Start a process in the background. Enforce the time limits via PHP
- // since ulimit4.sh seems to often not work for this particular usage.
- wfShellExec( $cmd, $retVal, array(), array( 'time' => 0, 'memory' => 0 ) );
- if ( $retVal == 0 ) {
- $result['result'] = 'Poll';
- } else {
- UploadBase::setSessionStatus( $this->mParams['filekey'], false );
- $this->dieUsage(
- "Failed to start AssembleUploadChunks.php", 'stashfailed' );
- }
+ // Check we added the last chunk:
+ if ( $this->mParams['offset'] + $chunkSize == $this->mParams['filesize'] ) {
+ if ( $this->mParams['async'] ) {
+ $progress = UploadBase::getSessionStatus( $this->mParams['filekey'] );
+ if ( $progress && $progress['result'] === 'Poll' ) {
+ $this->dieUsage( "Chunk assembly already in progress.", 'stashfailed' );
+ }
+ UploadBase::setSessionStatus(
+ $this->mParams['filekey'],
+ array( 'result' => 'Poll',
+ 'stage' => 'queued', 'status' => Status::newGood() )
+ );
+ $ok = JobQueueGroup::singleton()->push( new AssembleUploadChunksJob(
+ Title::makeTitle( NS_FILE, $this->mParams['filekey'] ),
+ array(
+ 'filename' => $this->mParams['filename'],
+ 'filekey' => $this->mParams['filekey'],
+ 'session' => $this->getRequest()->exportUserSession(),
+ 'userid' => $this->getUser()->getId()
+ )
+ ) );
+ if ( $ok ) {
+ $result['result'] = 'Poll';
} else {
- $status = $this->mUpload->concatenateChunks();
- if ( !$status->isGood() ) {
- $this->dieUsage( $status->getWikiText(), 'stashfailed' );
- return array();
- }
-
- // We have a new filekey for the fully concatenated file.
- $result['filekey'] = $this->mUpload->getLocalFile()->getFileKey();
-
- // Remove chunk from stash. (Checks against user ownership of chunks.)
- $this->mUpload->stash->removeFile( $this->mParams['filekey'] );
-
- $result['result'] = 'Success';
+ UploadBase::setSessionStatus( $this->mParams['filekey'], false );
+ $this->dieUsage(
+ "Failed to start AssembleUploadChunks.php", 'stashfailed' );
}
} else {
- // Continue passing through the filekey for adding further chunks.
- $result['filekey'] = $this->mParams['filekey'];
+ $status = $this->mUpload->concatenateChunks();
+ if ( !$status->isGood() ) {
+ $this->dieUsage( $status->getWikiText(), 'stashfailed' );
+ return array();
+ }
+
+ // The fully concatenated file has a new filekey. So remove
+ // the old filekey and fetch the new one.
+ $this->mUpload->stash->removeFile( $filekey );
+ $filekey = $this->mUpload->getLocalFile()->getFileKey();
+
+ $result['result'] = 'Success';
}
}
+ $result['filekey'] = $filekey;
$result['offset'] = $this->mParams['offset'] + $chunkSize;
return $result;
}
$fileKey = $stashFile->getFileKey();
} catch ( MWException $e ) {
$message = 'Stashing temporary file failed: ' . get_class( $e ) . ' ' . $e->getMessage();
- wfDebug( __METHOD__ . ' ' . $message . "\n");
+ wfDebug( __METHOD__ . ' ' . $message . "\n" );
throw new MWException( $message );
}
return $fileKey;
}
}
-
/**
* Check warnings.
* Returns a suitable array for inclusion into API results if there were warnings
return $warnings;
}
-
/**
* Perform the actual upload. Returns a suitable result array on success;
* dies on failure.
* @return array
*/
protected function performUpload( $warnings ) {
- global $IP;
-
// Use comment as initial page text by default
if ( is_null( $this->mParams['text'] ) ) {
$this->mParams['text'] = $this->mParams['comment'];
}
+ /** @var $file File */
$file = $this->mUpload->getLocalFile();
$watch = $this->getWatchlistValue( $this->mParams['watchlist'], $file->getTitle() );
$this->mParams['filekey'],
array( 'result' => 'Poll', 'stage' => 'queued', 'status' => Status::newGood() )
);
- $retVal = 1;
- $cmd = wfShellWikiCmd(
- "$IP/includes/upload/PublishStashedFile.php",
+ $ok = JobQueueGroup::singleton()->push( new PublishStashedFileJob(
+ Title::makeTitle( NS_FILE, $this->mParams['filename'] ),
array(
- '--wiki', wfWikiID(),
- '--filename', $this->mParams['filename'],
- '--filekey', $this->mParams['filekey'],
- '--userid', $this->getUser()->getId(),
- '--comment', $this->mParams['comment'],
- '--text', $this->mParams['text'],
- '--watch', $watch,
- '--sessionid', session_id(),
- '--quiet'
+ 'filename' => $this->mParams['filename'],
+ 'filekey' => $this->mParams['filekey'],
+ 'comment' => $this->mParams['comment'],
+ 'text' => $this->mParams['text'],
+ 'watch' => $watch,
+ 'session' => $this->getRequest()->exportUserSession(),
+ 'userid' => $this->getUser()->getId()
)
- ) . " < " . wfGetNull() . " > " . wfGetNull() . " 2>&1 &";
- // Start a process in the background. Enforce the time limits via PHP
- // since ulimit4.sh seems to often not work for this particular usage.
- wfShellExec( $cmd, $retVal, array(), array( 'time' => 0, 'memory' => 0 ) );
- if ( $retVal == 0 ) {
+ ) );
+ if ( $ok ) {
$result['result'] = 'Poll';
} else {
UploadBase::setSessionStatus( $this->mParams['filekey'], false );
"Failed to start PublishStashedFile.php", 'publishfailed' );
}
} else {
+ /** @var $status Status */
$status = $this->mUpload->performUpload( $this->mParams['comment'],
$this->mParams['text'], $watch, $this->getUser() );
protected function checkAsyncDownloadEnabled() {
global $wgAllowAsyncCopyUploads;
if ( !$wgAllowAsyncCopyUploads ) {
- $this->dieUsage( 'Asynchronous copy uploads disabled', 'asynccopyuploaddisabled');
+ $this->dieUsage( 'Asynchronous copy uploads disabled', 'asynccopyuploaddisabled' );
}
}
),
),
'ignorewarnings' => false,
- 'file' => null,
+ 'file' => array(
+ ApiBase::PARAM_TYPE => 'upload',
+ ),
'url' => null,
'filekey' => null,
'sessionkey' => array(
'filesize' => null,
'offset' => null,
- 'chunk' => null,
+ 'chunk' => array(
+ ApiBase::PARAM_TYPE => 'upload',
+ ),
'async' => false,
'asyncdownload' => false,