BryanDavis has uploaded a new change for review.
https://gerrit.wikimedia.org/r/228020
Change subject: ObjectFactory: add support for setter injection
......................................................................
ObjectFactory: add support for setter injection
Extend ObjectFactory::getObjectFromSpec() to support setter injection on
created objects when the specification includes a 'calls' member.
Bug: T107440
Change-Id: Ie2ece2e9658dd2d895d3935da4dc2da8a0a316e2
---
M includes/libs/ObjectFactory.php
M tests/phpunit/includes/libs/ObjectFactoryTest.php
2 files changed, 63 insertions(+), 11 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/20/228020/1
diff --git a/includes/libs/ObjectFactory.php b/includes/libs/ObjectFactory.php
index ec8c36a..1cb544b 100644
--- a/includes/libs/ObjectFactory.php
+++ b/includes/libs/ObjectFactory.php
@@ -49,6 +49,13 @@
* constructor/callable. This behavior can be suppressed by adding
* closure_expansion => false to the specification.
*
+ * The specification may also contain a 'calls' key that describes
method
+ * calls to make on the newly created object before returning it. This
+ * pattern is often known as "setter injection". The value of this key
is
+ * expected to be an associative array with method names as keys and
+ * argument lists as values. The argument list will be expanded (or not)
+ * in the same way as the 'args' key for the main object.
+ *
* @param array $spec Object specification
* @return object
* @throws InvalidArgumentException when object specification does not
@@ -58,18 +65,11 @@
*/
public static function getObjectFromSpec( $spec ) {
$args = isset( $spec['args'] ) ? $spec['args'] : array();
+ $expandArgs = !isset( $spec['closure_expansion'] ) ||
+ $spec['closure_expansion'] === true;
- if ( !isset( $spec['closure_expansion'] ) ||
- $spec['closure_expansion'] === true
- ) {
- $args = array_map( function ( $value ) {
- if ( is_object( $value ) && $value instanceof
Closure ) {
- // If an argument is a Closure, call it.
- return $value();
- } else {
- return $value;
- }
- }, $args );
+ if ( $expandArgs ) {
+ $args = static::expandClosures( $args );
}
if ( isset( $spec['class'] ) ) {
@@ -88,6 +88,33 @@
);
}
+ if ( isset( $spec['calls'] ) && is_array( $spec['calls'] ) ) {
+ // Call additional methods on the newly created object
+ foreach ( $spec['calls'] as $method => $margs ) {
+ if ( $expandArgs ) {
+ $margs = static::expandClosures( $margs
);
+ }
+ call_user_func_array( array( $obj, $method ),
$margs );
+ }
+ }
+
return $obj;
}
+
+ /**
+ * Iterate a list and call any closures it contains.
+ *
+ * @param array $list List of things
+ * @return array List with any Closures replaced with their output
+ */
+ protected static function expandClosures( $list ) {
+ return array_map( function ( $value ) {
+ if ( is_object( $value ) && $value instanceof Closure )
{
+ // If $value is a Closure, call it.
+ return $value();
+ } else {
+ return $value;
+ }
+ }, $list );
+ }
}
diff --git a/tests/phpunit/includes/libs/ObjectFactoryTest.php
b/tests/phpunit/includes/libs/ObjectFactoryTest.php
index a9d3cc1..aea037e 100644
--- a/tests/phpunit/includes/libs/ObjectFactoryTest.php
+++ b/tests/phpunit/includes/libs/ObjectFactoryTest.php
@@ -29,10 +29,17 @@
'args' => array( function() {
return 'unwrapped';
}, ),
+ 'calls' => array(
+ 'setter' => array( function() {
+ return 'unwrapped';
+ }, ),
+ ),
'closure_expansion' => false,
) );
$this->assertInstanceOf( 'Closure', $obj->args[0] );
$this->assertSame( 'unwrapped', $obj->args[0]() );
+ $this->assertInstanceOf( 'Closure', $obj->setterArgs[0] );
+ $this->assertSame( 'unwrapped', $obj->setterArgs[0]() );
}
/**
@@ -44,25 +51,43 @@
'args' => array( function() {
return 'unwrapped';
}, ),
+ 'calls' => array(
+ 'setter' => array( function() {
+ return 'unwrapped';
+ }, ),
+ ),
'closure_expansion' => true,
) );
$this->assertInternalType( 'string', $obj->args[0] );
$this->assertSame( 'unwrapped', $obj->args[0] );
+ $this->assertInternalType( 'string', $obj->setterArgs[0] );
+ $this->assertSame( 'unwrapped', $obj->setterArgs[0] );
$obj = ObjectFactory::getObjectFromSpec( array(
'class' => 'ObjectFactoryTest_Fixture',
'args' => array( function() {
return 'unwrapped';
}, ),
+ 'calls' => array(
+ 'setter' => array( function() {
+ return 'unwrapped';
+ }, ),
+ ),
) );
$this->assertInternalType( 'string', $obj->args[0] );
$this->assertSame( 'unwrapped', $obj->args[0] );
+ $this->assertInternalType( 'string', $obj->setterArgs[0] );
+ $this->assertSame( 'unwrapped', $obj->setterArgs[0] );
}
}
class ObjectFactoryTest_Fixture {
public $args;
+ public $setterArgs;
public function __construct( /*...*/ ) {
$this->args = func_get_args();
}
+ public function setter( /*...*/ ) {
+ $this->setterArgs = func_get_args();
+ }
}
--
To view, visit https://gerrit.wikimedia.org/r/228020
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie2ece2e9658dd2d895d3935da4dc2da8a0a316e2
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: BryanDavis <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits