Mwjames has uploaded a new change for review.
https://gerrit.wikimedia.org/r/57701
Change subject: Split up ParserData responsibility, move store update into
ParserDataStorage
......................................................................
Split up ParserData responsibility, move store update into ParserDataStorage
ParserData now only handles methods directly involved in
manipulating the ParserOutput/Semenatic Data object while
ParserDataStorage handles the update of the store with
the data coming from the ParserData object.
Change-Id: Iaa1a3d9d08918f33a98792b3ea2e9d7c5747dba5
---
M SemanticMediaWiki.hooks.php
M includes/ParserData.php
A includes/ParserDataStorage.php
M includes/Setup.php
M includes/jobs/SMW_UpdateJob.php
A tests/phpunit/includes/ParserDataStorageTest.php
M tests/phpunit/includes/ParserDataTest.php
M tests/phpunit/includes/parserhooks/AskParserFunctionTest.php
M tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php
M tests/phpunit/includes/parserhooks/SetParserFunctionTest.php
M tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php
M tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php
12 files changed, 495 insertions(+), 353 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/SemanticMediaWiki
refs/changes/01/57701/1
diff --git a/SemanticMediaWiki.hooks.php b/SemanticMediaWiki.hooks.php
index f0d45a5..27941cd 100644
--- a/SemanticMediaWiki.hooks.php
+++ b/SemanticMediaWiki.hooks.php
@@ -486,12 +486,12 @@
// Separate globals from local state
// FIXME Do a new SMW\Settings( $GLOBALS );
- $options = array(
+ $settings = array(
'smwgUseCategoryHierarchy' =>
$GLOBALS['smwgUseCategoryHierarchy'],
'smwgCategoriesAsInstances' =>
$GLOBALS['smwgCategoriesAsInstances'],
);
- $parserData = new SMW\ParserData( $parser->getTitle(),
$parser->getOutput(), $options );
+ $parserData = new SMW\ParserData( $parser->getTitle(),
$parser->getOutput(), $settings );
$parserData->addCategories(
$parser->getOutput()->getCategoryLinks() );
$parserData->addDefaultSort( $parser->getDefaultSort() );
@@ -499,7 +499,8 @@
// updated as well for all other cases onLinksUpdateConstructed
will
// initiate the store update
if( $cache->get( 'smw:autorefresh:' .
$parser->getTitle()->getPrefixedDBkey() ) ){
- $parserData->updateStore();
+ $parserDataStorage = new SMW\ParserDataStorage(
$parserData );
+ $parserDataStorage->updateStore();
}
$cache->delete( 'smw:autorefresh:' .
$parser->getTitle()->getPrefixedDBkey() );
@@ -521,8 +522,11 @@
* @return true
*/
public static function onLinksUpdateConstructed( $linksUpdate ) {
- $parserData = new SMW\ParserData( $linksUpdate->getTitle(),
$linksUpdate->getParserOutput() );
- $parserData->updateStore();
+ $parserDataStorage = new SMW\ParserDataStorage( new
SMW\ParserData(
+ $linksUpdate->getTitle(),
+ $linksUpdate->getParserOutput() )
+ );
+ $parserDataStorage->updateStore();
return true;
}
diff --git a/includes/ParserData.php b/includes/ParserData.php
index f77b365..4dcd8a1 100644
--- a/includes/ParserData.php
+++ b/includes/ParserData.php
@@ -6,9 +6,7 @@
use WikiPage;
use ParserOutput;
use MWException;
-use Job;
-use SMWStore;
use SMWDIWikiPage;
use SMWPropertyValue;
use SMWSemanticData;
@@ -17,7 +15,6 @@
use SMWDIBlob;
use SMWDIBoolean;
use SMWDITime;
-use SMWUpdateJob;
/**
* Interface handling semantic data storage to a ParserOutput instance
@@ -93,13 +90,6 @@
public function clearData();
/**
- * Updates the store with semantic data fetched from a ParserOutput
object
- *
- * @since 1.9
- */
- public function updateStore();
-
- /**
* Returns an report about activities that occurred during processing
*
* @since 1.9
@@ -132,39 +122,28 @@
/**
* Represents Title object
- * @var $title
*/
protected $title;
/**
* Represents ParserOutput object
- * @var $parserOutput
*/
protected $parserOutput;
/**
* Represents SMWSemanticData object
- * @var $semanticData
*/
protected $semanticData;
/**
* Represents collected errors
- * @var $errors
*/
protected $errors = array();
/**
* Represents invoked GLOBALS
- * @var $options
*/
- protected $options;
-
- /**
- * Represents invoked $smwgEnableUpdateJobs
- * @var $updateJobs
- */
- protected $updateJobs = true;
+ protected $settings;
/**
* Allows explicitly to switch storage method, MW 1.21 comes with a new
@@ -185,13 +164,12 @@
*
* @param \Title $title
* @param \ParserOutput $parserOutput
- * @param array $options
+ * @param array $settings
*/
- public function __construct( Title $title, ParserOutput $parserOutput,
array $options = array() ) {
+ public function __construct( Title $title, ParserOutput $parserOutput,
array $settings = array() ) {
$this->title = $title;
$this->parserOutput = $parserOutput;
- $this->options = $options;
- $this->updateJobs = $GLOBALS['smwgEnableUpdateJobs'];
+ $this->settings = $settings;
$this->setData();
}
@@ -273,16 +251,6 @@
}
/**
- * Explicitly disable update jobs (e.g when running store update
- * in the job queue)
- *
- * @since 1.9
- */
- public function disableUpdateJobs() {
- $this->updateJobs = false;
- }
-
- /**
* Returns instantiated semanticData container
*
* @since 1.9
@@ -290,18 +258,6 @@
* @return \SMWSemanticData
*/
public function getData() {
- return $this->semanticData;
- }
-
- /**
- * FIXME use getData() instead
- * AskParserFunctionTest
- *
- * @since 1.9
- *
- * @return \SMWSemanticData
- */
- public function getSemanticData() {
return $this->semanticData;
}
@@ -420,14 +376,14 @@
// Iterate over available categories
foreach ( $categoryLinks as $catname ) {
- if ( $this->options['smwgCategoriesAsInstances'] && (
$this->getTitle()->getNamespace() !== NS_CATEGORY ) ) {
+ if ( $this->settings['smwgCategoriesAsInstances'] && (
$this->getTitle()->getNamespace() !== NS_CATEGORY ) ) {
$this->semanticData->addPropertyObjectValue(
new SMWDIProperty(
SMWDIProperty::TYPE_CATEGORY ),
new SMWDIWikiPage( $catname,
NS_CATEGORY, '' )
);
}
- if ( $this->options['smwgUseCategoryHierarchy'] && (
$this->getTitle()->getNamespace() === NS_CATEGORY ) ) {
+ if ( $this->settings['smwgUseCategoryHierarchy'] && (
$this->getTitle()->getNamespace() === NS_CATEGORY ) ) {
$this->semanticData->addPropertyObjectValue(
new SMWDIProperty(
SMWDIProperty::TYPE_SUBCATEGORY ),
new SMWDIWikiPage( $catname,
NS_CATEGORY, '' )
@@ -479,7 +435,7 @@
// Keeps temporary account over processed properties
$processedProperty = array();
- foreach ( $this->options['smwgPageSpecialProperties'] as
$propertyId ) {
+ foreach ( $GLOBALS['smwgPageSpecialProperties'] as $propertyId
) {
// Ensure that only special properties are added that
are registered
// and only added once
@@ -522,281 +478,4 @@
}
}
- /**
- * Updates the store with semantic data attached to a ParserOutput
object
- *
- * This function takes care of storing the collected semantic data and
takes
- * care of clearing out any outdated entries for the processed page. It
assume that
- * parsing has happened and that all relevant data is contained in the
provided parser
- * output.
- *
- * Optionally, this function also takes care of triggering indirect
updates that might be
- * needed for overall database consistency. If the saved page describes
a property or data type,
- * the method checks whether the property type, the data type, the
allowed values, or the
- * conversion factors have changed. If so, it triggers SMWUpdateJobs
for the relevant articles,
- * which then asynchronously update the semantic data in the database.
- *
- * @todo FIXME: Some job generations here might create too many jobs at
once
- * on a large wiki. Use incremental jobs instead.
- *
- * To disable jobs either set $smwgEnableUpdateJobs = false or invoke
- * SMW\ParserData::disableUpdateJobs()
- *
- * Called from SMWUpdateJob::run, SMWHooks::onLinksUpdateConstructed,
- * SMWHooks::onParserAfterTidy
- *
- * @since 1.9
- *
- * @return boolean
- */
- public function updateStore() {
- wfProfileIn( __METHOD__ );
-
- // FIXME get rid of globals and use options array instead while
- // invoking the constructor
- $this->options = array(
- 'smwgDeclarationProperties' =>
$GLOBALS['smwgDeclarationProperties'],
- 'smwgPageSpecialProperties' =>
$GLOBALS['smwgPageSpecialProperties']
- );
-
- $namespace = $this->title->getNamespace();
- $wikiPage = WikiPage::factory( $this->title );
- $revision = $wikiPage->getRevision();
- $store = smwfGetStore();
- $jobs = array();
-
- // Make sure to have a valid revision (null means delete etc.)
- // Check if semantic data should be processed and displayed for
a page in
- // the given namespace
- $processSemantics = $revision !== null ?
smwfIsSemanticsProcessed( $namespace ) : false;
-
- if ( $processSemantics ) {
- $user = \User::newFromId( $revision->getUser() );
- $this->addSpecialProperties( $wikiPage, $revision,
$user );
- } else {
- // data found, but do all operations as if it was empty
- $this->semanticData = new SMWSemanticData(
$this->getSubject() );
- }
-
- // Careful: storage access must happen *before* the storage
update;
- // even finding uses of a property fails after its type was
changed.
- if ( $this->updateJobs && ( $namespace === SMW_NS_PROPERTY ) ) {
- $this->getDiffPropertyTypes( $store, $jobs );
- } else if ( $this->updateJobs && ( $namespace === SMW_NS_TYPE )
) {
- $this->getDiffConversionFactors( $store, $jobs );
- }
-
- // Actually store semantic data, or at least clear it if needed
- if ( $processSemantics ) {
- $store->updateData( $this->semanticData );
- } else {
- $store->clearData( $this->semanticData->getSubject() );
- }
-
- // Job::batchInsert was deprecated in MW 1.21
- // @see JobQueueGroup::singleton()->push( $job );
- if ( $jobs !== array() ) {
- Job::batchInsert( $jobs );
- }
-
- wfProfileOut( __METHOD__ );
-
- return true;
- }
-
- /**
- * Helper method to handle diff/change in type property pages
- *
- * @note If it is a property, then we need to check if the type or the
- * allowed values have been changed.
- *
- * @since 1.9
- *
- * @param SMWStore $store
- * @param array &$jobs
- */
- protected function getDiffPropertyTypes( SMWStore $store, array &$jobs
) {
- wfProfileIn( __METHOD__ );
-
- $updatejobflag = false;
- $ptype = new SMWDIProperty( SMWDIProperty::TYPE_HAS_TYPE );
-
- // Get values from the store
- $oldtype = $store->getPropertyValues(
- $this->semanticData->getSubject(),
- $ptype
- );
-
- // Get values currently hold by the semantic container
- $newtype = $this->semanticData->getPropertyValues( $ptype );
-
- // Compare old and new type
- if ( !$this->equalDatavalues( $oldtype, $newtype ) ) {
- $updatejobflag = true;
- } else {
- // Compare values (in case of _PVAL (allowed values)
for a
- // property change must be processed again)
- foreach ( $this->options['smwgDeclarationProperties']
as $prop ) {
-
- $dataItem = new SMWDIProperty( $prop );
- $oldValues = $store->getPropertyValues(
- $this->semanticData->getSubject(),
- $dataItem
- );
- $newValues =
$this->semanticData->getPropertyValues( $dataItem );
- $updatejobflag = !$this->equalDatavalues(
$oldValues, $newValues );
- }
- }
-
- // Job generation
- if ( $updatejobflag ) {
- $prop = new SMWDIProperty( $this->title->getDBkey() );
-
- // Array of all subjects that have some value for the
given property
- $subjects = $store->getAllPropertySubjects( $prop );
-
- // Add jobs
- $this->addJobs( $subjects, $jobs );
-
- // Hook
- wfRunHooks( 'smwUpdatePropertySubjects', array( &$jobs
) );
-
- // Fetch all those that have an error property attached
and
- // re-run it through the job-queue
- $subjects = $store->getPropertySubjects(
- new SMWDIProperty( SMWDIProperty::TYPE_ERROR ),
- $this->semanticData->getSubject()
- );
-
- // Add jobs
- $this->addJobs( $subjects, $jobs );
- }
-
- wfProfileOut( __METHOD__ );
- }
-
- /**
- * Helper method to handle diff/change of conversion related properties
- *
- * @note if it is a type we need to check if the conversion factors
- * have been changed
- *
- * @since 1.9
- *
- * @param SMWStore $store
- * @param array &$jo
- */
- protected function getDiffConversionFactors( SMWStore $store, array
&$jobs ) {
- wfProfileIn( __METHOD__ );
-
- $updatejobflag = false;
- $pconv = new SMWDIProperty( SMWDIProperty::TYPE_CONVERSION );
- $ptype = new SMWDIProperty( SMWDIProperty::TYPE_HAS_TYPE );
-
- $oldfactors = smwfGetStore()->getPropertyValues(
- $this->semanticData->getSubject(),
- $pconv
- );
- $newfactors = $this->semanticData->getPropertyValues( $pconv );
-
- // Compare
- $updatejobflag = !$this->equalDatavalues( $oldfactors,
$newfactors );
-
- // Job generation
- if ( $updatejobflag ) {
-
- /// FIXME: this will kill large wikis! Use incremental
updates!
- $dataValue = SMWDataValueFactory::newTypeIdValue(
'__typ', $title->getDBkey() );
- $propertyPages = $store->getPropertySubjects( $ptype,
$dataValue );
-
- foreach ( $propertyPages as $propertyPage ) {
- // Add jobs
- $this->addJobs( array( $propertyPage ), $jobs );
-
- $prop = new SMWDIProperty(
$propertyPage->getDBkey() );
- $subjects = $store->getAllPropertySubjects(
$prop );
-
- // Add jobs
- $this->addJobs( $subjects, $jobs );
-
- $subjects = $store->getPropertySubjects(
- new SMWDIProperty(
SMWDIProperty::TYPE_ERROR ),
- $prop->getWikiPageValue()
- );
-
- // Add jobs
- $this->addJobs( $subjects, $jobs );
- }
- }
-
- wfProfileOut( __METHOD__ );
- }
-
- /**
- * Helper method to iterate over an array of SMWDIWikiPage and return
and
- * array of SMWUpdateJob jobs
- *
- * Check whether a job with the same getPrefixedDBkey string (prefixed
title,
- * with underscores and any interwiki and namespace prefixes) is already
- * registered and if so don't insert a new job. This is particular
important
- * for pages that include a large amount of subobjects where the same
Title
- * and ParserOutput object is used (subobjects are included using the
same
- * WikiPage which means the resulting ParserOutput object is the same)
- *
- * @since 1.9
- *
- * @param SMWDIWikiPage[] $subjects
- * @param array &$jobs
- */
- protected function addJobs( array $subjects, &$jobs ) {
-
- foreach ( $subjects as $subject ) {
- $duplicate = false;
- $subjectTitle = $subject->getTitle();
-
- if ( $subjectTitle instanceof Title ) {
-
- // Avoid duplicate jobs for the same title
object
- foreach ( $jobs as $job ) {
- if (
$job->getTitle()->getPrefixedDBkey() === $subjectTitle->getPrefixedDBkey() ){
- $duplicate = true;
- break;
- }
- }
- if ( !$duplicate ) {
- $jobs[] = new SMWUpdateJob(
$subjectTitle );
- }
- }
- }
- }
-
- /**
- * Helper function that compares two arrays of data values to check
whether
- * they contain the same content. Returns true if the two arrays
contain the
- * same data values (irrespective of their order), false otherwise.
- *
- * @since 1.9
- */
- protected function equalDatavalues( $oldDataValue, $newDataValue ) {
- // The hashes of all values of both arrays are taken, then
sorted
- // and finally concatenated, thus creating one long hash out of
each
- // of the data value arrays. These are compared.
- $values = array();
- foreach ( $oldDataValue as $v ) {
- $values[] = $v->getHash();
- }
-
- sort( $values );
- $oldDataValueHash = implode( '___', $values );
-
- $values = array();
- foreach ( $newDataValue as $v ) {
- $values[] = $v->getHash();
- }
-
- sort( $values );
- $newDataValueHash = implode( '___', $values );
-
- return ( $oldDataValueHash == $newDataValueHash );
- }
}
diff --git a/includes/ParserDataStorage.php b/includes/ParserDataStorage.php
new file mode 100644
index 0000000..7077030
--- /dev/null
+++ b/includes/ParserDataStorage.php
@@ -0,0 +1,375 @@
+<?php
+
+namespace SMW;
+
+use WikiPage;
+use Job;
+use Title;
+
+use SMWStore;
+use SMWDIWikiPage;
+use SMWDataValueFactory;
+use SMWDIProperty;
+use SMWUpdateJob;
+
+/**
+ * Update the store with the processed semantic data container provided by
+ * the ParserData object
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ * @ingroup ParserHooks
+ *
+ * @author Markus Krötzsch
+ * @author mwjames
+ */
+
+/**
+ * Class is responsible to update the store with the processed semantic data
+ * container provided by the ParserData object
+ *
+ * @ingroup SMW
+ * @ingroup ParserHooks
+ */
+class ParserDataStorage {
+
+ /**
+ * Represents IParserData object
+ */
+ protected $parserData;
+
+ /**
+ * Represents SMWSemanticData object
+ */
+ protected $semanticData;
+
+ /**
+ * Represents SMWStore object
+ */
+ protected $store;
+
+ /**
+ * Represents invoked GLOBALS
+ */
+ protected $settings;
+
+ /**
+ * Represents invoked $smwgEnableUpdateJobs
+ */
+ protected $updateJobs = true;
+
+ /**
+ * Constructor
+ *
+ * @since 1.9
+ *
+ * @param IParserData $parserData
+ * @param array $settings
+ */
+ public function __construct( IParserData $parserData, array $settings =
array() ) {
+ $this->parserData = $parserData;
+ $this->store = smwfGetStore();
+ $this->settings = $settings;
+ $this->updateJobs = $GLOBALS['smwgEnableUpdateJobs'];
+ }
+
+ /**
+ * Explicitly disable update jobs (e.g when running store update
+ * in the job queue)
+ *
+ * @since 1.9
+ */
+ public function disableUpdateJobs() {
+ $this->updateJobs = false;
+ }
+
+ /**
+ * Updates the store with semantic data attached to a ParserOutput
object
+ *
+ * This function takes care of storing the collected semantic data and
takes
+ * care of clearing out any outdated entries for the processed page. It
assume that
+ * parsing has happened and that all relevant data is contained in the
provided parser
+ * output.
+ *
+ * Optionally, this function also takes care of triggering indirect
updates that might be
+ * needed for overall database consistency. If the saved page describes
a property or data type,
+ * the method checks whether the property type, the data type, the
allowed values, or the
+ * conversion factors have changed. If so, it triggers SMWUpdateJobs
for the relevant articles,
+ * which then asynchronously update the semantic data in the database.
+ *
+ * @todo FIXME: Some job generations here might create too many jobs at
once
+ * on a large wiki. Use incremental jobs instead.
+ *
+ * To disable jobs either set $smwgEnableUpdateJobs = false or invoke
+ * SMW\ParserData::disableUpdateJobs()
+ *
+ * Called from SMWUpdateJob::run, SMWHooks::onLinksUpdateConstructed,
+ * SMWHooks::onParserAfterTidy
+ *
+ * @since 1.9
+ *
+ * @return boolean
+ */
+ public function updateStore() {
+ wfProfileIn( __METHOD__ );
+
+ $subject = $this->parserData->getSubject();
+ $namespace = $subject->getTitle()->getNamespace();
+ $wikiPage = WikiPage::factory( $subject->getTitle() );
+ $revision = $wikiPage->getRevision();
+ $jobs = array();
+
+ // Make sure to have a valid revision (null means delete etc.)
+ // Check if semantic data should be processed and displayed for
a page in
+ // the given namespace
+ $processSemantics = $revision !== null ?
smwfIsSemanticsProcessed( $namespace ) : false;
+
+ if ( $processSemantics ) {
+ $user = \User::newFromId( $revision->getUser() );
+ $this->parserData->addSpecialProperties( $wikiPage,
$revision, $user );
+ } else {
+ // data found, but do all operations as if it was empty
+ $this->parserData->clearData();
+ }
+
+ // Careful: storage access must happen *before* the storage
update;
+ // even finding uses of a property fails after its type was
changed.
+ if ( $this->updateJobs && ( $namespace === SMW_NS_PROPERTY ) ) {
+ $this->getDiffPropertyTypes( $jobs );
+ } else if ( $this->updateJobs && ( $namespace === SMW_NS_TYPE )
) {
+ $this->getDiffConversionFactors( $jobs );
+ }
+
+ // Actually store semantic data, or at least clear it if needed
+ if ( $processSemantics ) {
+ $this->store->updateData( $this->parserData->getData()
);
+ } else {
+ $this->store->clearData( $subject );
+ }
+
+ // Job::batchInsert was deprecated in MW 1.21
+ // @see JobQueueGroup::singleton()->push( $job );
+ if ( $jobs !== array() ) {
+ Job::batchInsert( $jobs );
+ }
+
+ wfProfileOut( __METHOD__ );
+
+ return true;
+ }
+
+ /**
+ * Helper method to handle diff/change in type property pages
+ *
+ * @note If it is a property, then we need to check if the type or the
+ * allowed values have been changed.
+ *
+ * @since 1.9
+ *
+ * @param array &$jobs
+ */
+ protected function getDiffPropertyTypes( array &$jobs ) {
+ wfProfileIn( __METHOD__ );
+
+ $updatejobflag = false;
+ $subject = $this->parserData->getSubject();
+ $ptype = new SMWDIProperty( SMWDIProperty::TYPE_HAS_TYPE );
+
+ // Get values from the store
+ $oldtype = $this->store->getPropertyValues(
+ $subject,
+ $ptype
+ );
+
+ // Get values currently hold by the semantic container
+ $newtype = $this->parserData->getData()->getPropertyValues(
$ptype );
+
+ // Compare old and new type
+ if ( !$this->equalDatavalues( $oldtype, $newtype ) ) {
+ $updatejobflag = true;
+ } else {
+ // Compare values (in case of _PVAL (allowed values)
for a
+ // property change must be processed again)
+ foreach ( $GLOBALS['smwgDeclarationProperties'] as
$prop ) {
+
+ $dataItem = new SMWDIProperty( $prop );
+ $oldValues = $this->store->getPropertyValues(
+ $subject,
+ $dataItem
+ );
+ $newValues =
$this->parserData->getData()->getPropertyValues( $dataItem );
+ $updatejobflag = !$this->equalDatavalues(
$oldValues, $newValues );
+ }
+ }
+
+ // Job generation
+ if ( $updatejobflag ) {
+ $prop = new SMWDIProperty( $subject->getDBkey() );
+
+ // Array of all subjects that have some value for the
given property
+ $subjects = $this->store->getAllPropertySubjects( $prop
);
+
+ // Add jobs
+ $this->addJobs( $subjects, $jobs );
+
+ // Hook
+ wfRunHooks( 'smwUpdatePropertySubjects', array( &$jobs
) );
+
+ // Fetch all those that have an error property attached
and
+ // re-run it through the job-queue
+ $subjects = $this->store->getPropertySubjects(
+ new SMWDIProperty( SMWDIProperty::TYPE_ERROR ),
+ $subject
+ );
+
+ // Add jobs
+ $this->addJobs( $subjects, $jobs );
+ }
+
+ wfProfileOut( __METHOD__ );
+ }
+
+ /**
+ * Helper method to handle diff/change of conversion related properties
+ *
+ * @note if it is a type we need to check if the conversion factors
+ * have been changed
+ *
+ * @since 1.9
+ *
+ * @param SMWDIWikiPage $subject
+ * @param array &$jo
+ */
+ protected function getDiffConversionFactors( array &$jobs ) {
+ wfProfileIn( __METHOD__ );
+
+ $updatejobflag = false;
+ $subject = $this->parserData->getSubject();
+ $pconv = new SMWDIProperty( SMWDIProperty::TYPE_CONVERSION );
+ $ptype = new SMWDIProperty( SMWDIProperty::TYPE_HAS_TYPE );
+
+ $oldfactors = $this->store->getPropertyValues(
+ $subject,
+ $pconv
+ );
+ $newfactors = $this->parserData->getData()->getPropertyValues(
$pconv );
+
+ // Compare
+ $updatejobflag = !$this->equalDatavalues( $oldfactors,
$newfactors );
+
+ // Job generation
+ if ( $updatejobflag ) {
+
+ /// FIXME: this will kill large wikis! Use incremental
updates!
+ $dataValue = SMWDataValueFactory::newTypeIdValue(
'__typ', $subject->getDBkey() );
+ $propertyPages = $this->store->getPropertySubjects(
$ptype, $dataValue );
+
+ foreach ( $propertyPages as $propertyPage ) {
+ // Add jobs
+ $this->addJobs( array( $propertyPage ), $jobs );
+
+ $prop = new SMWDIProperty(
$propertyPage->getDBkey() );
+ $subjects =
$this->store->getAllPropertySubjects( $prop );
+
+ // Add jobs
+ $this->addJobs( $subjects, $jobs );
+
+ $subjects = $this->store->getPropertySubjects(
+ new SMWDIProperty(
SMWDIProperty::TYPE_ERROR ),
+ $prop->getWikiPageValue()
+ );
+
+ // Add jobs
+ $this->addJobs( $subjects, $jobs );
+ }
+ }
+
+ wfProfileOut( __METHOD__ );
+ }
+
+ /**
+ * Helper method to iterate over an array of SMWDIWikiPage and return
and
+ * array of SMWUpdateJob jobs
+ *
+ * Check whether a job with the same getPrefixedDBkey string (prefixed
title,
+ * with underscores and any interwiki and namespace prefixes) is already
+ * registered and if so don't insert a new job. This is particular
important
+ * for pages that include a large amount of subobjects where the same
Title
+ * and ParserOutput object is used (subobjects are included using the
same
+ * WikiPage which means the resulting ParserOutput object is the same)
+ *
+ * @since 1.9
+ *
+ * @param SMWDIWikiPage[] $subjects
+ * @param array &$jobs
+ */
+ protected function addJobs( array $subjects, &$jobs ) {
+
+ foreach ( $subjects as $subject ) {
+ $duplicate = false;
+ $subjectTitle = $subject->getTitle();
+
+ if ( $subjectTitle instanceof Title ) {
+
+ // Avoid duplicate jobs for the same title
object
+ foreach ( $jobs as $job ) {
+ if (
$job->getTitle()->getPrefixedDBkey() === $subjectTitle->getPrefixedDBkey() ){
+ $duplicate = true;
+ break;
+ }
+ }
+
+ if ( !$duplicate ) {
+ $jobs[] = new SMWUpdateJob(
$subjectTitle );
+ }
+ }
+ }
+ }
+
+ /**
+ * Helper function that compares two arrays of data values to check
whether
+ * they contain the same content. Returns true if the two arrays
contain the
+ * same data values (irrespective of their order), false otherwise.
+ *
+ * @since 1.9
+ */
+ protected function equalDatavalues( $oldDataValue, $newDataValue ) {
+ // The hashes of all values of both arrays are taken, then
sorted
+ // and finally concatenated, thus creating one long hash out of
each
+ // of the data value arrays. These are compared.
+ $values = array();
+ foreach ( $oldDataValue as $v ) {
+ $values[] = $v->getHash();
+ }
+
+ sort( $values );
+ $oldDataValueHash = implode( '___', $values );
+
+ $values = array();
+ foreach ( $newDataValue as $v ) {
+ $values[] = $v->getHash();
+ }
+
+ sort( $values );
+ $newDataValueHash = implode( '___', $values );
+
+ return ( $oldDataValueHash == $newDataValueHash );
+ }
+}
diff --git a/includes/Setup.php b/includes/Setup.php
index 3e71a40..70aeedc 100644
--- a/includes/Setup.php
+++ b/includes/Setup.php
@@ -132,6 +132,7 @@
$wgAutoloadClasses['SMWParseData'] = $incDir .
'SMW_ParseData.php';
$wgAutoloadClasses['SMW\IParserData'] = $incDir .
'ParserData.php';
$wgAutoloadClasses['SMW\ParserData'] = $incDir .
'ParserData.php';
+ $wgAutoloadClasses['SMW\ParserDataStorage'] = $incDir .
'ParserDataStorage.php';
// Article pages
$apDir = $smwgIP . 'includes/articlepages/';
diff --git a/includes/jobs/SMW_UpdateJob.php b/includes/jobs/SMW_UpdateJob.php
index 42693b4..4ac2e22 100644
--- a/includes/jobs/SMW_UpdateJob.php
+++ b/includes/jobs/SMW_UpdateJob.php
@@ -74,9 +74,12 @@
// @since 1.9
// SMWParseData::storeData( $output, $this->title, false );
- $parserData = new SMW\ParserData( $this->title, $output );
- $parserData->disableUpdateJobs();
- $parserData->updateStore();
+ $parserDataStorage = new SMW\ParserDataStorage( new
SMW\ParserData(
+ $this->title,
+ $output )
+ );
+ $parserDataStorage->disableUpdateJobs();
+ $parserDataStorage->updateStore();
wfProfileOut( __METHOD__ . '-update' );
wfProfileOut( 'SMWUpdateJob::run (SMW)' );
diff --git a/tests/phpunit/includes/ParserDataStorageTest.php
b/tests/phpunit/includes/ParserDataStorageTest.php
new file mode 100644
index 0000000..5448ab7
--- /dev/null
+++ b/tests/phpunit/includes/ParserDataStorageTest.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\ParserDataStorage;
+use SMW\ParserData;
+
+use ParserOutput;
+use Title;
+
+/**
+ * Tests for the SMW\ParserDataStorage class
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.9
+ *
+ * @ingroup SMW
+ * @ingroup Test
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+class ParserDataStorageTest extends \MediaWikiTestCase {
+
+ /**
+ * Helper method to get title object
+ *
+ * @return Title
+ */
+ private function getTitle( $title ){
+ return Title::newFromText( $title );
+ }
+
+ /**
+ * Helper method to get ParserOutput object
+ *
+ * @return ParserOutput
+ */
+ private function getParserOutput(){
+ return new ParserOutput();
+ }
+
+ /**
+ * Helper method
+ *
+ * @return SMW\ParserData
+ */
+ private function getInstance( $titleName, ParserOutput $parserOutput ) {
+ $parserData = new ParserData( $this->getTitle( $titleName ),
$parserOutput );
+ return new ParserDataStorage( $parserData );
+ }
+
+ /**
+ * Test instance
+ *
+ */
+ public function testConstructor() {
+ $instance = $this->getInstance( 'Foo', $this->getParserOutput()
);
+ $this->assertInstanceOf( 'SMW\ParserDataStorage', $instance );
+ }
+
+}
diff --git a/tests/phpunit/includes/ParserDataTest.php
b/tests/phpunit/includes/ParserDataTest.php
index 3c2df8a..689c506 100644
--- a/tests/phpunit/includes/ParserDataTest.php
+++ b/tests/phpunit/includes/ParserDataTest.php
@@ -105,17 +105,17 @@
$instance->addPropertyValueString( $propertyName, $value );
// Check the returned instance
- $this->assertInstanceOf( 'SMWSemanticData',
$instance->getSemanticData() );
+ $this->assertInstanceOf( 'SMWSemanticData',
$instance->getData() );
$this->assertCount( $error, $instance->getErrors() );
// Check added properties
- foreach ( $instance->getSemanticData()->getProperties() as $key
=> $diproperty ){
+ foreach ( $instance->getData()->getProperties() as $key =>
$diproperty ){
$this->assertInstanceOf( 'SMWDIProperty', $diproperty );
$this->assertContains( $propertyName,
$diproperty->getLabel() );
// Check added property values
- foreach (
$instance->getSemanticData()->getPropertyValues( $diproperty ) as $dataItem ){
+ foreach ( $instance->getData()->getPropertyValues(
$diproperty ) as $dataItem ){
$dataValue =
SMWDataValueFactory::newDataItemValue( $dataItem, $diproperty );
if ( $dataValue->getDataItem()->getDIType() ===
SMWDataItem::TYPE_WIKIPAGE ){
$this->assertContains( $value,
$dataValue->getWikiValue() );
diff --git a/tests/phpunit/includes/parserhooks/AskParserFunctionTest.php
b/tests/phpunit/includes/parserhooks/AskParserFunctionTest.php
index ddd3fa4..ea38f6e 100644
--- a/tests/phpunit/includes/parserhooks/AskParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/AskParserFunctionTest.php
@@ -215,10 +215,10 @@
$parserData = new ParserData( $this->getTitle( $title ),
$parserOutput );
// Check the returned instance
- $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getSemanticData() );
+ $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getData() );
// Confirm subSemanticData objects for the SemanticData instance
- foreach ( $parserData->getSemanticData()->getSubSemanticData()
as $containerSemanticData ){
+ foreach ( $parserData->getData()->getSubSemanticData() as
$containerSemanticData ){
$this->assertInstanceOf( 'SMWContainerSemanticData',
$containerSemanticData );
$this->assertCount( $expected['queryCount'],
$containerSemanticData->getProperties() );
diff --git a/tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php
b/tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php
index b1dc488..670849e 100644
--- a/tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php
@@ -192,16 +192,16 @@
$parserData = new ParserData( $this->getTitle( $title ),
$parserOutput );
// Check the returned instance
- $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getSemanticData() );
- $this->assertCount( $expected['propertyCount'],
$parserData->getSemanticData()->getProperties() );
+ $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getData() );
+ $this->assertCount( $expected['propertyCount'],
$parserData->getData()->getProperties() );
// Confirm concept property
- foreach ( $parserData->getSemanticData()->getProperties() as
$key => $diproperty ){
+ foreach ( $parserData->getData()->getProperties() as $key =>
$diproperty ){
$this->assertInstanceOf( 'SMWDIProperty', $diproperty );
$this->assertEquals( '_CONC' , $diproperty->getKey() );
// Confirm concept property values
- foreach (
$parserData->getSemanticData()->getPropertyValues( $diproperty ) as $dataItem ){
+ foreach ( $parserData->getData()->getPropertyValues(
$diproperty ) as $dataItem ){
$this->assertEquals( $expected['conceptQuery'],
$dataItem->getConceptQuery() );
$this->assertEquals( $expected['conceptDocu'],
$dataItem->getDocumentation() );
$this->assertEquals( $expected['conceptSize'],
$dataItem->getSize() );
diff --git a/tests/phpunit/includes/parserhooks/SetParserFunctionTest.php
b/tests/phpunit/includes/parserhooks/SetParserFunctionTest.php
index a286fbd..9a73b88 100644
--- a/tests/phpunit/includes/parserhooks/SetParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/SetParserFunctionTest.php
@@ -202,16 +202,16 @@
$parserData = new ParserData( $this->getTitle( $title ),
$parserOutput );
// Check the returned instance
- $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getSemanticData() );
- $this->assertCount( $expected['propertyCount'],
$parserData->getSemanticData()->getProperties() );
+ $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getData() );
+ $this->assertCount( $expected['propertyCount'],
$parserData->getData()->getProperties() );
// Check added properties
- foreach ( $parserData->getSemanticData()->getProperties() as
$key => $diproperty ){
+ foreach ( $parserData->getData()->getProperties() as $key =>
$diproperty ){
$this->assertInstanceOf( 'SMWDIProperty', $diproperty );
$this->assertContains( $diproperty->getLabel(),
$expected['propertyLabel'] );
// Check added property values
- foreach (
$parserData->getSemanticData()->getPropertyValues( $diproperty ) as $dataItem ){
+ foreach ( $parserData->getData()->getPropertyValues(
$diproperty ) as $dataItem ){
$dataValue =
SMWDataValueFactory::newDataItemValue( $dataItem, $diproperty );
if ( $dataValue->getDataItem()->getDIType() ===
SMWDataItem::TYPE_WIKIPAGE ){
$this->assertContains(
$dataValue->getWikiValue(), $expected['value'] );
diff --git a/tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php
b/tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php
index d2daab8..188bed7 100644
--- a/tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php
@@ -181,10 +181,10 @@
$parserData = new ParserData( $this->getTitle( $title ),
$parserOutput );
// Check the returned instance
- $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getSemanticData() );
+ $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getData() );
// Confirm subSemanticData objects for the SemanticData instance
- foreach ( $parserData->getSemanticData()->getSubSemanticData()
as $containerSemanticData ){
+ foreach ( $parserData->getData()->getSubSemanticData() as
$containerSemanticData ){
$this->assertInstanceOf( 'SMWContainerSemanticData',
$containerSemanticData );
$this->assertCount( $expected['queryCount'],
$containerSemanticData->getProperties() );
diff --git a/tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php
b/tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php
index 228fb9c..8cff23a 100644
--- a/tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php
@@ -267,10 +267,10 @@
$parserData = new ParserData( $this->getTitle( $title ),
$parserOutput );
// Check the returned instance
- $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getSemanticData() );
+ $this->assertInstanceOf( 'SMWSemanticData',
$parserData->getData() );
// Confirm subSemanticData objects for the SemanticData instance
- foreach ( $parserData->getSemanticData()->getSubSemanticData()
as $containerSemanticData ){
+ foreach ( $parserData->getData()->getSubSemanticData() as
$containerSemanticData ){
$this->assertInstanceOf( 'SMWContainerSemanticData',
$containerSemanticData );
$this->assertCount( $expected['propertyCount'],
$containerSemanticData->getProperties() );
--
To view, visit https://gerrit.wikimedia.org/r/57701
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iaa1a3d9d08918f33a98792b3ea2e9d7c5747dba5
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/SemanticMediaWiki
Gerrit-Branch: master
Gerrit-Owner: Mwjames <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits