Follow-up r70137: Made asynchronous upload working a bit more. It now fully works...
authorBryan Tong Minh <btongminh@users.mediawiki.org>
Mon, 6 Sep 2010 10:18:53 +0000 (10:18 +0000)
committerBryan Tong Minh <btongminh@users.mediawiki.org>
Mon, 6 Sep 2010 10:18:53 +0000 (10:18 +0000)
ApiUpload:
* Added "statuskey" parameter; this is the key that is returned by an async upload
* Refactored warnings transformation into its own function
* filename is no longer required on all uploads

UploadFromUrlJob:
* Moved upload results to its own entry in $_SESSION, instead of using the one from upload
* Fix storing in session by calling wfSetupSession and session_write_close where needed

Tests:
* Set $wgUser in ApiSetup, so that individual tests don't have to do this for themselves
* Added tests to cover most code paths from the API
* Fixed UploadFromUrlTestSuite so that its tests are included in a regular phpunit invocation (something strange with the AutoLoader; not sure what)

Other files:
* Allow passing session id to wfSetupSession
* Explicitly close the session before doing jobs, so that jobs can't manipulate the current session

RELEASE-NOTES
includes/GlobalFunctions.php
includes/Wiki.php
includes/api/ApiUpload.php
includes/job/UploadFromUrlJob.php
includes/upload/UploadFromUrl.php
maintenance/tests/ApiSetup.php
maintenance/tests/UploadFromUrlTest.php
maintenance/tests/UploadFromUrlTestSuite.php

index 521ae8f..129196e 100644 (file)
@@ -380,6 +380,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
   missing
 * (bug 24724) list=allusers is out by 1 (shows total users - 1)
 * (bug 24166) API error when using rvprop=tags
+* Introduced "asynchronous download" mode for upload-by-url. Requires 
+  $wgAllowAsyncCopyUploads to be true.
 
 === Languages updated in 1.17 ===
 
index c30b783..271628b 100644 (file)
@@ -2918,7 +2918,7 @@ function wfHttpOnlySafe() {
 /**
  * Initialise php session
  */
-function wfSetupSession() {
+function wfSetupSession( $sessionId = false ) {
        global $wgSessionsInMemcached, $wgCookiePath, $wgCookieDomain,
                        $wgCookieSecure, $wgCookieHttpOnly, $wgSessionHandler;
        if( $wgSessionsInMemcached ) {
@@ -2944,6 +2944,9 @@ function wfSetupSession() {
                session_set_cookie_params( 0, $wgCookiePath, $wgCookieDomain, $wgCookieSecure );
        }
        session_cache_limiter( 'private, must-revalidate' );
+       if ( $sessionId ) {
+               session_id( $sessionId );
+       }
        wfSuppressWarnings();
        session_start();
        wfRestoreWarnings();
index cd671ce..0c65b4a 100644 (file)
@@ -379,6 +379,8 @@ class MediaWiki {
                $output->output();
                // Do any deferred jobs
                $this->doUpdates( $deferredUpdates );
+               // Close the session so that jobs don't access the current session
+               session_write_close();
                $this->doJobs();
                wfProfileOut( __METHOD__ );
        }
index 9ba52ea..af08a62 100644 (file)
@@ -55,7 +55,10 @@ class ApiUpload extends ApiBase {
                $this->mParams['file'] = $request->getFileName( 'file' );
 
                // Select an upload module
-               $this->selectUploadModule();
+               if ( !$this->selectUploadModule() ) {
+                       // This is not a true upload, but a status request or similar
+                       return;
+               }
                if ( !isset( $this->mUpload ) ) {
                        $this->dieUsage( 'No upload module set', 'nomodule' );
                }
@@ -96,15 +99,39 @@ class ApiUpload extends ApiBase {
        }
 
        /**
-        * Select an upload module and set it to mUpload. Dies on failure.
+        * 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; 
+        * otherwise true
+        * 
+        * @return bool
         */
        protected function selectUploadModule() {
                $request = $this->getMain()->getRequest();
 
                // One and only one of the following parameters is needed
                $this->requireOnlyOneParameter( $this->mParams,
-                       'sessionkey', 'file', 'url' );
+                       'sessionkey', 'file', 'url', 'statuskey' );
 
+               if ( $this->mParams['statuskey'] ) {
+                       // Status request for an async upload
+                       $sessionData = UploadFromUrlJob::getSessionData( $this->mParams['statuskey'] );
+                       if ( !isset( $sessionData['result'] ) ) {
+                               $this->dieUsage();      
+                       }
+                       if ( $sessionData['result'] == 'Warning' ) {
+                               $sessionData['warnings'] = $this->transformWarnings( $sessionData['warnings'] );
+                               $sessionData['sessionkey'] = $this->mParams['statuskey'];
+                       }
+                       $this->getResult()->addValue( null, $this->getModuleName(), $sessionData );
+                       return false;
+                       
+               } 
+               
+               // The following modules all require the filename parameter to be set
+               if ( is_null( $this->mParams['filename'] ) ) {
+                       $this->dieUsageMsg( array( 'missingparam', 'filename' ) );
+               }
+               
                if ( $this->mParams['sessionkey'] ) {
                        // Upload stashed in a previous request
                        $sessionData = $request->getSessionData( UploadBase::getSessionKeyName() );
@@ -132,6 +159,11 @@ class ApiUpload extends ApiBase {
 
                        $async = false;
                        if ( $this->mParams['asyncdownload'] ) {
+                               if ( $this->mParams['leavemessage'] && !$this->mParams['ignorewarnings'] ) {
+                                       $this->dieUsage( 'Using leavemessage without ignorewarnings is not supported',
+                                               'missing-ignorewarnings' );
+                               }
+                               
                                if ( $this->mParams['leavemessage'] ) {
                                        $async = 'async-leavemessage';
                                } else {
@@ -143,6 +175,8 @@ class ApiUpload extends ApiBase {
                                $this->mParams['url'], $async );
 
                }
+               
+               return true;
        }
 
        /**
@@ -225,25 +259,8 @@ class ApiUpload extends ApiBase {
                if ( !$this->mParams['ignorewarnings'] ) {
                        $warnings = $this->mUpload->checkWarnings();
                        if ( $warnings ) {
-                               // Add indices
-                               $this->getResult()->setIndexedTagName( $warnings, 'warning' );
-
-                               if ( isset( $warnings['duplicate'] ) ) {
-                                       $dupes = array();
-                                       foreach ( $warnings['duplicate'] as $key => $dupe )
-                                               $dupes[] = $dupe->getName();
-                                       $this->getResult()->setIndexedTagName( $dupes, 'duplicate' );
-                                       $warnings['duplicate'] = $dupes;
-                               }
-
-                               if ( isset( $warnings['exists'] ) ) {
-                                       $warning = $warnings['exists'];
-                                       unset( $warnings['exists'] );
-                                       $warnings[$warning['warning']] = $warning['file']->getName();
-                               }
-
                                $result['result'] = 'Warning';
-                               $result['warnings'] = $warnings;
+                               $result['warnings'] = $this->transformWarnings( $warnings );
 
                                $sessionKey = $this->mUpload->stashSession();
                                if ( !$sessionKey ) {
@@ -257,6 +274,32 @@ class ApiUpload extends ApiBase {
                }
                return;
        }
+       
+       /**
+        * Transforms a warnings array returned by mUpload->checkWarnings() into
+        * something that can be directly used as API result
+        */
+       protected function transformWarnings( $warnings ) {
+               // Add indices
+               $this->getResult()->setIndexedTagName( $warnings, 'warning' );
+
+               if ( isset( $warnings['duplicate'] ) ) {
+                       $dupes = array();
+                       foreach ( $warnings['duplicate'] as $key => $dupe ) {
+                               $dupes[] = $dupe->getName();
+                       }
+                       $this->getResult()->setIndexedTagName( $dupes, 'duplicate' );
+                       $warnings['duplicate'] = $dupes;
+               }
+
+               if ( isset( $warnings['exists'] ) ) {
+                       $warning = $warnings['exists'];
+                       unset( $warnings['exists'] );
+                       $warnings[$warning['warning']] = $warning['file']->getName();
+               }
+               
+               return $warnings;       
+       }
 
        /**
         * Perform the actual upload. Returns a suitable result array on success;
@@ -290,7 +333,7 @@ class ApiUpload extends ApiBase {
                                // requested so
                                return array(
                                        'result' => 'Queued',
-                                       'sessionkey' => $error[0][1],
+                                       'statuskey' => $error[0][1],
                                );
                        } else {
                                $this->getResult()->setIndexedTagName( $error, 'error' );
@@ -320,7 +363,6 @@ class ApiUpload extends ApiBase {
                $params = array(
                        'filename' => array(
                                ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true
                        ),
                        'comment' => array(
                                ApiBase::PARAM_DFLT => ''
@@ -351,6 +393,7 @@ class ApiUpload extends ApiBase {
                        $params += array(
                                'asyncdownload' => false,
                                'leavemessage' => false,
+                               'statuskey' => null,
                        );
                }
                return $params;
@@ -375,6 +418,7 @@ class ApiUpload extends ApiBase {
                        $params += array(
                                'asyncdownload' => 'Make fetching a URL asynchronous',
                                'leavemessage' => 'If asyncdownload is used, leave a message on the user talk page if finished',
+                               'statuskey' => 'Fetch the upload status for this session key',
                        );
                }
 
index 31c7dc7..63166ef 100644 (file)
@@ -16,6 +16,8 @@
  * @ingroup JobQueue
  */
 class UploadFromUrlJob extends Job {
+       const SESSION_KEYNAME = 'wsUploadFromUrlJobData';
+       
        public $upload;
        protected $user;
 
@@ -24,14 +26,6 @@ class UploadFromUrlJob extends Job {
        }
 
        public function run() {
-               # Until we find a way to store data in sessions, set leaveMessage to
-               # true unconditionally
-               $this->params['leaveMessage'] = true;
-               # Similar for ignorewarnings. This is not really a good fallback, but
-               # there is no easy way to get a wikitext formatted warning message to
-               # show to the user
-               $this->params['ignoreWarnings'] = true;
-               
                # Initialize this object and the upload object
                $this->upload = new UploadFromUrl();
                $this->upload->initialize( 
@@ -60,6 +54,8 @@ class UploadFromUrlJob extends Job {
                if ( !$this->params['ignoreWarnings'] ) {
                        $warnings = $this->upload->checkWarnings();
                        if ( $warnings ) {              
+                               wfSetupSession( $this->params['sessionId'] );
+                                                               
                                if ( $this->params['leaveMessage'] ) {
                                        $this->user->leaveUserMessage( 
                                                wfMsg( 'upload-warning-subj' ),
@@ -72,7 +68,10 @@ class UploadFromUrlJob extends Job {
                                                'warnings', $warnings );
                                }
                                
-                               // FIXME: stash in session
+                               # Stash the upload in the session
+                               $this->upload->stashSession( $this->params['sessionKey'] );
+                               session_write_close();
+                               
                                return true;
                        }
                }
@@ -111,28 +110,44 @@ class UploadFromUrlJob extends Job {
                                        ) );
                        }
                } else {
+                       wfSetupSession( $this->params['sessionId'] );                   
                        if ( $status->isOk() ) {
                                $this->storeResultInSession( 'Success', 
-                                       'filename', $this->getLocalFile()->getName() );
+                                       'filename', $this->upload->getLocalFile()->getName() );
                        } else {
                                $this->storeResultInSession( 'Failure',
                                        'errors', $status->getErrorsArray() );
                        }
-                       
+                       session_write_close();                  
                }
        }
 
        /**
-        * Store a result in the session data
-        * THIS IS BROKEN. $_SESSION does not exist when using runJobs.php
+        * Store a result in the session data. Note that the caller is responsible
+        * for appropriate session_start and session_write_close calls.
         * 
         * @param $result String: the result (Success|Warning|Failure)
         * @param $dataKey String: the key of the extra data
         * @param $dataValue Mixed: the extra data itself
         */
        protected function storeResultInSession( $result, $dataKey, $dataValue ) {
-               $session &= $_SESSION[UploadBase::getSessionKeyname()][$this->params['sessionKey']];
+               $session =& self::getSessionData( $this->params['sessionKey'] );
                $session['result'] = $result;
                $session[$dataKey] = $dataValue;
        }
+       
+       /**
+        * Initialize the session data. Sets the intial result to queued.
+        */
+       public function initializeSessionData() {
+               $session =& self::getSessionData( $this->params['sessionKey'] );
+               $$session['result'] = 'Queued';
+       }
+       
+       public static function &getSessionData( $key ) {
+               if ( !isset( $_SESSION[self::SESSION_KEYNAME][$key] ) ) {
+                       $_SESSION[self::SESSION_KEYNAME][$key] = array();
+               }
+               return $_SESSION[self::SESSION_KEYNAME][$key];
+       }
 }
index e206a24..42b3827 100644 (file)
@@ -197,8 +197,10 @@ class UploadFromUrl extends UploadBase {
                        'userName' => $user->getName(),
                        'leaveMessage' => $this->mAsync == 'async-leavemessage',
                        'ignoreWarnings' => $this->mIgnoreWarnings,
+                       'sessionId' => session_id(),
                        'sessionKey' => $sessionKey,
                ) );
+               $job->initializeSessionData();
                $job->insert();
                return $sessionKey;
        }
index 7f34f11..51d2ff6 100644 (file)
@@ -22,7 +22,7 @@ abstract class ApiTestSetup extends PHPUnit_Framework_TestCase {
        static function setupUser() {
                if ( self::$user == NULL ) {
                        self::$userName = "Useruser";
-                       self::$passWord = User::randomPassword();
+                       self::$passWord = 'Passpass';
 
                        self::$user = User::newFromName( self::$userName );
                        if ( !self::$user->getID() ) {
@@ -33,5 +33,7 @@ abstract class ApiTestSetup extends PHPUnit_Framework_TestCase {
                        self::$user->setPassword( self::$passWord );
                        self::$user->saveSettings();
                }
+               
+               $GLOBALS['wgUser'] = self::$user;
        }
 }
index b4f7e97..c2c2446 100644 (file)
@@ -1,44 +1,50 @@
 <?php
 
-/* Force User.php include for EDIT_TOKEN_SUFFIX */
-require_once dirname(__FILE__) . "/../../includes/User.php";
-
-class nullClass {
-       public function handleOutput() { }
-       public function purgeRedundantText() { }
-}
 
 class UploadFromUrlTest extends ApiTestSetup {
 
-       function setUp() {
+       public function setUp() {
                global $wgEnableUploads, $wgAllowCopyUploads;
+               parent::setup();
 
                $wgEnableUploads = true;
                $wgAllowCopyUploads = true;
-               parent::setup();
+               wfSetupSession();
 
                ini_set( 'log_errors', 1 );
                ini_set( 'error_reporting', 1 );
                ini_set( 'display_errors', 1 );
+               
+               if ( wfLocalFile( 'UploadFromUrlTest.png' )->exists() ) {
+                       $this->deleteFile( 'UploadFromUrlTest.png' );
+               }
        }
 
-       function doApiRequest( $params, $data = null ) {
-               $session = isset( $data[2] ) ? $data[2] : array();
-               $_SESSION = $session;
-
-               $req = new FauxRequest( $params, true, $session );
+       protected function doApiRequest( $params ) {
+               $sessionId = session_id();
+               session_write_close();
+               
+               $req = new FauxRequest( $params, true, $_SESSION );
                $module = new ApiMain( $req, true );
                $module->execute();
 
-               return array( $module->getResultData(), $req, $_SESSION );
+               wfSetupSession( $sessionId );
+               return array( $module->getResultData(), $req );
        }
 
-       function testClearQueue() {
+       /**
+        * Ensure that the job queue is empty before continuing
+        */
+       public function testClearQueue() {
                while ( $job = Job::pop() ) { }
                $this->assertFalse( $job );
        }
 
-       function testLogin() {
+       /**
+        * @todo Document why we test login, since the $wgUser hack used doesn't
+        * require login
+        */
+       public function testLogin() {
                $data = $this->doApiRequest( array(
                        'action' => 'login',
                        'lgname' => self::$userName,
@@ -64,19 +70,16 @@ class UploadFromUrlTest extends ApiTestSetup {
 
        /**
         * @depends testLogin
+        * @depends testClearQueue
         */
-       function testSetupUrlDownload( $data ) {
-               global $wgUser;
-               $wgUser = User::newFromName( self::$userName );
-               $wgUser->load();
-               $data[2]['wsEditToken'] = $data[2]['wsToken'];
-               $token = md5( $data[2]['wsToken'] ) . EDIT_TOKEN_SUFFIX;
+       public function testSetupUrlDownload( $data ) { 
+               $token = self::$user->editToken();
                $exception = false;
 
                try {
                        $this->doApiRequest( array(
                                'action' => 'upload',
-                       ), $data );
+                       ) );
                } catch ( UsageException $e ) {
                        $exception = true;
                        $this->assertEquals( "The token parameter must be set", $e->getMessage() );
@@ -91,7 +94,7 @@ class UploadFromUrlTest extends ApiTestSetup {
                        ), $data );
                } catch ( UsageException $e ) {
                        $exception = true;
-                       $this->assertEquals( "One of the parameters sessionkey, file, url is required",
+                       $this->assertEquals( "One of the parameters sessionkey, file, url, statuskey is required",
                                $e->getMessage() );
                }
                $this->assertTrue( $exception, "Got exception" );
@@ -109,7 +112,7 @@ class UploadFromUrlTest extends ApiTestSetup {
                }
                $this->assertTrue( $exception, "Got exception" );
 
-               $wgUser->removeGroup( 'sysop' );
+               self::$user->removeGroup( 'sysop' );
                $exception = false;
                try {
                        $this->doApiRequest( array(
@@ -124,8 +127,8 @@ class UploadFromUrlTest extends ApiTestSetup {
                }
                $this->assertTrue( $exception, "Got exception" );
 
-               $wgUser->addGroup( '*' );
-               $wgUser->addGroup( 'sysop' );
+               self::$user->addGroup( '*' );
+               self::$user->addGroup( 'sysop' );
                $exception = false;
                $data = $this->doApiRequest( array(
                        'action' => 'upload',
@@ -143,45 +146,65 @@ class UploadFromUrlTest extends ApiTestSetup {
 
        /**
         * @depends testLogin
+        * @depends testClearQueue
         */
-       function testDoDownload( $data ) {
-               global $wgUser;
-               $data[2]['wsEditToken'] = $data[2]['wsToken'];
-               $token = md5( $data[2]['wsToken'] ) . EDIT_TOKEN_SUFFIX;
+       public function testAsyncUpload( $data ) {
+               $token = self::$user->editToken();
 
-               $wgUser->addGroup( 'users' );
-               $data = $this->doApiRequest( array(
-                       'action' => 'upload',
-                       'filename' => 'UploadFromUrlTest.png',
-                       'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
-                       'asyncdownload' => 1,
-                       'token' => $token,
-               ), $data );
+               self::$user->addGroup( 'users' );
 
-               $job = Job::pop();
-               $this->assertEquals( 'UploadFromUrlJob', get_class( $job ) );
+               $data = $this->doAsyncUpload( $token, true );
+               $this->assertEquals( $data[0]['upload']['result'], 'Success' );
+               $this->assertEquals( $data[0]['upload']['filename'], 'UploadFromUrlTest.png' );
+               $this->assertTrue( wfLocalFile( $data[0]['upload']['filename'] )->exists() );
+               
+               $this->deleteFile( 'UploadFromUrlTest.png' );
 
-               $status = $job->run();
+               return $data;
+       }
+
+       /**
+        * @depends testLogin
+        * @depends testClearQueue
+        */
+       public function testAsyncUploadWarning( $data ) {
+               $token = self::$user->editToken();
+
+               self::$user->addGroup( 'users' );
 
-               $this->assertTrue( $status );
+
+               $data = $this->doAsyncUpload( $token );
+               
+               $this->assertEquals( $data[0]['upload']['result'], 'Warning' );
+               $this->assertTrue( isset( $data[0]['upload']['sessionkey'] ) );
+               
+               $data = $this->doApiRequest( array( 
+                       'action' => 'upload',
+                       'sessionkey' => $data[0]['upload']['sessionkey'],
+                       'filename' => 'UploadFromUrlTest.png',
+                       'ignorewarnings' => 1,
+                       'token' => $token,
+               ) );
+               $this->assertEquals( $data[0]['upload']['result'], 'Success' );
+               $this->assertEquals( $data[0]['upload']['filename'], 'UploadFromUrlTest.png' );
+               $this->assertTrue( wfLocalFile( $data[0]['upload']['filename'] )->exists() );
+               
+               $this->deleteFile( 'UploadFromUrlTest.png' );
 
                return $data;
        }
 
        /**
         * @depends testLogin
+        * @depends testClearQueue
         */
-       function testSyncDownload( $data ) {
-               global $wgUser;
-               $data[2]['wsEditToken'] = $data[2]['wsToken'];
-               $token = md5( $data[2]['wsToken'] ) . EDIT_TOKEN_SUFFIX;
+       public function testSyncDownload( $data ) {
+               $token = self::$user->editToken();
 
                $job = Job::pop();
                $this->assertFalse( $job, 'Starting with an empty jobqueue' );
 
-               //$this->deleteFile( 'UploadFromUrlTest.png' );
-
-               $wgUser->addGroup( 'users' );
+               self::$user->addGroup( 'users' );
                $data = $this->doApiRequest( array(
                        'action' => 'upload',
                        'filename' => 'UploadFromUrlTest.png',
@@ -194,25 +217,121 @@ class UploadFromUrlTest extends ApiTestSetup {
                $this->assertFalse( $job );
 
                $this->assertEquals( 'Success', $data[0]['upload']['result'] );
+               $this->deleteFile( 'UploadFromUrlTest.png' );
 
                return $data;
        }
+       
+       public function testLeaveMessage() {
+               $token = self::$user->editToken();
+               
+               $talk = self::$user->getTalkPage();
+               if ( $talk->exists() ) {
+                       $a = new Article( $talk );
+                       $a->doDeleteArticle( '' );
+               }
+               
+               $this->assertFalse( (bool)$talk->getArticleId( GAID_FOR_UPDATE ), 'User talk does not exist' );
+               
+               $data = $this->doApiRequest( array(
+                       'action' => 'upload',
+                       'filename' => 'UploadFromUrlTest.png',
+                       'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
+                       'asyncdownload' => 1,
+                       'token' => $token,
+                       'leavemessage' => 1,
+                       'ignorewarnings' => 1,
+               ) );
+               
+               $job = Job::pop();
+               $job->run();
+               
+               $this->assertTrue( wfLocalFile( 'UploadFromUrlTest.png' )->exists() );          
+               $this->assertTrue( (bool)$talk->getArticleId( GAID_FOR_UPDATE ), 'User talk exists' );
+               
+               $this->deleteFile( 'UploadFromUrlTest.png' );
+               
+               $talkRev = Revision::newFromTitle( $talk );
+               $talkSize = $talkRev->getSize();
+               
+               $exception = false;
+               try {
+                       $data = $this->doApiRequest( array(
+                               'action' => 'upload',
+                               'filename' => 'UploadFromUrlTest.png',
+                               'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
+                               'asyncdownload' => 1,
+                               'token' => $token,
+                               'leavemessage' => 1,
+                       ) );
+               } catch ( UsageException $e ) {
+                       $exception = true;
+                       $this->assertEquals( 'Using leavemessage without ignorewarnings is not supported', $e->getMessage() );
+               }
+               $this->assertTrue( $exception );
+               
+               $job = Job::pop();
+               $this->assertFalse( $job );
+               
+               return;
+               
+               // Broken until using leavemessage with ignorewarnings is supported
+               $job->run();
+               
+               $this->assertFalse( wfLocalFile( 'UploadFromUrlTest.png' )->exists() );
+               
+               $talkRev = Revision::newFromTitle( $talk );
+               $this->assertTrue( $talkRev->getSize() > $talkSize, 'New message left' );
 
+               
+       }
+       
        /**
-        * @depends testDoDownload
+        * Helper function to perform an async upload, execute the job and fetch 
+        * the status
+        * 
+        * @return array The result of action=upload&statuskey=key
         */
-       function testVerifyDownload( $data ) {
-               $t = Title::newFromText( "UploadFromUrlTest.png", NS_FILE );
-
-               $this->assertTrue( $t->exists() );
-
-               $this->deleteFile( 'UploadFromUrlTest.png' );
-        }
+       private function doAsyncUpload( $token, $ignoreWarnings = false, $leaveMessage = false ) {
+               $params = array(
+                       'action' => 'upload',
+                       'filename' => 'UploadFromUrlTest.png',
+                       'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
+                       'asyncdownload' => 1,
+                       'token' => $token,
+               );
+               if ( $ignoreWarnings ) {
+                       $params['ignorewarnings'] = 1;
+               }
+               if ( $leaveMessage ) {
+                       $params['leavemessage'] = 1;
+               }
+               
+               $data = $this->doApiRequest( $params );
+               $this->assertEquals( $data[0]['upload']['result'], 'Queued' );
+               $this->assertTrue( isset( $data[0]['upload']['statuskey'] ) );
+               $statusKey = $data[0]['upload']['statuskey'];
+               
+               $job = Job::pop();
+               $this->assertEquals( 'UploadFromUrlJob', get_class( $job ) );
+               
+               $status = $job->run();
+               $this->assertTrue( $status );
+               
+               $data = $this->doApiRequest( array( 
+                       'action' => 'upload',
+                       'statuskey' => $statusKey,
+                       'token' => $token,
+               ) );
+               
+               return $data;
+       }
+       
 
        /**
         *
         */
-       function deleteFile( $name ) {
+       protected function deleteFile( $name ) {
                $t = Title::newFromText( $name, NS_FILE );
                $this->assertTrue($t->exists(), "File '$name' exists");
 
index 927154b..5966a6e 100644 (file)
@@ -170,6 +170,10 @@ class UploadFromUrlTestSuite extends PHPUnit_Framework_TestSuite {
        }
 
        public static function suite() {
-               return new UploadFromUrlTestSuite( 'UploadFromUrlTest' );
+               // Hack to invoke the autoloader required to get phpunit to recognize
+               // the UploadFromUrlTest class 
+               class_exists( 'UploadFromUrlTest' );
+               $suite = new UploadFromUrlTestSuite( 'UploadFromUrlTest' );
+               return $suite;
        }
 }