Skip to content

Commit

Permalink
Merge pull request #405 from SemanticMediaWiki/hotfix-linksupdate
Browse files Browse the repository at this point in the history
MW 1.23+ / Hotfix for empty ParserOutput caused by RefreshLinksJob
  • Loading branch information
JeroenDeDauw committed Jul 19, 2014
2 parents 82da90b + 464955e commit fa96681
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 8 deletions.
52 changes: 45 additions & 7 deletions includes/src/MediaWiki/Hooks/LinksUpdateConstructed.php
Expand Up @@ -3,15 +3,16 @@
namespace SMW\MediaWiki\Hooks;

use SMW\Application;
use SMW\ContentParser;
use SMW\SemanticData;

use LinksUpdate;

/**
* LinksUpdateConstructed hook is called at the end of LinksUpdate() is contruction
* LinksUpdateConstructed hook is called at the end of LinksUpdate()
*
* @see http://www.mediawiki.org/wiki/Manual:Hooks/LinksUpdateConstructed
*
* @ingroup FunctionHook
*
* @license GNU GPL v2+
* @since 1.9
*
Expand All @@ -24,6 +25,11 @@ class LinksUpdateConstructed {
*/
protected $linksUpdate = null;

/**
* @var Application
*/
private $application = null;

/**
* @since 1.9
*
Expand All @@ -40,17 +46,49 @@ public function __construct( LinksUpdate $linksUpdate ) {
*/
public function process() {

$this->application = Application::getInstance();

/**
* @var ParserData $parserData
*/
$parserData = Application::getInstance()->newParserData(
$this->linksUpdate->getTitle(),
$this->linksUpdate->getParserOutput()
);
$parserData = $this->application
->newParserData( $this->linksUpdate->getTitle(), $this->linksUpdate->getParserOutput() );

if ( $parserData->getSemanticData()->isEmpty() &&
( $semanticData = $this->refetchSemanticData() ) instanceOf SemanticData ) {
$parserData->setSemanticData( $semanticData );
}

$parserData->updateStore();

return true;
}

/**
* #347 showed that an external process (e.g. RefreshLinksJob) can inject a
* ParserOutput without SemanticData which forces the Store updater to create
* an empty container and clear all existing data. To ensure that for a Title
* and its current revision are really "empty" (e.g. delete action initiated
* by a human) content is re-parsed
*
* @note Parsing is expensive but it is more expensive to loose data or to
* expect that MW adheres the object contract
*/
private function refetchSemanticData() {
wfDebug( __METHOD__ . ' Empty SemanticData / re-parsing: ' . $this->linksUpdate->getTitle()->getPrefixedDBkey() . "\n" );

$contentParser = $this->application->newContentParser( $this->linksUpdate->getTitle() );
$parserOutput = $contentParser->parse()->getOutput();

if ( $parserOutput === null ) {
return null;
}

if ( method_exists( $parserOutput, 'getExtensionData' ) ) {
return $parserOutput->getExtensionData( 'smwdata' );
}

return $parserOutput->mSMWData;
}

}
@@ -0,0 +1,64 @@
<?php

namespace SMW\Tests\Integration\MediaWiki;

use SMW\Tests\Util\SemanticDataValidator;
use SMW\Tests\Util\ParserFactory;
use SMW\Tests\Util\PageCreator;
use SMW\Tests\MwDBaseUnitTestCase;

use SMW\ContentParser;
use SMW\ParserData;
use SMW\DIWikiPage;

use Title;
use LinksUpdate;
use ParserOutput;

/**
* @ingroup Test
*
* @group SMW
* @group SMWExtension
* @group semantic-mediawiki-integration
* @group mediawiki-databaseless
* @group medium
*
* @license GNU GPL v2+
* @since 2.0
*
* @author mwjames
*/
class LinksUpdateEmptyParserOutputDBIntegrationTest extends MwDBaseUnitTestCase {

public function testDoUpdate() {

$title = Title::newFromText( __METHOD__ );
$subject = DIWikiPage::newFromTitle( $title );

$pageCreator = new PageCreator();

$pageCreator
->createPage( $title )
->doEdit( '[[Has some property::LinksUpdateConstructedOnEmptyParserOutput]]' );

$propertiesCountBeforeUpdate = count( $this->getStore()->getSemanticData( $subject )->getProperties() );

/**
* See #347 and LinksUpdateConstructed
*/
$linksUpdate = new LinksUpdate( $title, new ParserOutput() );
$linksUpdate->doUpdate();

/**
* Asserts that before and after the update, the SemanticData container
* holds the same amount of properties despite the fact that the ParserOutput
* was invoked empty
*/
$this->assertCount(
$propertiesCountBeforeUpdate,
$this->getStore()->getSemanticData( $subject )->getProperties()
);
}

}
Expand Up @@ -231,7 +231,7 @@ public function propertyCountProvider() {
'msg' => 'Asserts property Aa, Fuyu, _SKEY, and _MDAT from the previous state as no update has been made yet'
),
'poAfter' => array(
'count' => 1,
'count' => 0,
'msg' => 'Asserts property _MDAT exists after the update'
),
'storeAfter' => array(
Expand Down

0 comments on commit fa96681

Please sign in to comment.