}
/**
- * Gets called after successfull removal.
- * Can be overriden to get rid of linked data.
+ * Gets called after successful removal.
+ * Can be overridden to get rid of linked data.
*
* @since 1.20
*/
* - nonLocking : No locks are acquired for the operations.
* This can increase performance for non-critical writes.
* This has no effect unless the 'force' flag is set.
- * - allowStale : Don't require the latest available data.
- * This can increase performance for non-critical writes.
- * This has no effect unless the 'force' flag is set.
* - nonJournaled : Don't log this operation batch in the file journal.
* This limits the ability of recovery scripts.
* - parallelize : Try to do operations in parallel when possible.
}
if ( empty( $opts['force'] ) ) { // sanity
unset( $opts['nonLocking'] );
- unset( $opts['allowStale'] );
}
return $this->doOperationsInternal( $ops, $opts );
}
protected $state = self::STATE_NEW; // integer
protected $failed = false; // boolean
protected $async = false; // boolean
- protected $useLatest = true; // boolean
protected $batchId; // string
protected $doOperation = true; // boolean; operation is not a no-op
$this->batchId = $batchId;
}
- /**
- * Whether to allow stale data for file reads and stat checks
- *
- * @param $allowStale bool
- * @return void
- */
- final public function allowStaleReads( $allowStale ) {
- $this->useLatest = !$allowStale;
- }
-
/**
* Get the value of the parameter with the given name
*
if ( isset( $predicates['exists'][$source] ) ) {
return $predicates['exists'][$source]; // previous op assures this
} else {
- $params = array( 'src' => $source, 'latest' => $this->useLatest );
+ $params = array( 'src' => $source, 'latest' => true );
return $this->backend->fileExists( $params );
}
}
} elseif ( isset( $predicates['exists'][$source] ) && !$predicates['exists'][$source] ) {
return false; // previous op assures this
} else {
- $params = array( 'src' => $source, 'latest' => $this->useLatest );
+ $params = array( 'src' => $source, 'latest' => true );
return $this->backend->getFileSha1Base36( $params );
}
}
* $opts is an array of options, including:
* - force : Errors that would normally cause a rollback do not.
* The remaining operations are still attempted if any fail.
- * - allowStale : Don't require the latest available data.
- * This can increase performance for non-critical writes.
- * This has no effect unless the 'force' flag is set.
* - nonJournaled : Don't log this operation batch in the file journal.
* - concurrency : Try to do this many operations in parallel when possible.
*
}
$batchId = $journal->getTimestampedUUID();
- $allowStale = !empty( $opts['allowStale'] );
$ignoreErrors = !empty( $opts['force'] );
$journaled = empty( $opts['nonJournaled'] );
$maxConcurrency = isset( $opts['concurrency'] ) ? $opts['concurrency'] : 1;
foreach ( $performOps as $index => $fileOp ) {
$backendName = $fileOp->getBackend()->getName();
$fileOp->setBatchId( $batchId ); // transaction ID
- $fileOp->allowStaleReads( $allowStale ); // consistency level
// Decide if this op can be done concurrently within this sub-batch
// or if a new concurrent sub-batch must be started after this one...
if ( $fileOp->dependsOn( $curBatchDeps )
}
$job = Job::factory( $row->job_cmd, $title,
self::extractBlob( $row->job_params ), $row->job_id );
+ $job->id = $row->job_id; // XXX: work around broken subclasses
// Flag this job as an old duplicate based on its "root" job...
if ( $this->isRootJobOldDuplicate( $job ) ) {
$job = DuplicateJob::newFromJob( $job ); // convert to a no-op
* @return Job|bool
*/
protected function doAck( Job $job ) {
+ if ( !$job->getId() ) {
+ throw new MWException( "Job of type '{$job->getType()}' has no ID." );
+ }
+
$dbw = $this->getMasterDB();
$dbw->commit( __METHOD__, 'flush' ); // flush existing transaction
}
/**
- * @see ORMRow::save
+ * @see IORMRow::save
* @see Site::save
*
* @since 1.21
* @return boolean Success indicator
*/
public function save( $functionName = null ) {
- $dbw = wfGetDB( DB_MASTER );
+ $dbw = $this->table->getWriteDbConnection();
$trx = $dbw->trxLevel();
return $success;
}
+ /**
+ * @since 1.21
+ *
+ * @see ORMRow::onRemoved
+ */
+ protected function onRemoved() {
+ $dbw = $this->table->getWriteDbConnection();
+
+ $dbw->delete(
+ 'site_identifiers',
+ array(
+ 'si_site' => $this->getId()
+ ),
+ __METHOD__
+ );
+
+ parent::onRemoved();
+ }
+
/**
* @see Site::setPath
*
'DummyContentHandlerForTesting' => "$testDir/phpunit/includes/content/ContentHandlerTest.php",
'DummyContentForTesting' => "$testDir/phpunit/includes/content/ContentHandlerTest.php",
'ContentHandlerTest' => "$testDir/phpunit/includes/content/ContentHandlerTest.php",
- 'JavascriptContentTest' => "$testDir/phpunit/includes/content/JavascriptContentTest.php",
+ 'JavaScriptContentTest' => "$testDir/phpunit/includes/content/JavaScriptContentTest.php",
'TextContentTest' => "$testDir/phpunit/includes/content/TextContentTest.php",
'WikitextContentTest' => "$testDir/phpunit/includes/content/WikitextContentTest.php",
--- /dev/null
+<?php
+
+/**
+ * @group ContentHandler
+ * @group Database
+ * ^--- needed, because we do need the database to test link updates
+ */
+class JavaScriptContentTest extends TextContentTest {
+
+ public function newContent( $text ) {
+ return new JavaScriptContent( $text );
+ }
+
+ public static function dataGetParserOutput() {
+ return array(
+ array(
+ 'MediaWiki:Test.js',
+ null,
+ "hello <world>\n",
+ "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello <world>\n\n</pre>"
+ ),
+ array(
+ 'MediaWiki:Test.js',
+ null,
+ "hello(); // [[world]]\n",
+ "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello(); // [[world]]\n\n</pre>",
+ array(
+ 'Links' => array(
+ array( 'World' => 0 )
+ )
+ )
+ ),
+
+ // TODO: more...?
+ );
+ }
+
+ // XXX: Unused function
+ public static function dataGetSection() {
+ return array(
+ array( WikitextContentTest::$sections,
+ '0',
+ null
+ ),
+ array( WikitextContentTest::$sections,
+ '2',
+ null
+ ),
+ array( WikitextContentTest::$sections,
+ '8',
+ null
+ ),
+ );
+ }
+
+ // XXX: Unused function
+ public static function dataReplaceSection() {
+ return array(
+ array( WikitextContentTest::$sections,
+ '0',
+ 'No more',
+ null,
+ null
+ ),
+ array( WikitextContentTest::$sections,
+ '',
+ 'No more',
+ null,
+ null
+ ),
+ array( WikitextContentTest::$sections,
+ '2',
+ "== TEST ==\nmore fun",
+ null,
+ null
+ ),
+ array( WikitextContentTest::$sections,
+ '8',
+ 'No more',
+ null,
+ null
+ ),
+ array( WikitextContentTest::$sections,
+ 'new',
+ 'No more',
+ 'New',
+ null
+ ),
+ );
+ }
+
+ public function testAddSectionHeader( ) {
+ $content = $this->newContent( 'hello world' );
+ $c = $content->addSectionHeader( 'test' );
+
+ $this->assertTrue( $content->equals( $c ) );
+ }
+
+ // XXX: currently, preSaveTransform is applied to scripts. this may change or become optional.
+ public static function dataPreSaveTransform() {
+ return array(
+ array( 'hello this is ~~~',
+ "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
+ ),
+ array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
+ 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
+ ),
+ array( " Foo \n ",
+ " Foo",
+ ),
+ );
+ }
+
+ public static function dataPreloadTransform() {
+ return array(
+ array( 'hello this is ~~~',
+ 'hello this is ~~~',
+ ),
+ array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
+ 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
+ ),
+ );
+ }
+
+ public static function dataGetRedirectTarget() {
+ return array(
+ array( '#REDIRECT [[Test]]',
+ null,
+ ),
+ array( '#REDIRECT Test',
+ null,
+ ),
+ array( '* #REDIRECT [[Test]]',
+ null,
+ ),
+ );
+ }
+
+ /**
+ * @todo: test needs database!
+ */
+ /*
+ public function getRedirectChain() {
+ $text = $this->getNativeData();
+ return Title::newFromRedirectArray( $text );
+ }
+ */
+
+ /**
+ * @todo: test needs database!
+ */
+ /*
+ public function getUltimateRedirectTarget() {
+ $text = $this->getNativeData();
+ return Title::newFromRedirectRecurse( $text );
+ }
+ */
+
+ public static function dataIsCountable() {
+ return array(
+ array( '',
+ null,
+ 'any',
+ true
+ ),
+ array( 'Foo',
+ null,
+ 'any',
+ true
+ ),
+ array( 'Foo',
+ null,
+ 'comma',
+ false
+ ),
+ array( 'Foo, bar',
+ null,
+ 'comma',
+ false
+ ),
+ array( 'Foo',
+ null,
+ 'link',
+ false
+ ),
+ array( 'Foo [[bar]]',
+ null,
+ 'link',
+ false
+ ),
+ array( 'Foo',
+ true,
+ 'link',
+ false
+ ),
+ array( 'Foo [[bar]]',
+ false,
+ 'link',
+ false
+ ),
+ array( '#REDIRECT [[bar]]',
+ true,
+ 'any',
+ true
+ ),
+ array( '#REDIRECT [[bar]]',
+ true,
+ 'comma',
+ false
+ ),
+ array( '#REDIRECT [[bar]]',
+ true,
+ 'link',
+ false
+ ),
+ );
+ }
+
+ public static function dataGetTextForSummary() {
+ return array(
+ array( "hello\nworld.",
+ 16,
+ 'hello world.',
+ ),
+ array( 'hello world.',
+ 8,
+ 'hello...',
+ ),
+ array( '[[hello world]].',
+ 8,
+ '[[hel...',
+ ),
+ );
+ }
+
+ public function testMatchMagicWord( ) {
+ $mw = MagicWord::get( "staticredirect" );
+
+ $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
+ $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word, since it's not wikitext" );
+ }
+
+ public function testUpdateRedirect( ) {
+ $target = Title::newFromText( "testUpdateRedirect_target" );
+
+ $content = $this->newContent( "#REDIRECT [[Someplace]]" );
+ $newContent = $content->updateRedirect( $target );
+
+ $this->assertTrue( $content->equals( $newContent ), "content should be unchanged since it's not wikitext" );
+ }
+
+ public function testGetModel() {
+ $content = $this->newContent( "hello world." );
+
+ $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getModel() );
+ }
+
+ public function testGetContentHandler() {
+ $content = $this->newContent( "hello world." );
+
+ $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getContentHandler()->getModelID() );
+ }
+
+ public static function dataEquals( ) {
+ return array(
+ array( new JavaScriptContent( "hallo" ), null, false ),
+ array( new JavaScriptContent( "hallo" ), new JavaScriptContent( "hallo" ), true ),
+ array( new JavaScriptContent( "hallo" ), new CssContent( "hallo" ), false ),
+ array( new JavaScriptContent( "hallo" ), new JavaScriptContent( "HALLO" ), false ),
+ );
+ }
+
+}
+++ /dev/null
-<?php
-
-/**
- * @group ContentHandler
- * @group Database
- * ^--- needed, because we do need the database to test link updates
- */
-class JavascriptContentTest extends TextContentTest {
-
- public function newContent( $text ) {
- return new JavascriptContent( $text );
- }
-
- public static function dataGetParserOutput() {
- return array(
- array(
- 'MediaWiki:Test.js',
- null,
- "hello <world>\n",
- "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello <world>\n\n</pre>"
- ),
- array(
- 'MediaWiki:Test.js',
- null,
- "hello(); // [[world]]\n",
- "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello(); // [[world]]\n\n</pre>",
- array(
- 'Links' => array(
- array( 'World' => 0 )
- )
- )
- ),
-
- // TODO: more...?
- );
- }
-
- // XXX: Unused function
- public static function dataGetSection() {
- return array(
- array( WikitextContentTest::$sections,
- '0',
- null
- ),
- array( WikitextContentTest::$sections,
- '2',
- null
- ),
- array( WikitextContentTest::$sections,
- '8',
- null
- ),
- );
- }
-
- // XXX: Unused function
- public static function dataReplaceSection() {
- return array(
- array( WikitextContentTest::$sections,
- '0',
- 'No more',
- null,
- null
- ),
- array( WikitextContentTest::$sections,
- '',
- 'No more',
- null,
- null
- ),
- array( WikitextContentTest::$sections,
- '2',
- "== TEST ==\nmore fun",
- null,
- null
- ),
- array( WikitextContentTest::$sections,
- '8',
- 'No more',
- null,
- null
- ),
- array( WikitextContentTest::$sections,
- 'new',
- 'No more',
- 'New',
- null
- ),
- );
- }
-
- public function testAddSectionHeader( ) {
- $content = $this->newContent( 'hello world' );
- $c = $content->addSectionHeader( 'test' );
-
- $this->assertTrue( $content->equals( $c ) );
- }
-
- // XXX: currently, preSaveTransform is applied to scripts. this may change or become optional.
- public static function dataPreSaveTransform() {
- return array(
- array( 'hello this is ~~~',
- "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
- ),
- array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
- 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
- ),
- array( " Foo \n ",
- " Foo",
- ),
- );
- }
-
- public static function dataPreloadTransform() {
- return array(
- array( 'hello this is ~~~',
- 'hello this is ~~~',
- ),
- array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
- 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
- ),
- );
- }
-
- public static function dataGetRedirectTarget() {
- return array(
- array( '#REDIRECT [[Test]]',
- null,
- ),
- array( '#REDIRECT Test',
- null,
- ),
- array( '* #REDIRECT [[Test]]',
- null,
- ),
- );
- }
-
- /**
- * @todo: test needs database!
- */
- /*
- public function getRedirectChain() {
- $text = $this->getNativeData();
- return Title::newFromRedirectArray( $text );
- }
- */
-
- /**
- * @todo: test needs database!
- */
- /*
- public function getUltimateRedirectTarget() {
- $text = $this->getNativeData();
- return Title::newFromRedirectRecurse( $text );
- }
- */
-
- public static function dataIsCountable() {
- return array(
- array( '',
- null,
- 'any',
- true
- ),
- array( 'Foo',
- null,
- 'any',
- true
- ),
- array( 'Foo',
- null,
- 'comma',
- false
- ),
- array( 'Foo, bar',
- null,
- 'comma',
- false
- ),
- array( 'Foo',
- null,
- 'link',
- false
- ),
- array( 'Foo [[bar]]',
- null,
- 'link',
- false
- ),
- array( 'Foo',
- true,
- 'link',
- false
- ),
- array( 'Foo [[bar]]',
- false,
- 'link',
- false
- ),
- array( '#REDIRECT [[bar]]',
- true,
- 'any',
- true
- ),
- array( '#REDIRECT [[bar]]',
- true,
- 'comma',
- false
- ),
- array( '#REDIRECT [[bar]]',
- true,
- 'link',
- false
- ),
- );
- }
-
- public static function dataGetTextForSummary() {
- return array(
- array( "hello\nworld.",
- 16,
- 'hello world.',
- ),
- array( 'hello world.',
- 8,
- 'hello...',
- ),
- array( '[[hello world]].',
- 8,
- '[[hel...',
- ),
- );
- }
-
- public function testMatchMagicWord( ) {
- $mw = MagicWord::get( "staticredirect" );
-
- $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
- $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word, since it's not wikitext" );
- }
-
- public function testUpdateRedirect( ) {
- $target = Title::newFromText( "testUpdateRedirect_target" );
-
- $content = $this->newContent( "#REDIRECT [[Someplace]]" );
- $newContent = $content->updateRedirect( $target );
-
- $this->assertTrue( $content->equals( $newContent ), "content should be unchanged since it's not wikitext" );
- }
-
- public function testGetModel() {
- $content = $this->newContent( "hello world." );
-
- $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getModel() );
- }
-
- public function testGetContentHandler() {
- $content = $this->newContent( "hello world." );
-
- $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getContentHandler()->getModelID() );
- }
-
- public static function dataEquals( ) {
- return array(
- array( new JavascriptContent( "hallo" ), null, false ),
- array( new JavascriptContent( "hallo" ), new JavascriptContent( "hallo" ), true ),
- array( new JavascriptContent( "hallo" ), new CssContent( "hallo" ), false ),
- array( new JavascriptContent( "hallo" ), new JavascriptContent( "HALLO" ), false ),
- );
- }
-
-}
return array(
array( new TextContent( "hallo" ), null, false ),
array( new TextContent( "hallo" ), new TextContent( "hallo" ), true ),
- array( new TextContent( "hallo" ), new JavascriptContent( "hallo" ), false ),
+ array( new TextContent( "hallo" ), new JavaScriptContent( "hallo" ), false ),
array( new TextContent( "hallo" ), new WikitextContent( "hallo" ), false ),
array( new TextContent( "hallo" ), new TextContent( "HALLO" ), false ),
);
return array(
array( new WikitextContent( "hallo" ), null, false ),
array( new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ),
- array( new WikitextContent( "hallo" ), new JavascriptContent( "hallo" ), false ),
+ array( new WikitextContent( "hallo" ), new JavaScriptContent( "hallo" ), false ),
array( new WikitextContent( "hallo" ), new TextContent( "hallo" ), false ),
array( new WikitextContent( "hallo" ), new WikitextContent( "HALLO" ), false ),
);
/**
* @dataProvider constructorTestProvider
*/
- public function testSave( array $data, $loadDefaults ) {
+ public function testSaveAndRemove( array $data, $loadDefaults ) {
$item = $this->getRowInstance( $data, $loadDefaults );
$this->assertTrue( $item->save() );
$this->assertEquals( $id, $item->getId() );
$this->verifyFields( $item, $data );
- }
-
- /**
- * @dataProvider constructorTestProvider
- * @depends testSave
- */
- public function testRemove( array $data, $loadDefaults ) {
- $item = $this->getRowInstance( $data, $loadDefaults );
$this->assertTrue( $item->remove() );