Mwjames has uploaded a new change for review.
https://gerrit.wikimedia.org/r/93027
Change subject: Enable DIC object definitions to be merged with other containers
......................................................................
Enable DIC object definitions to be merged with other containers
* Move mock objects into the MockObjectRepository
* Change visibility of some methods
* Rename EmptyDependencyContainer to NullDependencyContainer
Change-Id: I16f5ea5f6db35d22feaea6a968b6b80d7c7e6bc5
---
M SemanticMediaWiki.classes.php
M docs/dic.md
M includes/context/EmptyContext.php
M includes/dic/BaseDependencyContainer.php
M includes/dic/DependencyContainer.php
D includes/dic/EmptyDependencyContainer.php
A includes/dic/NullDependencyContainer.php
M includes/dic/SharedDependencyContainer.php
M includes/dic/SimpleDependencyBuilder.php
M tests/phpunit/MockObjectRepository.php
M tests/phpunit/includes/dic/SharedDependencyContainerTest.php
M tests/phpunit/includes/dic/SimpleDependencyBuilderTest.php
12 files changed, 178 insertions(+), 158 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/SemanticMediaWiki
refs/changes/27/93027/1
diff --git a/SemanticMediaWiki.classes.php b/SemanticMediaWiki.classes.php
index 9e17122..26c98bd 100644
--- a/SemanticMediaWiki.classes.php
+++ b/SemanticMediaWiki.classes.php
@@ -80,7 +80,7 @@
'SMW\DependencyObject' =>
'includes/dic/DependencyContainer.php',
'SMW\DependencyContainer' =>
'includes/dic/DependencyContainer.php',
'SMW\BaseDependencyContainer' =>
'includes/dic/BaseDependencyContainer.php',
- 'SMW\EmptyDependencyContainer' =>
'includes/dic/EmptyDependencyContainer.php',
+ 'SMW\NullDependencyContainer' =>
'includes/dic/NullDependencyContainer.php',
'SMW\SharedDependencyContainer' =>
'includes/dic/SharedDependencyContainer.php',
// Dependency Injector
diff --git a/docs/dic.md b/docs/dic.md
index b556286..81d42e7 100644
--- a/docs/dic.md
+++ b/docs/dic.md
@@ -70,7 +70,7 @@
### DependencyContainer
* DependencyContainer is an interface that specifies how to register a
DepencyObject.
* BaseDependencyContainer implements the DependencyContainer and declares
methods to retrieve and store object definitions
-* EmptyDependencyContainer is an empty container that extends
BaseDependencyContainer
+* NullDependencyContainer is an empty container that extends
BaseDependencyContainer
* SharedDependencyContainer implements most common object definitions that are
used within Semantic MediaWiki
```php
diff --git a/includes/context/EmptyContext.php
b/includes/context/EmptyContext.php
index a4fbe8a..abe1386 100644
--- a/includes/context/EmptyContext.php
+++ b/includes/context/EmptyContext.php
@@ -63,7 +63,7 @@
protected function register( DependencyBuilder $builder = null ) {
if ( $builder === null ) {
- $builder = new SimpleDependencyBuilder( new
EmptyDependencyContainer() );
+ $builder = new SimpleDependencyBuilder( new
NullDependencyContainer() );
}
$builder->getContainer()->registerObject( 'Settings', null );
diff --git a/includes/dic/BaseDependencyContainer.php
b/includes/dic/BaseDependencyContainer.php
index 3ed9503..805475f 100644
--- a/includes/dic/BaseDependencyContainer.php
+++ b/includes/dic/BaseDependencyContainer.php
@@ -3,23 +3,17 @@
namespace SMW;
/**
- * Provides a DependencyContainer base class
- *
- * @file
- *
- * @license GNU GPL v2+
- * @since 1.9
- *
- * @author mwjames
- */
-
-/**
* Implements the DependencyContainer interface and is responsible for handling
* object storage, and retrieval of object definitions
*
- * Examples and a more exhaustive description can be found at /di/README.md
+ * Examples and a more exhaustive description can be found at /docs/dic.md
*
* @ingroup DependencyContainer
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
*/
abstract class BaseDependencyContainer extends ObjectStorage implements
DependencyContainer {
@@ -60,11 +54,9 @@
}
/**
- * Returns storage array
+ * @see ObjectStorage::detach
*
- * @since 1.9
- *
- * @return array
+ * @since 1.9
*/
public function toArray() {
return $this->storage;
@@ -75,10 +67,10 @@
*
* @since 1.9
*
- * @param array $mergeable
+ * @return array
*/
public function merge( array $mergeable ) {
- $this->storage = array_merge( $this->storage, $mergeable );
+ $this->storage = array_merge_recursive( $this->storage,
$mergeable );
}
/**
@@ -94,7 +86,7 @@
}
/**
- * Register an object
+ * @see DependencyContainer::registerObject
*
* @since 1.9
*
@@ -107,12 +99,26 @@
}
/**
- * @see DependencyContainer::loadObjects
+ * @see DependencyContainer::loadAllDefinitions
*
* @since 1.9
+ *
+ * @return array
*/
- public function loadObjects() {
- return array();
+ public function loadAllDefinitions() {
+
+ if ( !$this->has( 'def_' ) ) {
+ $this->set( 'def_', $this->getDefinitions() );
+ }
+
+ return $this->get( 'def_' );
}
+ /**
+ * @since 1.9
+ *
+ * @return array
+ */
+ protected abstract function getDefinitions();
+
}
diff --git a/includes/dic/DependencyContainer.php
b/includes/dic/DependencyContainer.php
index 0398b73..aaadf92 100644
--- a/includes/dic/DependencyContainer.php
+++ b/includes/dic/DependencyContainer.php
@@ -3,20 +3,14 @@
namespace SMW;
/**
- * Provides interfaces for dependency injection
- *
- * @file
- *
- * @license GNU GPL v2+
- * @since 1.9
- *
- * @author mwjames
- */
-
-/**
* Interface specifying a dependency object
*
* @ingroup DependencyContainer
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
*/
interface DependencyObject {
@@ -33,7 +27,7 @@
*
* @param DependencyBuilder $builder
*/
- public function inheritDescription( DependencyBuilder $builder );
+ public function retrieveDefinition( DependencyBuilder $builder );
}
@@ -52,10 +46,10 @@
public function registerObject( $objectName, $objectSignature,
$objectScope );
/**
- * Collects and map objects for deferred registration
+ * Retrieves object definitions
*
* @since 1.9
*/
- public function loadObjects();
+ public function loadAllDefinitions();
}
diff --git a/includes/dic/EmptyDependencyContainer.php
b/includes/dic/EmptyDependencyContainer.php
deleted file mode 100644
index 8f1ad5d..0000000
--- a/includes/dic/EmptyDependencyContainer.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-namespace SMW;
-
-/**
- * Provides an empty DependencyContainer entity
- *
- * @file
- *
- * @license GNU GPL v2+
- * @since 1.9
- *
- * @author mwjames
- */
-
-/**
- * Provides an empty DependencyContainer entity
- *
- * @ingroup DependencyContainer
- */
-class EmptyDependencyContainer extends BaseDependencyContainer {}
diff --git a/includes/dic/NullDependencyContainer.php
b/includes/dic/NullDependencyContainer.php
new file mode 100644
index 0000000..513103b
--- /dev/null
+++ b/includes/dic/NullDependencyContainer.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace SMW;
+
+/**
+ * Provides an empty DependencyContainer entity
+ *
+ * @ingroup DependencyContainer
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class NullDependencyContainer extends BaseDependencyContainer {
+
+ /**
+ * @since 1.9
+ */
+ protected function getDefinitions() {
+ return null;
+ }
+
+}
diff --git a/includes/dic/SharedDependencyContainer.php
b/includes/dic/SharedDependencyContainer.php
index 37f3942..c8c2696 100644
--- a/includes/dic/SharedDependencyContainer.php
+++ b/includes/dic/SharedDependencyContainer.php
@@ -19,15 +19,13 @@
* @since 1.9
*/
public function __construct() {
- $this->load();
+ $this->loadAtInstantiation();
}
/**
- * Load object definitions in advance
- *
* @since 1.9
*/
- public function load() {
+ protected function loadAtInstantiation() {
/**
* Settings object definition
@@ -65,15 +63,13 @@
}
/**
- * Load object definitions on request
- *
- * @see DependencyContainer::loadObjects
+ * @see BaseDependencyContainer::registerDefinitions
*
* @since 1.9
*
* @return array
*/
- public function loadObjects() {
+ protected function getDefinitions() {
return array(
'ParserData' => $this->getParserData(),
'NamespaceExaminer' =>
$this->getNamespaceExaminer(),
diff --git a/includes/dic/SimpleDependencyBuilder.php
b/includes/dic/SimpleDependencyBuilder.php
index 4695772..b1e2546 100644
--- a/includes/dic/SimpleDependencyBuilder.php
+++ b/includes/dic/SimpleDependencyBuilder.php
@@ -38,7 +38,7 @@
protected $recursionLevel = 0;
/**
- * Specifies a depth (or threshold) for a dependency graph. In case a
build
+ * Specifies a max depth (or threshold) for a dependency graph. In case
a build
* will overstep this limit it is assumed that the builder is caught in
an
* infinite loop due to a self-reference (circular reference) within its
* object definition
@@ -61,19 +61,23 @@
$this->dependencyContainer = $dependencyContainer;
if ( $this->dependencyContainer === null ) {
- $this->dependencyContainer = new
EmptyDependencyContainer();
+ $this->dependencyContainer = new
NullDependencyContainer();
}
}
/**
- * Register DependencyContainer
+ * Register a DependencyContainer
*
* @since 1.9
*
* @param DependencyContainer $container
*/
public function registerContainer( DependencyContainer $container ) {
+
+ $this->dependencyContainer->loadAllDefinitions();
+ $container->loadAllDefinitions();
+
$this->dependencyContainer->merge( $container->toArray() );
}
@@ -233,7 +237,7 @@
if ( !$this->dependencyContainer->has( $objectName ) ) {
- if ( !$this->search( $objectName ) ) {
+ if ( !$this->searchObjectByName( $objectName ) ) {
throw new OutOfBoundsException( "{$objectName}
is not registered or available as service object" );
};
@@ -250,7 +254,7 @@
}
if ( $objectSignature instanceOf DependencyObject ) {
- $objectSignature =
$objectSignature->inheritDescription( $this );
+ $objectSignature =
$objectSignature->retrieveDefinition( $this );
}
return $this->load( $objectName, $objectSignature, $objectScope
);
@@ -324,15 +328,13 @@
}
/**
- * Locate and register a deferred object
- *
- * @param string $objectName
+ * @since 1.9
*
* @return boolean
*/
- private function search( $objectName ) {
+ private function searchObjectByName( $objectName ) {
- $objectCatalog = $this->dependencyContainer->loadObjects();
+ $objectCatalog =
$this->dependencyContainer->loadAllDefinitions();
if ( isset( $objectCatalog[$objectName] ) ) {
diff --git a/tests/phpunit/MockObjectRepository.php
b/tests/phpunit/MockObjectRepository.php
index bd7f2fa..2b34368 100644
--- a/tests/phpunit/MockObjectRepository.php
+++ b/tests/phpunit/MockObjectRepository.php
@@ -151,6 +151,58 @@
}
/**
+ * Returns an DependencyObject object
+ *
+ * @since 1.9
+ *
+ * @return DependencyObject
+ */
+ public function DependencyObject() {
+
+ $methods = $this->builder->getInvokedMethods();
+
+ $dependencyObject = $this->getMockBuilder(
'SMW\DependencyObject' )
+ ->setMethods( $methods )
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $dependencyObject->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method )
);
+
+ }
+
+ return $dependencyObject;
+ }
+
+ /**
+ * Returns an Observer object
+ *
+ * @since 1.9
+ *
+ * @return Observer
+ */
+ public function FakeDependencyContainer() {
+
+ $methods = $this->builder->getInvokedMethods();
+
+ $dependencyObject = $this->getMockBuilder(
'SMW\NullDependencyContainer' )
+ ->setMethods( $methods )
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $dependencyObject->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method )
);
+
+ }
+
+ return $dependencyObject;
+ }
+
+ /**
* Returns a ParserData object
*
* @since 1.9
diff --git a/tests/phpunit/includes/dic/SharedDependencyContainerTest.php
b/tests/phpunit/includes/dic/SharedDependencyContainerTest.php
index 4755abc..86aaa9f 100644
--- a/tests/phpunit/includes/dic/SharedDependencyContainerTest.php
+++ b/tests/phpunit/includes/dic/SharedDependencyContainerTest.php
@@ -88,7 +88,7 @@
$this->assertObjectRegistration( $objectName,
$registeredObjects );
}
- foreach ( $instance->loadObjects() as $objectName =>
$objectSiganture ) {
+ foreach ( $instance->loadAllDefinitions() as $objectName =>
$objectSiganture ) {
$this->assertObjectRegistration( $objectName,
$registeredObjects );
}
diff --git a/tests/phpunit/includes/dic/SimpleDependencyBuilderTest.php
b/tests/phpunit/includes/dic/SimpleDependencyBuilderTest.php
index 3885fda..a1c5d1f 100644
--- a/tests/phpunit/includes/dic/SimpleDependencyBuilderTest.php
+++ b/tests/phpunit/includes/dic/SimpleDependencyBuilderTest.php
@@ -2,7 +2,7 @@
namespace SMW\Test;
-use SMW\EmptyDependencyContainer;
+use SMW\NullDependencyContainer;
use SMW\SimpleDependencyBuilder;
use SMW\DependencyBuilder;
use SMW\DependencyObject;
@@ -46,36 +46,6 @@
/**
* @since 1.9
*
- * @return DependencyContainer
- */
- private function newDependencyContainer( $toArray = array() ) {
-
- $container = $this->getMockBuilder( '\SMW\DependencyContainer' )
- ->disableOriginalConstructor()
- ->setMethods( array(
- 'preload',
- 'toArray',
- 'registerObject',
- 'has',
- 'get',
- 'set',
- 'remove',
- 'merge',
- 'loadObjects'
- )
- )
- ->getMock();
-
- $container->expects( $this->any() )
- ->method( 'toArray' )
- ->will( $this->returnValue( $toArray ) );
-
- return $container;
- }
-
- /**
- * @since 1.9
- *
* @return SimpleDependencyBuilder
*/
private function newInstance( $dependencyContainer = null ) {
@@ -96,8 +66,12 @@
$instance = $this->newInstance();
+ $container = $this->newMockBuilder()->newObject(
'FakeDependencyContainer', array(
+ 'toArray' => array( 'Test' => array( '123', 0 ) )
+ ) );
+
// Register container
- $instance->registerContainer( $this->newDependencyContainer(
array( 'Test' => array( '123', 0 ) ) ) );
+ $instance->registerContainer( $container );
$this->assertEquals(
'123',
@@ -105,8 +79,12 @@
'asserts object creation'
);
+ $container = $this->newMockBuilder()->newObject(
'FakeDependencyContainer', array(
+ 'toArray' => array( 'Test2' => array( 9001, 1 ) )
+ ) );
+
// Register additional container and asserts that both objects
are available
- $instance->registerContainer( $this->newDependencyContainer(
array( 'Test2' => array( 9001, 1 ) ) ) );
+ $instance->registerContainer( $container );
$this->assertEquals(
'123',
@@ -132,20 +110,28 @@
$instance = $this->newInstance();
- $instance->registerContainer( $this->newDependencyContainer(
array( 'Test' => array( 9001, 1 ) ) ) );
+ $container = $this->newMockBuilder()->newObject(
'FakeDependencyContainer', array(
+ 'toArray' => array( 'Test' => array( 9001, 1 ) )
+ ) );
+
+ $instance->registerContainer( $container );
$this->assertEquals(
9001,
$instance->newObject( 'Test' ),
- 'asserts object creation after container merge'
+ 'Asserts object creation after container merge'
);
- $instance->registerContainer( $this->newDependencyContainer(
array( 'Test' => array( 1009, 0 ) ) ) );
+ $container = $this->newMockBuilder()->newObject(
'FakeDependencyContainer', array(
+ 'toArray' => array( 'Test' => array( 1009, 0 ) )
+ ) );
+
+ $instance->registerContainer( $container );
$this->assertEquals(
- 1009,
+ 9001,
$instance->newObject( 'Test' ),
- 'asserts object definition has been overridden'
+ 'Asserts object definition has not been overridden'
);
}
@@ -173,7 +159,7 @@
public function testRegisterObjectUsingMagicMethodEagerLoading() {
$instance = $this->newInstance();
- $container = new EmptyDependencyContainer();
+ $container = new NullDependencyContainer();
// Eager loading
$container->someFunnyTitle = $this->newTitle();
@@ -194,7 +180,7 @@
public function testRegisterObjectUsingMagicMethodLazyLoading() {
$instance = $this->newInstance();
- $container = new EmptyDependencyContainer();
+ $container = new NullDependencyContainer();
$container->someFunnyTitle = $this->newTitle();
$container->FakeWikiPage = function ( DependencyBuilder
$builder ) {
@@ -234,7 +220,7 @@
$instance = $this->newInstance();
// Clear registered container
- $instance->registerContainer( new EmptyDependencyContainer() );
+ $instance->registerContainer( new NullDependencyContainer() );
// Object is using an argument that where invoked using the
__set method
// and is evenly accessible during the build process using
newObject()
@@ -591,8 +577,9 @@
*/
public function testDeferredLoading( $setup, $expected ) {
- $container = new FakeDependencyContainer();
- $container->setObjects( array( 'Quux' => $setup ) );
+ $container = $this->newMockBuilder()->newObject(
'FakeDependencyContainer', array(
+ 'getDefinitions' => array( 'Quux' => $setup )
+ ) );
$instance = $this->newInstance( $container );
@@ -612,8 +599,7 @@
*/
public function
testDeferredLoadingWithScopeChangeAndRecursiveObjectGraph() {
- $container = new FakeDependencyContainer();
- $container->setObjects( array(
+ $objectGraph = array(
'Title' => function( $builder ) {
return new Title();
@@ -631,6 +617,10 @@
return $builder->newObject( 'Bar' );
}
+ );
+
+ $container = $this->newMockBuilder()->newObject(
'FakeDependencyContainer', array(
+ 'getDefinitions' => $objectGraph
) );
$instance = $this->newInstance( $container );
@@ -762,8 +752,7 @@
$this->setExpectedException( 'OutOfBoundsException' );
- $container = new FakeDependencyContainer();
- $container->setObjects( array(
+ $objectGraph = array(
'Title' => function( $builder ) {
return $builder->newObject( 'Title' ); //
self-reference
@@ -785,6 +774,10 @@
return $builder->newObject( 'Foo' );
}
+ );
+
+ $container = $this->newMockBuilder()->newObject(
'FakeDependencyContainer', array(
+ 'getDefinitions' => $objectGraph
) );
$instance = $this->newInstance( $container );
@@ -833,26 +826,16 @@
$closure = function() use( $stdClass ) { return $stdClass; };
// #0
- $dependencyObject = $this->getMockBuilder(
'\SMW\DependencyObject' )
- ->disableOriginalConstructor()
- ->setMethods( array( 'inheritDescription' ) )
- ->getMock();
-
- $dependencyObject->expects( $this->any() )
- ->method( 'inheritDescription' )
- ->will( $this->returnValue( $stdClass ) );
+ $dependencyObject = $this->newMockBuilder()->newObject(
'DependencyObject', array(
+ 'retrieveDefinition' => $stdClass
+ ) );
$provider[] = array( $dependencyObject, $stdClass );
// #1
- $dependencyObject = $this->getMockBuilder(
'\SMW\DependencyObject' )
- ->disableOriginalConstructor()
- ->setMethods( array( 'inheritDescription' ) )
- ->getMock();
-
- $dependencyObject->expects( $this->any() )
- ->method( 'inheritDescription' )
- ->will( $this->returnValue( $closure ) );
+ $dependencyObject = $this->newMockBuilder()->newObject(
'DependencyObject', array(
+ 'retrieveDefinition' => $closure
+ ) );
$provider[] = array( $dependencyObject, $stdClass );
@@ -867,22 +850,6 @@
}
-/**
- * A fake dependency container
- */
-class FakeDependencyContainer extends EmptyDependencyContainer {
-
- protected $objects;
-
- public function setObjects( $objects ) {
- $this->objects = $objects;
- }
-
- public function loadObjects() {
- return $this->objects;
- }
-
-}
/**
* A fake object instance
--
To view, visit https://gerrit.wikimedia.org/r/93027
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I16f5ea5f6db35d22feaea6a968b6b80d7c7e6bc5
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