jenkins-bot has submitted this change and it was merged.

Change subject: \SMW\ChangeObserver
......................................................................


\SMW\ChangeObserver

Code coverage: 100%
CRAP: 10

The ChangeObserver acts on an invoked object notification and enforces loose
coupling between the sender of a change notification through this agent.

## Narrative
Before using the ChangeObserver, PropertyDisparityDetector would have been
coupled to the UpdateDispatcher instead now the ChangeAgent acts on behalf
of the PropertyDisparityDetector to invoke the necessary object.

This will allow [1] to use the same ChangeObserver

[1] https://gerrit.wikimedia.org/r/#/c/75825/

## Testing
* MockChangeObserver is being used to verify the Observer/Subject behaviour

Change-Id: Ifd8604d8ed551a62e3aa5c160e536c5cb1d0e718
---
M SemanticMediaWiki.settings.php
M includes/ParserData.php
M includes/PropertyDisparityDetector.php
M includes/Settings.php
M includes/Setup.php
M includes/jobs/PropertySubjectsUpdateDispatcherJob.php
A includes/utilities/ChangeObserver.php
A includes/utilities/MediaWikiInterfaceProvider.php
A tests/phpunit/MockChangeObserver.php
M tests/phpunit/includes/PropertyDisparityDetectorTest.php
A tests/phpunit/includes/utilities/ChangeObserverTest.php
11 files changed, 543 insertions(+), 41 deletions(-)

Approvals:
  Mwjames: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/SemanticMediaWiki.settings.php b/SemanticMediaWiki.settings.php
index 50c9cfe..88bb8ae 100644
--- a/SemanticMediaWiki.settings.php
+++ b/SemanticMediaWiki.settings.php
@@ -644,3 +644,15 @@
 ##
 $smwgPropertyZeroCountDisplay = true;
 ##
+
+###
+# Support of deferred update of properties using the JobQueue/CacheStore
+# to lighten performance degradation when changing properties
+#
+# In order to enable deferred updates, it requires the CacheStore
+# (e.g smwgCacheType) to be enabled and PropertyPageIdMapper to be present.
+#
+# @since 1.9
+##
+$smwgDeferredPropertyUpdate = false;
+##
diff --git a/includes/ParserData.php b/includes/ParserData.php
index 0acc9c8..5ea128c 100644
--- a/includes/ParserData.php
+++ b/includes/ParserData.php
@@ -387,8 +387,6 @@
                        return true;
                }
 
-               $dispatcherJob = null;
-
                $namespace = $this->title->getNamespace();
                $wikiPage  = WikiPage::factory( $this->title );
                $revision  = $wikiPage->getRevision();
@@ -422,7 +420,8 @@
                // even finding uses of a property fails after its type was 
changed.
                if ( $this->updateJobs ) {
                        $disparityDetector = new PropertyDisparityDetector( 
$store, $this->semanticData, Settings::newFromGlobals() );
-                       $dispatcherJob = 
$disparityDetector->detectDisparity()->getDispatcherJob();
+                       $disparityDetector->attach( new ChangeObserver() );
+                       $disparityDetector->detectDisparity();
                }
 
                // Actually store semantic data, or at least clear it if needed
@@ -432,14 +431,7 @@
                        $store->clearData( $this->semanticData->getSubject() );
                }
 
-               // Job::batchInsert was deprecated in MW 1.21
-               // @see JobQueueGroup::singleton()->push( $job );
-               if ( $dispatcherJob !== null ) {
-                       Job::batchInsert( $dispatcherJob );
-               }
-
                Profiler::Out( __METHOD__, true );
-
                return true;
        }
 
diff --git a/includes/PropertyDisparityDetector.php 
b/includes/PropertyDisparityDetector.php
index bed5dc9..e14bf06 100644
--- a/includes/PropertyDisparityDetector.php
+++ b/includes/PropertyDisparityDetector.php
@@ -2,9 +2,6 @@
 
 namespace SMW;
 
-use Title;
-use Job;
-
 /**
  * Class that detects a disparity between the property object and its store 
data
  *
@@ -37,7 +34,7 @@
  *
  * @ingroup SMW
  */
-class PropertyDisparityDetector {
+class PropertyDisparityDetector extends Subject implements TitleProvider {
 
        /** @var Store */
        protected $store;
@@ -48,8 +45,8 @@
        /** @var Settings */
        protected $settings;
 
-       /** @var Job */
-       protected $dispatcherJob = null;
+       /** @var boolean */
+       protected $hasDisparity = false;
 
        /**
         * @since 1.9
@@ -65,14 +62,14 @@
        }
 
        /**
-        * Returns update jobs as a result of the data comparison
+        * Returns a Title object
         *
         * @since 1.9
         *
-        * @return PropertyDisparityDispatcherJob|null
+        * @return Title
         */
-       public function getDispatcherJob() {
-               return $this->dispatcherJob;
+       public function getTitle() {
+               return $this->semanticData->getSubject()->getTitle();
        }
 
        /**
@@ -83,7 +80,7 @@
         * @return boolean
         */
        public function hasDisparity() {
-               return $this->getDispatcherJob() !== null;
+               return $this->hasDisparity;
        }
 
        /**
@@ -179,11 +176,9 @@
         * @param boolean $addJob
         */
        protected function addDispatchJob( $addJob = true ) {
-               if ( $addJob && $this->dispatcherJob === null ) {
-                       $this->dispatcherJob[] = new 
PropertySubjectsUpdateDispatcherJob(
-                               $this->semanticData->getSubject()->getTitle(),
-                               array( 'store' => get_class( $this->store ) )
-                       );
+               if ( $addJob && !$this->hasDisparity ) {
+                       $this->setState( 'runUpdateDispatcher' );
+                       $this->hasDisparity = true;
                }
        }
 
diff --git a/includes/Settings.php b/includes/Settings.php
index db5c8c6..1621efc 100644
--- a/includes/Settings.php
+++ b/includes/Settings.php
@@ -136,6 +136,7 @@
                        'smwgFixedProperties' => 
$GLOBALS['smwgFixedProperties'],
                        'smwgPropertyLowUsageThreshold' => 
$GLOBALS['smwgPropertyLowUsageThreshold'],
                        'smwgPropertyZeroCountDisplay' => 
$GLOBALS['smwgPropertyZeroCountDisplay'],
+                       'smwgDeferredPropertyUpdate' => 
$GLOBALS['smwgDeferredPropertyUpdate'],
                );
 
                if ( self::$instance === null ) {
diff --git a/includes/Setup.php b/includes/Setup.php
index e8c6123..7fe0d7b 100644
--- a/includes/Setup.php
+++ b/includes/Setup.php
@@ -166,6 +166,8 @@
        $wgAutoloadClasses['SMW\ObservableMessageReporter'] = $incDir . 
'/utilities/MessageReporter.php';
        $wgAutoloadClasses['SMW\RedirectBuilder']           = $incDir . 
'/utilities/RedirectBuilder.php';
        $wgAutoloadClasses['SMW\ParserOutputGenerator']     = $incDir . 
'/utilities/ParserOutputGenerator.php';
+       $wgAutoloadClasses['SMW\ChangeObserver']            = $incDir . 
'/utilities/ChangeObserver.php';
+       $wgAutoloadClasses['SMW\TitleProvider']             = $incDir . 
'/utilities/MediaWikiInterfaceProvider.php';
 
        $wgAutoloadClasses['SMW\Publisher']                 = $incDir . 
'/utilities/ObserverInterfaceProvider.php';
        $wgAutoloadClasses['SMW\Subject']                   = $incDir . 
'/utilities/ObserverInterfaceProvider.php';
@@ -424,6 +426,7 @@
        $wgAutoloadClasses['SMW\Test\MockObjectBuilder']             = 
$testsDir . 'MockObjectBuilder.php';
        $wgAutoloadClasses['SMW\Test\SpecialPageTestCase']           = 
$testsDir . 'SpecialPageTestCase.php';
        $wgAutoloadClasses['SMW\Test\CompatibilityTestCase']         = 
$testsDir . 'CompatibilityTestCase.php';
+       $wgAutoloadClasses['SMW\Test\MockChangeObserver']            = 
$testsDir . 'MockChangeObserver.php';
 
        // Jobs
        $wgAutoloadClasses['SMW\JobBase']   = $smwgIP . 
'includes/jobs/JobBase.php';
diff --git a/includes/jobs/PropertySubjectsUpdateDispatcherJob.php 
b/includes/jobs/PropertySubjectsUpdateDispatcherJob.php
index 284495e..ca969da 100644
--- a/includes/jobs/PropertySubjectsUpdateDispatcherJob.php
+++ b/includes/jobs/PropertySubjectsUpdateDispatcherJob.php
@@ -174,4 +174,16 @@
                        }
                }
        }
+
+       /**
+        * @see Job::insert
+        *
+        * @since 1.9
+        * @codeCoverageIgnore
+        */
+       public function insert() {
+               if ( $this->getSettings()->get( 'smwgEnableUpdateJobs' ) ) {
+                       parent::insert();
+               }
+       }
 }
diff --git a/includes/utilities/ChangeObserver.php 
b/includes/utilities/ChangeObserver.php
new file mode 100644
index 0000000..25c49fc
--- /dev/null
+++ b/includes/utilities/ChangeObserver.php
@@ -0,0 +1,160 @@
+<?php
+
+namespace SMW;
+
+/**
+ * General purpose change agent to enforce loose coupling by having
+ * a Publisher (subject) sent a change notification to this observer
+ *
+ * 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
+ *
+ * @license GNU GPL v2+
+ * @since   1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * General purpose change agent to enforce loose coupling by having
+ * a Publisher (subject) sent a change notification to this observer
+ *
+ * @note When testing rountrips, use MockChangeObserver instead
+ *
+ * @ingroup Observer
+ */
+class ChangeObserver extends Observer {
+
+       /** @var Settings */
+       protected $settings = null;
+
+       /** @var Store */
+       protected $store = null;
+
+       /** @var CacheHandler */
+       protected $cache = null;
+
+       /**
+        * Sets Store object
+        *
+        * @since 1.9
+        *
+        * @param Store $store
+        */
+       public function setStore( Store $store ) {
+               $this->store = $store;
+       }
+
+       /**
+        * Returns Store object
+        *
+        * @since 1.9
+        *
+        * @return Store
+        */
+       public function getStore() {
+
+               if ( $this->store === null ) {
+                       $this->store = StoreFactory::getStore();
+               }
+
+               return $this->store;
+       }
+
+       /**
+        * Sets Settings object
+        *
+        * @since 1.9
+        *
+        * @param Settings $settings
+        *
+        * @return ChangeAgent
+        */
+       public function setSettings( Settings $settings ) {
+               $this->settings = $settings;
+               return $this;
+       }
+
+       /**
+        * Returns Settings object
+        *
+        * @since 1.9
+        *
+        * @return Settings
+        */
+       public function getSettings() {
+
+               if ( $this->settings === null ) {
+                       $this->settings = Settings::newFromGlobals();
+               }
+
+               return $this->settings;
+       }
+
+       /**
+        * Returns CacheHandler object
+        *
+        * @since 1.9
+        *
+        * @return CacheHandler
+        */
+       public function getCache() {
+
+               if ( $this->cache === null ) {
+                       $this->cache = CacheHandler::newFromId( 
$this->getSettings()->get( 'smwgCacheType' ) );
+               }
+
+               return $this->cache;
+       }
+
+       /**
+        * UpdateJob dispatching
+        *
+        * loading of data
+        *
+        * Generally by the time the job is execute the store has been updated 
and
+        * data that belong to a property potentially are no longer are 
associate
+        * with a subject.
+        *
+        * [1] Immediate dispatching influences the performance during page 
saving
+        * since data that belongs to the property are loaded directly from the 
DB
+        * which has direct impact about the response time of the page in 
question.
+        *
+        * [2] Deferred dispatching uses a different approach to recognize 
necessary
+        * objects involved and deferres property/pageIds mapping to the 
JobQueue.
+        * This makes it unnecessary to load data from the DB therefore decrease
+        * performance degration during page update.
+        *
+        * @since 1.9
+        *
+        * @param TitleProvider $subject
+        */
+       public function runUpdateDispatcher( TitleProvider $subject ) {
+
+               $dispatcher = new PropertySubjectsUpdateDispatcherJob( 
$subject->getTitle() );
+               $dispatcher->setSettings( $this->getSettings() );
+
+               if ( $this->getSettings()->get( 'smwgDeferredPropertyUpdate' ) 
) {
+                       $dispatcher->insert(); // JobQueue is handling 
dispatching
+               } else {
+                       $dispatcher->run();
+               }
+
+               return true;
+       }
+
+}
diff --git a/includes/utilities/MediaWikiInterfaceProvider.php 
b/includes/utilities/MediaWikiInterfaceProvider.php
new file mode 100644
index 0000000..26a931d
--- /dev/null
+++ b/includes/utilities/MediaWikiInterfaceProvider.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace SMW;
+
+/**
+ * Specifies interfaces to access MediaWiki specific objects
+ *
+ * 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
+ *
+ * @license GNU GPL v2+
+ * @since   1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * Interface describing access to a Title object
+ *
+ * @ingroup Provider
+ */
+interface TitleProvider {
+
+       /**
+        * Returns a Title object
+        *
+        * @since  1.9
+        *
+        * @return Title
+        */
+       public function getTitle();
+
+}
\ No newline at end of file
diff --git a/tests/phpunit/MockChangeObserver.php 
b/tests/phpunit/MockChangeObserver.php
new file mode 100644
index 0000000..5d8d379
--- /dev/null
+++ b/tests/phpunit/MockChangeObserver.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace SMW\Test;
+
+use \SMW\ChangeObserver;
+use \SMW\TitleProvider;
+
+/**
+ * MockChangeAgent should only be used during testing to establish that
+ * a correct behaviour between Observer and Subject has been established.
+ *
+ * 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
+ *
+ * @license GNU GPL v2+
+ * @since   1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * MockChangeObserver should only be used during testing to establish that
+ * a correct behaviour between Observer and Subject has been established.
+ *
+ * Use the setNotifier/getNotifier to verify the function that was expected
+ * during processing was invoked because of a notification sent by the
+ * Publisher(Subject).
+ *
+ * Testing the publisher does not involve testing the execution of
+ * the expected processor and is part of a different test which should be
+ * treated as independent unit test.
+ *
+ * @par Example:
+ * @code
+ *  $observer = new MockChangeObserver();
+ *  $instance->attach( $observer );
+ *
+ *  $this->assertEquals( 'runFoo', $observer->getNotifier() )
+ * @end
+ *
+ * @ingroup Observer
+ * @codeCoverageIgnore
+ */
+class MockChangeObserver extends ChangeObserver {
+
+       /** @var string */
+       protected $notifier = null;
+
+       /**
+        * Sets a notifier
+        *
+        * Verfifies that the expected notifier is actually available in the
+        * parent class, meaning that any unrecognized renaming of any method
+        * in the mock or parent class will be flagged by returning null
+        * instead of the expected notifier name.
+        *
+        * @since 1.9
+        */
+       public function setNotifier( $notifier ) {
+               $this->notifier = method_exists( get_parent_class( $this ), 
$notifier ) ? $notifier : null;
+       }
+
+       /**
+        * Returns a registered notifier
+        *
+        * @since 1.9
+        */
+       public function getNotifier() {
+               return $this->notifier;
+       }
+
+       /**
+        * @see ChangeObserver::runUpdateDispatcher
+        *
+        * @since 1.9
+        */
+       public function runUpdateDispatcher( TitleProvider $subject ) {
+               $this->setNotifier( __FUNCTION__ );
+       }
+
+}
diff --git a/tests/phpunit/includes/PropertyDisparityDetectorTest.php 
b/tests/phpunit/includes/PropertyDisparityDetectorTest.php
index 5bf0b4e..979393b 100644
--- a/tests/phpunit/includes/PropertyDisparityDetectorTest.php
+++ b/tests/phpunit/includes/PropertyDisparityDetectorTest.php
@@ -86,7 +86,6 @@
                $this->assertInstanceOf( $this->getClass(), 
$this->getInstance() );
        }
 
-
        /**
         * @test PropertyDisparityDetector::detectDisparity
         * @dataProvider dataItemDataProvider
@@ -95,7 +94,7 @@
         */
        public function testFindDisparity( $storeValues, $dataValues, 
$settings, $expected ) {
 
-               $title = $this->getTitle( SMW_NS_PROPERTY );
+               $subject = $this->newSubject( $this->newTitle( SMW_NS_PROPERTY 
) );
                $this->storeValues = $storeValues;
 
                $store = array(
@@ -103,16 +102,19 @@
                );
 
                $data  = array(
-                       'getSubject'        => $this->newSubject( $title ),
+                       'getSubject'        => $subject,
                        'getPropertyValues' => $dataValues
                );
 
                $instance = $this->getInstance( $store, $data, $settings );
+               $observer = new MockChangeObserver( $instance );
 
                $this->assertInstanceOf( $this->getClass(), 
$instance->detectDisparity() );
-               $this->assertEquals( $expected['disp'], 
$instance->hasDisparity() );
-               $this->assertInternalType( $expected['type'], 
$instance->getDispatcherJob() );
-               $this->assertEquals( $expected['count'], count( 
$instance->getDispatcherJob() ) );
+               $this->assertEquals( $subject->getTitle(), 
$instance->getTitle() );
+               $this->assertEquals( $expected['change'], 
$instance->hasDisparity() );
+
+               // Verify that the Observer was notified
+               $this->assertEquals( $expected['notifier'], 
$observer->getNotifier() );
 
        }
 
@@ -123,10 +125,14 @@
         */
        public function dataItemDataProvider() {
 
+               $notifier = 'runUpdateDispatcher';
+
+               // Single
                $subject  = array(
                        $this->newSubject()
                );
 
+               // Multiple
                $subjects = array(
                        $this->newSubject(),
                        $this->newSubject(),
@@ -135,15 +141,15 @@
 
                return array(
                        //  $storeValues, $dataValues, $settings,               
$expected
-                       array( $subjects, array(),   array( '_PVAL', '_LIST' ), 
array( 'disp' => true,  'type' => 'array', 'count' => 1 ) ),
-                       array( array(),   $subjects, array( '_PVAL', '_LIST' ), 
array( 'disp' => true,  'type' => 'array', 'count' => 1 ) ),
-                       array( $subject,  $subjects, array( '_PVAL', '_LIST' ), 
array( 'disp' => true,  'type' => 'array', 'count' => 1 ) ),
-                       array( $subject,  array(),   array( '_PVAL', '_LIST' ), 
array( 'disp' => true,  'type' => 'array', 'count' => 1 ) ),
-                       array( $subject,  array(),   array( '_PVAL' ),          
array( 'disp' => true,  'type' => 'array', 'count' => 1 ) ),
-                       array( $subjects, $subjects, array( '_PVAL' ),          
array( 'disp' => false, 'type' => 'null',  'count' => 0 ) ),
-                       array( $subject,  $subject,  array( '_PVAL' ),          
array( 'disp' => false, 'type' => 'null',  'count' => 0 ) ),
-                       array( $subjects, $subjects, array( '_PVAL', '_LIST' ), 
array( 'disp' => true,  'type' => 'array', 'count' => 1 ) ),
-                       array( $subject,  $subject,  array( '_PVAL', '_LIST' ), 
array( 'disp' => true,  'type' => 'array', 'count' => 1 ) )
+                       array( $subjects, array(),   array( '_PVAL', '_LIST' ), 
array( 'change' => true,  'notifier' => $notifier ) ),
+                       array( array(),   $subjects, array( '_PVAL', '_LIST' ), 
array( 'change' => true,  'notifier' => $notifier ) ),
+                       array( $subject,  $subjects, array( '_PVAL', '_LIST' ), 
array( 'change' => true,  'notifier' => $notifier ) ),
+                       array( $subject,  array(),   array( '_PVAL', '_LIST' ), 
array( 'change' => true,  'notifier' => $notifier ) ),
+                       array( $subject,  array(),   array( '_PVAL'          ), 
array( 'change' => true,  'notifier' => $notifier ) ),
+                       array( $subjects, $subjects, array( '_PVAL'          ), 
array( 'change' => false, 'notifier' => null      ) ),
+                       array( $subject,  $subject,  array( '_PVAL'          ), 
array( 'change' => false, 'notifier' => null      ) ),
+                       array( $subjects, $subjects, array( '_PVAL', '_LIST' ), 
array( 'change' => true,  'notifier' => $notifier ) ),
+                       array( $subject,  $subject,  array( '_PVAL', '_LIST' ), 
array( 'change' => true,  'notifier' => $notifier ) )
                );
        }
 
diff --git a/tests/phpunit/includes/utilities/ChangeObserverTest.php 
b/tests/phpunit/includes/utilities/ChangeObserverTest.php
new file mode 100644
index 0000000..48df813
--- /dev/null
+++ b/tests/phpunit/includes/utilities/ChangeObserverTest.php
@@ -0,0 +1,179 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\ChangeObserver;
+
+/**
+ * Tests for the ChangeObserver 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
+ *
+ * @license GNU GPL v2+
+ * @since   1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * @covers \SMW\ChangeObserver
+ *
+ * @ingroup Test
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class ChangeObserverTest extends SemanticMediaWikiTestCase {
+
+       /**
+        * Returns the name of the class to be tested
+        *
+        * @return string|false
+        */
+       public function getClass() {
+               return '\SMW\ChangeObserver';
+       }
+
+       /**
+        * Helper method that returns a ChangeObserver object
+        *
+        * @since 1.9
+        *
+        * @param $data
+        *
+        * @return ChangeObserver
+        */
+       private function getInstance() {
+               return new ChangeObserver();
+       }
+
+       /**
+        * @test ChangeObserver::__construct
+        *
+        * @since 1.9
+        */
+       public function testConstructor() {
+               $this->assertInstanceOf( $this->getClass(), 
$this->getInstance() );
+       }
+
+       /**
+        * @test ChangeObserver::getStore
+        * @test ChangeObserver::setStore
+        *
+        * @since 1.9
+        */
+       public function testGetSetStore() {
+
+               $instance  = $this->getInstance();
+               $mockStore = $this->newMockObject()->getMockStore();
+
+               $this->assertInstanceOf( '\SMW\Store', $instance->getStore() );
+               $instance->setStore( $mockStore );
+               $this->assertInstanceOf( '\SMW\Store', $instance->getStore() );
+               $this->assertEquals( $mockStore, $instance->getStore() );
+
+       }
+
+       /**
+        * @test ChangeObserver::getCache
+        *
+        * @since 1.9
+        */
+       public function testGetCache() {
+
+               $instance = $this->getInstance();
+               $this->assertInstanceOf( '\SMW\CacheHandler', 
$instance->getCache() );
+       }
+
+       /**
+        * @test ChangeObserver::setSettings
+        * @test ChangeObserver::getSettings
+        * @dataProvider titleDataProvider
+        *
+        * @since 1.9
+        */
+       public function testGetSetSettings( $setup ) {
+
+               $instance = $this->getInstance();
+               $settings = $this->getSettings( $setup['settings'] );
+
+               $this->assertInstanceOf( '\SMW\Settings', 
$instance->getSettings() );
+
+               $instance->setSettings( $settings ) ;
+               $this->assertEquals( $settings , $instance->getSettings() );
+
+       }
+
+       /**
+        * @test ChangeObserver::runUpdateDispatcher
+        * @dataProvider titleDataProvider
+        *
+        * @since 1.9
+        */
+       public function testUpdateDispatcherJob( $setup, $expected ) {
+
+               $instance = $this->getInstance();
+               $instance->setSettings( $this->getSettings( $setup['settings'] 
) );
+
+               $this->assertTrue( $instance->runUpdateDispatcher( 
$setup['title'] ) );
+       }
+
+       /**
+        * @note smwgEnableUpdateJobs is set false to avoid having a Job being
+        * pushed into the "real" JobQueue
+        *
+        * @return array
+        */
+       public function titleDataProvider() {
+
+               $title = $this->getMockForAbstractClass( '\SMW\TitleProvider' );
+
+               $title->expects( $this->any() )
+                       ->method( 'getTitle' )
+                       ->will( $this->returnValue( $this->newTitle() ) );
+
+               $provider = array();
+
+               // #0
+               $provider[] = array(
+                       array(
+                               'settings' => array(
+                                       'smwgEnableUpdateJobs' => false,
+                                       'smwgDeferredPropertyUpdate' => false
+                               ),
+                               'title'    => $title
+                       ),
+                       array()
+               );
+
+               // #1
+               $provider[] = array(
+                       array(
+                               'settings' => array(
+                                       'smwgEnableUpdateJobs' => false,
+                                       'smwgDeferredPropertyUpdate' => true
+                               ),
+                               'title'    => $title
+                       ),
+                       array()
+               );
+
+               return $provider;
+       }
+
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/75850
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ifd8604d8ed551a62e3aa5c160e536c5cb1d0e718
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/SemanticMediaWiki
Gerrit-Branch: master
Gerrit-Owner: Mwjames <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: Mwjames <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to