Skip to content
This repository has been archived by the owner on Feb 6, 2020. It is now read-only.

Commit

Permalink
Merge branch 'hotfix/159-creation-options-must-be-null' into release-2.7
Browse files Browse the repository at this point in the history
Close #159
  • Loading branch information
weierophinney committed Dec 5, 2017
2 parents 249d9d5 + f217651 commit ba7069c
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 10 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 2.7.10 - TBD
## 2.7.10 - 2017-12-05

### Added

Expand All @@ -22,7 +22,10 @@ All notable changes to this project will be documented in this file, in reverse

### Fixed

- Nothing.
- [#210](https://github.com/zendframework/zend-servicemanager/pull/210) fixes a
regression whereby factories accepting creation options were receiving an
empty array versus a `null` value when no options were present for a
particular invocation; they now correctly receive a `null` value.

## 2.7.9 - 2017-11-27

Expand Down
36 changes: 31 additions & 5 deletions src/AbstractPluginManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use Interop\Container\ContainerInterface;
use Exception as BaseException;
use ReflectionMethod;

/**
* ServiceManager implementation for managing plugins
Expand Down Expand Up @@ -356,13 +357,38 @@ protected function createServiceViaCallback($callable, $cName, $rName)
$factory = reset($callable);
}

// duck-type MutableCreationOptionsInterface for forward compatibility
if (isset($factory)
if ($factory instanceof Factory\InvokableFactory) {
// InvokableFactory::setCreationOptions has a different signature than
// MutableCreationOptionsInterface; allows null value.
$options = is_array($this->creationOptions) && ! empty($this->creationOptions)
? $this->creationOptions
: null;
$factory->setCreationOptions($options);
} elseif ($factory instanceof MutableCreationOptionsInterface) {
// MutableCreationOptionsInterface expects an array, always; pass an
// empty array for lack of creation options.
$options = is_array($this->creationOptions) && ! empty($this->creationOptions)
? $this->creationOptions
: [];
$factory->setCreationOptions($options);
} elseif (isset($factory)
&& method_exists($factory, 'setCreationOptions')
) {
$factory->setCreationOptions(is_array($this->creationOptions) ? $this->creationOptions : []);
} elseif ($factory instanceof Factory\InvokableFactory) {
$factory->setCreationOptions(null);
// duck-type MutableCreationOptionsInterface for forward compatibility

$options = $this->creationOptions;

// If we have empty creation options, we have to find out if a default
// value is present and use that; otherwise, we should use an empty
// array, as that's the standard type-hint.
if (! is_array($options) || empty($options)) {
$r = new ReflectionMethod($factory, 'setCreationOptions');
$params = $r->getParameters();
$optionsParam = array_shift($params);
$options = $optionsParam->isDefaultValueAvailable() ? $optionsParam->getDefaultValue() : [];
}

$factory->setCreationOptions($options);
}

return parent::createServiceViaCallback($callable, $cName, $rName);
Expand Down
14 changes: 13 additions & 1 deletion test/AbstractPluginManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ public function testRetrievingServicesViaFactoryThatUsesCreationOptionsShouldRet

/**
* @group 205
* @codingStandardsIgnoreStart
*/
// @codingStandardsIgnoreStart
public function testRetrievingServicesViaFactoryThatUsesCreationOptionsShouldReturnNewInstanceEveryTimeOptionsAreProvided()
{
// @codingStandardsIgnoreEnd
Expand Down Expand Up @@ -451,4 +451,16 @@ public function testInvokableFactoryHasMutableOptions()
$object = $pluginManager->get('foo', $options);
$this->assertEquals($options, $object->getOptions());
}

public function testIfCreationOptionsAreEmptySetThemThemToNullWhenCreatingAService()
{
// @codingStandardsIgnoreEnd
/** @var $pluginManager AbstractPluginManager */
$pluginManager = $this->getMockForAbstractClass('Zend\ServiceManager\AbstractPluginManager');
$pluginManager->setFactory(Baz::class, FactoryUsingCreationOptions::class);
$pluginManager->setShared(Baz::class, false);
$plugin = $pluginManager->get(Baz::class);

$this->assertNull($plugin->options);
}
}
4 changes: 2 additions & 2 deletions test/TestAsset/FactoryUsingCreationOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ public function createService(ServiceLocatorInterface $serviceLocator)
}

/**
* @param array $creationOptions
* @param array|null $creationOptions
*
* @return void
*/
public function setCreationOptions(array $creationOptions)
public function setCreationOptions(array $creationOptions = null)
{
$this->creationOptions = $creationOptions;
}
Expand Down

0 comments on commit ba7069c

Please sign in to comment.