From 7756cc1a6e312178f95fedbc75d19c277601ebe0 Mon Sep 17 00:00:00 2001 From: Gianluca Arbezzano Date: Tue, 8 Dec 2015 22:23:13 +0000 Subject: [PATCH 1/9] ServiceManager v2-v3 compatibility --- .travis.yml | 8 ++ composer.json | 8 +- src/Factory.php | 14 +-- src/InputFilterAbstractServiceFactory.php | 66 ++++++++--- src/InputFilterPluginManager.php | 106 ++++++++++++++--- test/FactoryTest.php | 112 +++++++++++------- .../InputFilterAbstractServiceFactoryTest.php | 88 +++++++++----- test/InputFilterPluginManagerTest.php | 46 ++++--- test/MigrationTest.php | 42 +++++++ 9 files changed, 349 insertions(+), 141 deletions(-) create mode 100644 test/MigrationTest.php diff --git a/.travis.yml b/.travis.yml index 7d2515e4..c30dde09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,9 +17,15 @@ matrix: - php: 5.5 env: - EXECUTE_CS_CHECK=true + - php: 5.5 + env: + - SERVICE_MANAGER_VERSION="^2.7.5" - php: 5.6 env: - EXECUTE_TEST_COVERALLS=true + - php: 5.6 + env: + - SERVICE_MANAGER_VERSION="^2.7.5" - php: 7 - php: hhvm allow_failures: @@ -41,6 +47,8 @@ script: - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/phpunit --coverage-clover clover.xml ; fi - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then ./vendor/bin/phpunit ; fi - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run ; fi + - if [[ $SERVICE_MANAGER_VERSION != '' ]]; then composer require --no-update "zendframework/zend-servicemanager:$SERVICE_MANAGER_VERSION" ; fi + - if [[ $SERVICE_MANAGER_VERSION == '' ]]; then composer require --no-update "zendframework/zend-servicemanager:^3.0.3" ; fi after_script: - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/coveralls ; fi diff --git a/composer.json b/composer.json index 69a2694f..90d613d0 100644 --- a/composer.json +++ b/composer.json @@ -14,12 +14,12 @@ }, "require": { "php": ">=5.5", - "zendframework/zend-filter": "~2.5", - "zendframework/zend-validator": "^2.5.3", - "zendframework/zend-stdlib": "~2.5" + "zendframework/zend-filter": "^2.6.0", + "zendframework/zend-validator": "^2.6.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { - "zendframework/zend-servicemanager": "~2.5", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", "fabpot/php-cs-fixer": "1.7.*", "phpunit/PHPUnit": "^4.5" }, diff --git a/src/Factory.php b/src/Factory.php index ecdb2299..5cfa614b 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -11,7 +11,7 @@ use Traversable; use Zend\Filter\FilterChain; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\ServiceManager; use Zend\Stdlib\ArrayUtils; use Zend\Validator\ValidatorChain; use Zend\Validator\ValidatorInterface; @@ -117,15 +117,7 @@ public function clearDefaultValidatorChain() public function setInputFilterManager(InputFilterPluginManager $inputFilterManager) { $this->inputFilterManager = $inputFilterManager; - $serviceLocator = $this->inputFilterManager->getServiceLocator(); - if ($serviceLocator && $serviceLocator instanceof ServiceLocatorInterface) { - if ($serviceLocator->has('ValidatorManager')) { - $this->getDefaultValidatorChain()->setPluginManager($serviceLocator->get('ValidatorManager')); - } - if ($serviceLocator->has('FilterManager')) { - $this->getDefaultFilterChain()->setPluginManager($serviceLocator->get('FilterManager')); - } - } + $inputFilterManager->populateFactoryPluginManagers($this); return $this; } @@ -135,7 +127,7 @@ public function setInputFilterManager(InputFilterPluginManager $inputFilterManag public function getInputFilterManager() { if (null === $this->inputFilterManager) { - $this->inputFilterManager = new InputFilterPluginManager; + $this->inputFilterManager = new InputFilterPluginManager(new ServiceManager()); } return $this->inputFilterManager; diff --git a/src/InputFilterAbstractServiceFactory.php b/src/InputFilterAbstractServiceFactory.php index 5d8c5506..ef551ed3 100644 --- a/src/InputFilterAbstractServiceFactory.php +++ b/src/InputFilterAbstractServiceFactory.php @@ -9,9 +9,11 @@ namespace Zend\InputFilter; +use Interop\Container\ContainerInterface; use Zend\Filter\FilterPluginManager; use Zend\ServiceManager\AbstractFactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\ServiceManager; use Zend\Validator\ValidatorPluginManager; class InputFilterAbstractServiceFactory implements AbstractFactoryInterface @@ -21,22 +23,47 @@ class InputFilterAbstractServiceFactory implements AbstractFactoryInterface */ protected $factory; + /** - * @param ServiceLocatorInterface $inputFilters + * @param ContainerInterface $services + * @param string $rName + * @param array $options + * @return InputFilterInterface + */ + public function __invoke(ContainerInterface $services, $rName, array $options = null) + { + // v2 - get parent service manager + if (! method_exists($services, 'configure')) { + $services = $services->getServiceLocator(); + } + + $allConfig = $services->get('config'); + $config = $allConfig['input_filter_specs'][$rName]; + + $factory = $this->getInputFilterFactory($services); + + return $factory->createInputFilter($config); + } + + /** + * + * @param ContainerInterface $services * @param string $cName * @param string $rName * @return bool */ - public function canCreateServiceWithName(ServiceLocatorInterface $inputFilters, $cName, $rName) + public function canCreate(ContainerInterface $services, $rName) { - $services = $inputFilters->getServiceLocator(); - if (! $services instanceof ServiceLocatorInterface - || ! $services->has('Config') - ) { + // v2 - get parent service manager + if (! method_exists($services, 'configure')) { + $services = $services->getServiceLocator(); + } + + if (! $services->has('config')) { return false; } - $config = $services->get('Config'); + $config = $services->get('config'); if (!isset($config['input_filter_specs'][$rName]) || !is_array($config['input_filter_specs'][$rName]) ) { @@ -46,6 +73,19 @@ public function canCreateServiceWithName(ServiceLocatorInterface $inputFilters, return true; } + /** + * Determine if we can create a service with name (v2) + * + * @param ServiceLocatorInterface $serviceLocator + * @param $name + * @param $requestedName + * @return bool + */ + public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) + { + return $this->canCreate($serviceLocator, $requestedName); + } + /** * @param ServiceLocatorInterface $inputFilters * @param string $cName @@ -54,13 +94,7 @@ public function canCreateServiceWithName(ServiceLocatorInterface $inputFilters, */ public function createServiceWithName(ServiceLocatorInterface $inputFilters, $cName, $rName) { - $services = $inputFilters->getServiceLocator(); - $allConfig = $services->get('Config'); - $config = $allConfig['input_filter_specs'][$rName]; - - $factory = $this->getInputFilterFactory($services); - - return $factory->createInputFilter($config); + return $this($inputFilters, $rName); } /** @@ -94,7 +128,7 @@ protected function getFilterPluginManager(ServiceLocatorInterface $services) return $services->get('FilterManager'); } - return new FilterPluginManager(); + return new FilterPluginManager(new ServiceManager()); } /** @@ -107,6 +141,6 @@ protected function getValidatorPluginManager(ServiceLocatorInterface $services) return $services->get('ValidatorManager'); } - return new ValidatorPluginManager(); + return new ValidatorPluginManager(new ServiceManager()); } } diff --git a/src/InputFilterPluginManager.php b/src/InputFilterPluginManager.php index 3290b102..bd6340c6 100644 --- a/src/InputFilterPluginManager.php +++ b/src/InputFilterPluginManager.php @@ -9,9 +9,10 @@ namespace Zend\InputFilter; +use Interop\Container\ContainerInterface; use Zend\ServiceManager\AbstractPluginManager; -use Zend\ServiceManager\ConfigInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Exception\InvalidServiceException; +use Zend\ServiceManager\Factory\InvokableFactory; use Zend\Stdlib\InitializableInterface; /** @@ -22,55 +23,100 @@ class InputFilterPluginManager extends AbstractPluginManager { /** - * Default set of plugins + * Default alias of plugins * * @var string[] */ - protected $invokableClasses = [ + protected $aliases = [ 'inputfilter' => InputFilter::class, + 'inputFilter' => InputFilter::class, + 'InputFilter' => InputFilter::class, 'collection' => CollectionInputFilter::class, + 'Collection' => CollectionInputFilter::class, ]; /** - * Whether or not to share by default + * Default set of plugins + * + * @var string[] + */ + protected $factories = [ + InputFilter::class => InvokableFactory::class, + CollectionInputFilter::class => InvokableFactory::class, + // v2 canonical FQCN + 'zendinputfilterinputfilter' => InvokableFactory::class, + 'zendinputfiltercollectioninputfilter' => InvokableFactory::class, + ]; + + /** + * Whether or not to share by default (v3) + * + * @var bool + */ + protected $sharedByDefault = false; + + /** + * Whether or not to share by default (v2) * * @var bool */ protected $shareByDefault = false; + /** - * @param ConfigInterface $configuration + * @param ContainerInterface $parentLocator + * @param array $config */ - public function __construct(ConfigInterface $configuration = null) + public function __construct(ContainerInterface $parentLocator, array $config = []) { - parent::__construct($configuration); - + parent::__construct($parentLocator, $config); $this->addInitializer([$this, 'populateFactory']); } /** * Inject this and populate the factory with filter chain and validator chain * - * @param $inputFilter + * @param mixed $first + * @param mixed $second */ - public function populateFactory($inputFilter) + public function populateFactory($first, $second) { + if ($first instanceof ContainerInterface) { + $container = $first; + $inputFilter = $second; + } else { + $container = $second; + $inputFilter = $first; + } if ($inputFilter instanceof InputFilter) { $factory = $inputFilter->getFactory(); $factory->setInputFilterManager($this); + } + } - if ($this->serviceLocator instanceof ServiceLocatorInterface) { - $factory->getDefaultFilterChain()->setPluginManager($this->serviceLocator->get('FilterManager')); - $factory->getDefaultValidatorChain()->setPluginManager($this->serviceLocator->get('ValidatorManager')); - } + public function populateFactoryPluginManagers(Factory $factory) + { + if (property_exists($this, 'creationContext')) { + // v3 + $container = $this->creationContext; + } else { + // v2 + $container = $this->serviceLocator; + } + + if ($container && $container->has('FilterManager')) { + $factory->getDefaultFilterChain()->setPluginManager($container->get('FilterManager')); + } + if ($container && $container->has('ValidatorManager')) { + $factory->getDefaultValidatorChain()->setPluginManager($container->get('ValidatorManager')); } } /** - * {@inheritDoc} + * {@inheritDoc} (v3) */ - public function validatePlugin($plugin) + public function validate($plugin) { if ($plugin instanceof InputFilterInterface || $plugin instanceof InputInterface) { // Hook to perform various initialization, when the inputFilter is not created through the factory @@ -82,11 +128,35 @@ public function validatePlugin($plugin) return; } - throw new Exception\RuntimeException(sprintf( + throw new InvalidServiceException(sprintf( 'Plugin of type %s is invalid; must implement %s or %s', (is_object($plugin) ? get_class($plugin) : gettype($plugin)), InputFilterInterface::class, InputInterface::class )); } + + /** + * Validate the plugin (v2) + * + * Checks that the filter loaded is either a valid callback or an instance + * of FilterInterface. + * + * @param mixed $plugin + * @return void + * @throws Exception\RuntimeException if invalid + */ + public function validatePlugin($plugin) + { + try { + $this->validate($plugin); + } catch (InvalidServiceException $e) { + throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e); + } + } + + public function shareByDefault() + { + return $this->sharedByDefault; + } } diff --git a/test/FactoryTest.php b/test/FactoryTest.php index 41cd1bda..2be82eba 100644 --- a/test/FactoryTest.php +++ b/test/FactoryTest.php @@ -9,6 +9,7 @@ namespace ZendTest\InputFilter; +use Interop\Container\ContainerInterface; use PHPUnit_Framework_MockObject_MockObject as MockObject; use PHPUnit_Framework_TestCase as TestCase; use Zend\Filter; @@ -45,17 +46,17 @@ public function testCreateInputWithInvalidDataTypeThrowsInvalidArgumentException public function testCreateInputWithTypeAsAnUnknownPluginAndNotExistsAsClassNameThrowException() { - $factory = $this->createDefaultFactory(); $type = 'foo'; - /** @var InputFilterPluginManager|MockObject $pluginManager */ - $pluginManager = $this->getMock(InputFilterPluginManager::class); + $pluginManager = $this->getMockBuilder(InputFilterPluginManager::class) + ->disableOriginalConstructor() + ->getMock(); $pluginManager->expects($this->atLeastOnce()) ->method('has') ->with($type) - ->willReturn(false) - ; - $factory->setInputFilterManager($pluginManager); + ->willReturn(false); + + $factory = new Factory($pluginManager); $this->setExpectedException( RuntimeException::class, @@ -68,13 +69,30 @@ public function testCreateInputWithTypeAsAnUnknownPluginAndNotExistsAsClassNameT ); } + public function testGetInputFilterManagerSettedByItsSetter() + { + $pluginManager = $this->getMockBuilder(InputFilterPluginManager::class) + ->disableOriginalConstructor() + ->getMock(); + $factory = new Factory(); + $factory->setInputFilterManager($pluginManager); + $this->assertSame($pluginManager, $factory->getInputFilterManager()); + } + + public function testGetInputFilterManagerWhenYouConstructFactoryWithIt() + { + $pluginManager = $this->getMockBuilder(InputFilterPluginManager::class) + ->disableOriginalConstructor() + ->getMock(); + $factory = new Factory($pluginManager); + $this->assertSame($pluginManager, $factory->getInputFilterManager()); + } + public function testCreateInputWithTypeAsAnInvalidPluginInstanceThrowException() { - $factory = $this->createDefaultFactory(); $type = 'fooPlugin'; $pluginManager = $this->createInputFilterPluginManagerMockForPlugin($type, 'invalid_value'); - - $factory->setInputFilterManager($pluginManager); + $factory = new Factory($pluginManager); $this->setExpectedException( RuntimeException::class, @@ -283,9 +301,11 @@ public function testFactoryAllowsInjectingValidatorChain() public function testFactoryUsesComposedFilterChainWhenCreatingNewInputObjects() { + $smMock = $this->getMock(ContainerInterface::class); + $factory = $this->createDefaultFactory(); $filterChain = new Filter\FilterChain(); - $pluginManager = new Filter\FilterPluginManager(); + $pluginManager = new Filter\FilterPluginManager($smMock); $filterChain->setPluginManager($pluginManager); $factory->setDefaultFilterChain($filterChain); $input = $factory->createInput([ @@ -299,9 +319,10 @@ public function testFactoryUsesComposedFilterChainWhenCreatingNewInputObjects() public function testFactoryUsesComposedValidatorChainWhenCreatingNewInputObjects() { + $smMock = $this->getMock(ContainerInterface::class); $factory = $this->createDefaultFactory(); $validatorChain = new Validator\ValidatorChain(); - $validatorPlugins = new Validator\ValidatorPluginManager(); + $validatorPlugins = new Validator\ValidatorPluginManager($smMock); $validatorChain->setPluginManager($validatorPlugins); $factory->setDefaultValidatorChain($validatorChain); $input = $factory->createInput([ @@ -315,9 +336,10 @@ public function testFactoryUsesComposedValidatorChainWhenCreatingNewInputObjects public function testFactoryInjectsComposedFilterAndValidatorChainsIntoInputObjectsWhenCreatingNewInputFilterObjects() { + $smMock = $this->getMock(ContainerInterface::class); $factory = $this->createDefaultFactory(); - $filterPlugins = new Filter\FilterPluginManager(); - $validatorPlugins = new Validator\ValidatorPluginManager(); + $filterPlugins = new Filter\FilterPluginManager($smMock); + $validatorPlugins = new Validator\ValidatorPluginManager($smMock); $filterChain = new Filter\FilterChain(); $validatorChain = new Validator\ValidatorChain(); $filterChain->setPluginManager($filterPlugins); @@ -348,11 +370,11 @@ public function testFactoryWillCreateInputWithSuggestedFilters() 'name' => 'foo', 'filters' => [ [ - 'name' => 'string_trim', + 'name' => Filter\StringTrim::class ], $htmlEntities, [ - 'name' => 'string_to_lower', + 'name' => Filter\StringToLower::class, 'options' => [ 'encoding' => 'ISO-8859-1', ], @@ -390,11 +412,11 @@ public function testFactoryWillCreateInputWithSuggestedValidators() 'name' => 'foo', 'validators' => [ [ - 'name' => 'not_empty', + 'name' => Validator\NotEmpty::class, ], $digits, [ - 'name' => 'string_length', + 'name' => Validator\StringLength::class, 'options' => [ 'min' => 3, 'max' => 5, @@ -509,10 +531,10 @@ public function testFactoryWillCreateInputFilterAndAllInputObjectsFromGivenConfi 'required' => false, 'validators' => [ [ - 'name' => 'not_empty', + 'name' => Validator\NotEmpty::class, ], [ - 'name' => 'string_length', + 'name' => Validator\StringLength::class, 'options' => [ 'min' => 3, 'max' => 5, @@ -524,10 +546,10 @@ public function testFactoryWillCreateInputFilterAndAllInputObjectsFromGivenConfi 'allow_empty' => true, 'filters' => [ [ - 'name' => 'string_trim', + 'name' => Filter\StringTrim::class, ], [ - 'name' => 'string_to_lower', + 'name' => Filter\StringToLower::class, 'options' => [ 'encoding' => 'ISO-8859-1', ], @@ -541,10 +563,10 @@ public function testFactoryWillCreateInputFilterAndAllInputObjectsFromGivenConfi 'required' => false, 'validators' => [ [ - 'name' => 'not_empty', + 'name' => Validator\NotEmpty::class, ], [ - 'name' => 'string_length', + 'name' => Validator\StringLength::class, 'options' => [ 'min' => 3, 'max' => 5, @@ -556,10 +578,10 @@ public function testFactoryWillCreateInputFilterAndAllInputObjectsFromGivenConfi 'allow_empty' => true, 'filters' => [ [ - 'name' => 'string_trim', + 'name' => Filter\StringTrim::class ], [ - 'name' => 'string_to_lower', + 'name' => Filter\StringToLower::class, 'options' => [ 'encoding' => 'ISO-8859-1', ], @@ -689,15 +711,15 @@ public function testFactoryWillNotGetPrioritySetting() 'name' => 'foo', 'filters' => [ [ - 'name' => 'string_trim', + 'name' => 'StringTrim', 'priority' => Filter\FilterChain::DEFAULT_PRIORITY - 1 // 999 ], [ - 'name' => 'string_to_upper', + 'name' => 'StringToUpper', 'priority' => Filter\FilterChain::DEFAULT_PRIORITY + 1 //1001 ], [ - 'name' => 'string_to_lower', // default priority 1000 + 'name' => 'StringToLower' // default priority 1000 ] ] ]); @@ -767,13 +789,11 @@ public function testCanSetInputErrorMessage() public function testSetInputFilterManagerWithServiceManager() { - $inputFilterManager = new InputFilterPluginManager; $serviceManager = new ServiceManager\ServiceManager; - $serviceManager->setService('ValidatorManager', new Validator\ValidatorPluginManager); - $serviceManager->setService('FilterManager', new Filter\FilterPluginManager); - $inputFilterManager->setServiceLocator($serviceManager); - $factory = $this->createDefaultFactory(); - $factory->setInputFilterManager($inputFilterManager); + $inputFilterManager = new InputFilterPluginManager($serviceManager); + $serviceManager->setService('ValidatorManager', new Validator\ValidatorPluginManager($serviceManager)); + $serviceManager->setService('FilterManager', new Filter\FilterPluginManager($serviceManager)); + $factory = new Factory($inputFilterManager); $this->assertInstanceOf( Validator\ValidatorPluginManager::class, $factory->getDefaultValidatorChain()->getPluginManager() @@ -786,15 +806,16 @@ public function testSetInputFilterManagerWithServiceManager() public function testSetInputFilterManagerWithoutServiceManager() { - $inputFilterManager = new InputFilterPluginManager(); - $factory = $this->createDefaultFactory(); - $factory->setInputFilterManager($inputFilterManager); + $smMock = $this->getMock(ContainerInterface::class); + $inputFilterManager = new InputFilterPluginManager($smMock); + $factory = new Factory($inputFilterManager); $this->assertSame($inputFilterManager, $factory->getInputFilterManager()); } public function testSetInputFilterManagerOnConstruct() { - $inputFilterManager = new InputFilterPluginManager(); + $smMock = $this->getMock(ContainerInterface::class); + $inputFilterManager = new InputFilterPluginManager($smMock); $factory = new Factory($inputFilterManager); $this->assertSame($inputFilterManager, $factory->getInputFilterManager()); } @@ -885,10 +906,10 @@ public function testCanCreateInputFilterFromProvider() public function testSuggestedTypeMayBePluginNameInInputFilterPluginManager() { - $factory = $this->createDefaultFactory(); - $pluginManager = new InputFilterPluginManager(); + $serviceManager = new ServiceManager\ServiceManager(); + $pluginManager = new InputFilterPluginManager($serviceManager); $pluginManager->setService('bar', new Input('bar')); - $factory->setInputFilterManager($pluginManager); + $factory = new Factory($pluginManager); $input = $factory->createInput([ 'type' => 'bar' @@ -898,9 +919,9 @@ public function testSuggestedTypeMayBePluginNameInInputFilterPluginManager() public function testInputFromPluginManagerMayBeFurtherConfiguredWithSpec() { - $factory = $this->createDefaultFactory(); - $pluginManager = new InputFilterPluginManager(); + $pluginManager = new InputFilterPluginManager(new ServiceManager\ServiceManager()); $pluginManager->setService('bar', $barInput = new Input('bar')); + $factory = new Factory($pluginManager); $this->assertTrue($barInput->isRequired()); $factory->setInputFilterManager($pluginManager); @@ -932,7 +953,10 @@ protected function createDefaultFactory() protected function createInputFilterPluginManagerMockForPlugin($pluginName, $pluginValue) { /** @var InputFilterPluginManager|MockObject $pluginManager */ - $pluginManager = $this->getMock(InputFilterPluginManager::class); + $pluginManager = $this->getMockBuilder(InputFilterPluginManager::class) + ->disableOriginalConstructor() + ->getMock(); + $pluginManager->expects($this->atLeastOnce()) ->method('has') ->with($pluginName) diff --git a/test/InputFilterAbstractServiceFactoryTest.php b/test/InputFilterAbstractServiceFactoryTest.php index 9b081f25..30129807 100644 --- a/test/InputFilterAbstractServiceFactoryTest.php +++ b/test/InputFilterAbstractServiceFactoryTest.php @@ -36,8 +36,7 @@ class InputFilterAbstractServiceFactoryTest extends TestCase public function setUp() { $this->services = new ServiceManager(); - $this->filters = new InputFilterPluginManager(); - $this->filters->setServiceLocator($this->services); + $this->filters = new InputFilterPluginManager($this->services); $this->services->setService('InputFilterManager', $this->filters); $this->factory = new InputFilterAbstractServiceFactory(); @@ -45,42 +44,53 @@ public function setUp() public function testCannotCreateServiceIfNoConfigServicePresent() { - $this->assertFalse($this->factory->canCreateServiceWithName($this->filters, 'filter', 'filter')); + $this->assertFalse($this->factory->canCreate($this->getCompatContainer(), 'filter')); + // v2 + $this->assertFalse($this->factory->canCreateServiceWithName($this->getCompatContainer(), 'filter', 'filter')); } public function testCannotCreateServiceIfConfigServiceDoesNotHaveInputFiltersConfiguration() { - $this->services->setService('Config', []); - $this->assertFalse($this->factory->canCreateServiceWithName($this->filters, 'filter', 'filter')); + $this->services->setService('config', []); + $this->assertFalse($this->factory->canCreate($this->getCompatContainer(), 'filter')); + // v2 + $this->assertFalse($this->factory->canCreateServiceWithName($this->getCompatContainer(), 'filter', 'filter')); } public function testCannotCreateServiceIfConfigInputFiltersDoesNotContainMatchingServiceName() { - $this->services->setService('Config', [ + $this->services->setService('config', [ 'input_filter_specs' => [], ]); - $this->assertFalse($this->factory->canCreateServiceWithName($this->filters, 'filter', 'filter')); + $this->assertFalse($this->factory->canCreate($this->getCompatContainer(), 'filter')); + // v2 + $this->assertFalse($this->factory->canCreateServiceWithName($this->getCompatContainer(), 'filter', 'filter')); } public function testCanCreateServiceIfConfigInputFiltersContainsMatchingServiceName() { - $this->services->setService('Config', [ + $this->services->setService('config', [ 'input_filter_specs' => [ 'filter' => [], ], ]); - $this->assertTrue($this->factory->canCreateServiceWithName($this->filters, 'filter', 'filter')); + $this->assertTrue($this->factory->canCreate($this->getCompatContainer(), 'filter')); + // v2 + $this->assertTrue($this->factory->canCreateServiceWithName($this->getCompatContainer(), 'filter', 'filter')); } public function testCreatesInputFilterInstance() { - $this->services->setService('Config', [ + $this->services->setService('config', [ 'input_filter_specs' => [ 'filter' => [], ], ]); - $filter = $this->factory->createServiceWithName($this->filters, 'filter', 'filter'); + $filter = $this->factory->__invoke($this->getCompatContainer(), 'filter'); $this->assertInstanceOf(InputFilterInterface::class, $filter); + // v2 + $v2filter = $this->factory->createServiceWithName($this->getCompatContainer(), 'filter', 'filter'); + $this->assertEquals($filter, $v2filter); } /** @@ -88,19 +98,19 @@ public function testCreatesInputFilterInstance() */ public function testUsesConfiguredValidationAndFilterManagerServicesWhenCreatingInputFilter() { - $filters = new FilterPluginManager(); + $filters = new FilterPluginManager($this->services); $filter = function ($value) { }; $filters->setService('foo', $filter); - $validators = new ValidatorPluginManager(); + $validators = new ValidatorPluginManager($this->services); /** @var ValidatorInterface|MockObject $validator */ $validator = $this->getMock(ValidatorInterface::class); $validators->setService('foo', $validator); $this->services->setService('FilterManager', $filters); $this->services->setService('ValidatorManager', $validators); - $this->services->setService('Config', [ + $this->services->setService('config', [ 'input_filter_specs' => [ 'filter' => [ 'input' => [ @@ -117,8 +127,12 @@ public function testUsesConfiguredValidationAndFilterManagerServicesWhenCreating ], ]); - $inputFilter = $this->factory->createServiceWithName($this->filters, 'filter', 'filter'); + + $inputFilter = $this->factory->__invoke($this->getCompatContainer(), 'filter'); $this->assertTrue($inputFilter->has('input')); + // v2 + $v2InputFilter = $this->factory->createServiceWithName($this->getCompatContainer(), 'filter', 'filter'); + $this->assertEquals($inputFilter, $v2InputFilter); $input = $inputFilter->get('input'); @@ -128,7 +142,7 @@ public function testUsesConfiguredValidationAndFilterManagerServicesWhenCreating $this->assertSame($filter, $filterChain->plugin('foo')); $this->assertEquals(1, count($filterChain)); - $validatorChain = $input->getvalidatorChain(); + $validatorChain = $input->getValidatorChain(); $this->assertSame($validators, $validatorChain->getPluginManager()); $this->assertEquals(1, count($validatorChain)); $this->assertSame($validator, $validatorChain->plugin('foo')); @@ -137,19 +151,7 @@ public function testUsesConfiguredValidationAndFilterManagerServicesWhenCreating public function testRetrieveInputFilterFromInputFilterPluginManager() { - $filters = new FilterPluginManager(); - $filter = function ($value) { - }; - $filters->setService('foo', $filter); - - $validators = new ValidatorPluginManager(); - /** @var ValidatorInterface|MockObject $validator */ - $validator = $this->getMock(ValidatorInterface::class); - $validators->setService('foo', $validator); - - $this->services->setService('FilterManager', $filters); - $this->services->setService('ValidatorManager', $validators); - $this->services->setService('Config', [ + $this->services->setService('config', [ 'input_filter_specs' => [ 'foobar' => [ 'input' => [ @@ -165,9 +167,37 @@ public function testRetrieveInputFilterFromInputFilterPluginManager() ], ], ]); + $validators = new ValidatorPluginManager($this->services); + /** @var ValidatorInterface|MockObject $validator */ + $validator = $this->getMock(ValidatorInterface::class); + $this->services->setService('ValidatorManager', $validators); + $validators->setService('foo', $validator); + + $filters = new FilterPluginManager($this->services); + $filter = function ($value) { + }; + $filters->setService('foo', $filter); + + $this->services->setService('FilterManager', $filters); $this->services->get('InputFilterManager')->addAbstractFactory(InputFilterAbstractServiceFactory::class); $inputFilter = $this->services->get('InputFilterManager')->get('foobar'); $this->assertInstanceOf(InputFilterInterface::class, $inputFilter); } + + /** + * Returns appropriate instance to pass to `canCreate()` et al depending on SM version + * + * v3 passes the 'creationContext' (ie the root SM) to the AbstractFactory, whereas v2 passes the PluginManager + */ + protected function getCompatContainer() + { + if (method_exists($this->services, 'configure')) { + // v3 + return $this->services; + } else { + // v2 + return $this->filters; + } + } } diff --git a/test/InputFilterPluginManagerTest.php b/test/InputFilterPluginManagerTest.php index 8314e283..e430f305 100644 --- a/test/InputFilterPluginManagerTest.php +++ b/test/InputFilterPluginManagerTest.php @@ -18,7 +18,9 @@ use Zend\InputFilter\InputFilterPluginManager; use Zend\InputFilter\InputInterface; use Zend\ServiceManager\AbstractPluginManager; +use Zend\ServiceManager\Exception\InvalidServiceException; use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\ServiceManager; use Zend\Stdlib\InitializableInterface; use Zend\Validator\ValidatorPluginManager; @@ -32,9 +34,15 @@ class InputFilterPluginManagerTest extends \PHPUnit_Framework_TestCase */ protected $manager; + /** + * @var ServiceManager + */ + protected $services; + public function setUp() { - $this->manager = new InputFilterPluginManager(); + $this->services = new ServiceManager(); + $this->manager = new InputFilterPluginManager($this->services); } public function testIsASubclassOfAbstractPluginManager() @@ -50,7 +58,7 @@ public function testIsNotSharedByDefault() public function testRegisteringInvalidElementRaisesException() { $this->setExpectedException( - RuntimeException::class, + $this->getServiceNotFoundException(), 'must implement Zend\InputFilter\InputFilterInterface or Zend\InputFilter\InputInterface' ); $this->manager->setService('test', $this); @@ -59,7 +67,7 @@ public function testRegisteringInvalidElementRaisesException() public function testLoadingInvalidElementRaisesException() { $this->manager->setInvokableClass('test', get_class($this)); - $this->setExpectedException(RuntimeException::class); + $this->setExpectedException($this->getServiceNotFoundException()); $this->manager->get('test'); } @@ -84,8 +92,6 @@ public function testDefaultInvokableClasses($alias, $expectedInstance) public function testInputFilterInvokableClassSMDependenciesArePopulatedWithoutServiceLocator() { - $this->assertNull($this->manager->getServiceLocator(), 'Plugin manager is expected to no have a service locator'); - /** @var InputFilter $service */ $service = $this->manager->get('inputfilter'); @@ -99,21 +105,15 @@ public function testInputFilterInvokableClassSMDependenciesArePopulatedWithoutSe public function testInputFilterInvokableClassSMDependenciesArePopulatedWithServiceLocator() { - $filterManager = $this->getMock(FilterPluginManager::class); - $validatorManager = $this->getMock(ValidatorPluginManager::class); + $filterManager = $this->getMockBuilder(FilterPluginManager::class) + ->disableOriginalConstructor() + ->getMock(); + $validatorManager = $this->getMockBuilder(ValidatorPluginManager::class) + ->disableOriginalConstructor() + ->getMock(); - $serviceLocator = $this->createServiceLocatorInterfaceMock(); - $serviceLocator->method('get') - ->willReturnMap( - [ - ['FilterManager', $filterManager], - ['ValidatorManager', $validatorManager], - ] - ) - ; - - $this->manager->setServiceLocator($serviceLocator); - $this->assertSame($serviceLocator, $this->manager->getServiceLocator(), 'getServiceLocator() value not match'); + $this->services->setService('FilterManager', $filterManager); + $this->services->setService('ValidatorManager', $validatorManager); /** @var InputFilter $service */ $service = $this->manager->get('inputfilter'); @@ -211,4 +211,12 @@ protected function createServiceLocatorInterfaceMock() return $serviceLocator; } + + protected function getServiceNotFoundException() + { + if (method_exists($this->manager, 'configure')) { + return InvalidServiceException::class; + } + return RuntimeException::class; + } } diff --git a/test/MigrationTest.php b/test/MigrationTest.php new file mode 100644 index 00000000..b91e332f --- /dev/null +++ b/test/MigrationTest.php @@ -0,0 +1,42 @@ +markTestSkipped("InputFilterPluginManager accepts multiple instances"); + } + + protected function getPluginManager() + { + return new InputFilterPluginManager(new ServiceManager()); + } + + protected function getV2InvalidPluginException() + { + return RuntimeException::class; + } + + protected function getInstanceOf() + { + // InputFilterManager accepts multiple instance types + return; + } +} From 7796548e83a555519166c857008075ee12eeec95 Mon Sep 17 00:00:00 2001 From: Matt Kynaston Date: Sat, 13 Feb 2016 17:51:11 +0000 Subject: [PATCH 2/9] Giving --prefer-lowest a try. v2 should test under 5.5, v3 under 5.6 --- .travis.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index c30dde09..cc36c05e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,15 +17,10 @@ matrix: - php: 5.5 env: - EXECUTE_CS_CHECK=true - - php: 5.5 - env: - - SERVICE_MANAGER_VERSION="^2.7.5" + - SERVICE_MANAGER_V2=true - php: 5.6 env: - EXECUTE_TEST_COVERALLS=true - - php: 5.6 - env: - - SERVICE_MANAGER_VERSION="^2.7.5" - php: 7 - php: hhvm allow_failures: @@ -41,14 +36,13 @@ before_install: - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then composer require --dev --no-update satooshi/php-coveralls ; fi install: - - travis_retry composer install --no-interaction --ignore-platform-reqs + - if [[ $SERVICE_MANAGER_V2 != 'true' ]]; then travis_retry composer install --no-interaction --ignore-platform-reqs ; fi + - if [[ $SERVICE_MANAGER_V2 == 'true' ]]; then travis_retry composer update --no-interaction --ignore-platform-reqs --prefer-lowest ; fi script: - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/phpunit --coverage-clover clover.xml ; fi - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then ./vendor/bin/phpunit ; fi - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run ; fi - - if [[ $SERVICE_MANAGER_VERSION != '' ]]; then composer require --no-update "zendframework/zend-servicemanager:$SERVICE_MANAGER_VERSION" ; fi - - if [[ $SERVICE_MANAGER_VERSION == '' ]]; then composer require --no-update "zendframework/zend-servicemanager:^3.0.3" ; fi after_script: - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/coveralls ; fi From 310470c4741501ba0890ec79653d77eb9230f7d2 Mon Sep 17 00:00:00 2001 From: Matt Kynaston Date: Wed, 17 Feb 2016 22:53:21 +0000 Subject: [PATCH 3/9] Try travis now zend-validator-2.6 is there --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 90d613d0..1cf43f09 100644 --- a/composer.json +++ b/composer.json @@ -40,3 +40,4 @@ } } } + From 86e6c2ccf7bb995f78a13bdb42d065ce4e1fa519 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 18 Feb 2016 12:26:08 -0600 Subject: [PATCH 4/9] Run a job per SM version per PHP version - to ensure no regressions between PHP versions as well. --- .travis.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cc36c05e..faac7d4b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,12 +17,23 @@ matrix: - php: 5.5 env: - EXECUTE_CS_CHECK=true - - SERVICE_MANAGER_V2=true + - php: 5.5 + env: + - SERVICE_MANAGER_VERSION="^2.7.5" - php: 5.6 env: - EXECUTE_TEST_COVERALLS=true + - php: 5.6 + env: + - SERVICE_MANAGER_VERSION="^2.7.5" - php: 7 - - php: hhvm + - php: 7 + env: + - SERVICE_MANAGER_VERSION="^2.7.5" + - php: hhvm + - php: hhvm + env: + - SERVICE_MANAGER_VERSION="^2.7.5" allow_failures: - php: 7 @@ -34,6 +45,8 @@ before_install: - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi - composer self-update - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then composer require --dev --no-update satooshi/php-coveralls ; fi + - if [[ $SERVICE_MANAGER_VERSION != '' ]]; then composer require --dev --no-update "zendframework/zend-servicemanager:$SERVICE_MANAGER_VERSION" ; fi + - if [[ $SERVICE_MANAGER_VERSION == '' ]]; then composer require --dev --no-update "zendframework/zend-servicemanager:^3.0.3" ; fi install: - if [[ $SERVICE_MANAGER_V2 != 'true' ]]; then travis_retry composer install --no-interaction --ignore-platform-reqs ; fi From d26c4b41b3fcc51ce90bd107a44c84c992dfd102 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 18 Feb 2016 12:27:39 -0600 Subject: [PATCH 5/9] Minor version updates - ensure compat with both PHP 5.5+ and 7.0+ - Use `^2.6` (no maintenance version), as we don't need to get more specific at this time. - remove empty line at end of file --- composer.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 1cf43f09..ef42126c 100644 --- a/composer.json +++ b/composer.json @@ -13,9 +13,9 @@ } }, "require": { - "php": ">=5.5", - "zendframework/zend-filter": "^2.6.0", - "zendframework/zend-validator": "^2.6.0", + "php": "^5.5 || ^7.0", + "zendframework/zend-filter": "^2.6", + "zendframework/zend-validator": "^2.6", "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { @@ -40,4 +40,3 @@ } } } - From 656001c418d0ecc143687bddfc82f8e077f5cfff Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 18 Feb 2016 12:38:06 -0600 Subject: [PATCH 6/9] Documented and simplified logic of populateFactoryPluginManagers - Created a ternary from the original if/else, making the logic more compact. - Added the method docblock. --- src/InputFilterPluginManager.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/InputFilterPluginManager.php b/src/InputFilterPluginManager.php index bd6340c6..a658260d 100644 --- a/src/InputFilterPluginManager.php +++ b/src/InputFilterPluginManager.php @@ -95,19 +95,22 @@ public function populateFactory($first, $second) } } + /** + * Populate the filter and validator managers for the default filter/validator chains. + * + * @param Factory $factory + * @return void + */ public function populateFactoryPluginManagers(Factory $factory) { - if (property_exists($this, 'creationContext')) { - // v3 - $container = $this->creationContext; - } else { - // v2 - $container = $this->serviceLocator; - } + $container = property_exists($this, 'creationContext') + ? $this->creationContext // v3 + : $this->serviceLocator; // v2 if ($container && $container->has('FilterManager')) { $factory->getDefaultFilterChain()->setPluginManager($container->get('FilterManager')); } + if ($container && $container->has('ValidatorManager')) { $factory->getDefaultValidatorChain()->setPluginManager($container->get('ValidatorManager')); } From ec011db485cd046ad872043ff80182165e13ed7f Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 18 Feb 2016 13:06:29 -0600 Subject: [PATCH 7/9] Incorporate feedback for InputFilterAbstractServiceFactory - Move v2 checks into v2-specific methods of abstract factory. - Use provided `$services` argument when lazy-instantiating filter and validator plugin managers. - For abstract factory tests, vary methods tested based on service manager version. --- src/InputFilterAbstractServiceFactory.php | 37 ++++---- .../InputFilterAbstractServiceFactoryTest.php | 92 ++++++++++++++----- 2 files changed, 89 insertions(+), 40 deletions(-) diff --git a/src/InputFilterAbstractServiceFactory.php b/src/InputFilterAbstractServiceFactory.php index ef551ed3..e91442d2 100644 --- a/src/InputFilterAbstractServiceFactory.php +++ b/src/InputFilterAbstractServiceFactory.php @@ -13,7 +13,6 @@ use Zend\Filter\FilterPluginManager; use Zend\ServiceManager\AbstractFactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; -use Zend\ServiceManager\ServiceManager; use Zend\Validator\ValidatorPluginManager; class InputFilterAbstractServiceFactory implements AbstractFactoryInterface @@ -23,7 +22,6 @@ class InputFilterAbstractServiceFactory implements AbstractFactoryInterface */ protected $factory; - /** * @param ContainerInterface $services * @param string $rName @@ -32,14 +30,8 @@ class InputFilterAbstractServiceFactory implements AbstractFactoryInterface */ public function __invoke(ContainerInterface $services, $rName, array $options = null) { - // v2 - get parent service manager - if (! method_exists($services, 'configure')) { - $services = $services->getServiceLocator(); - } - $allConfig = $services->get('config'); $config = $allConfig['input_filter_specs'][$rName]; - $factory = $this->getInputFilterFactory($services); return $factory->createInputFilter($config); @@ -54,11 +46,6 @@ public function __invoke(ContainerInterface $services, $rName, array $options = */ public function canCreate(ContainerInterface $services, $rName) { - // v2 - get parent service manager - if (! method_exists($services, 'configure')) { - $services = $services->getServiceLocator(); - } - if (! $services->has('config')) { return false; } @@ -83,7 +70,15 @@ public function canCreate(ContainerInterface $services, $rName) */ public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) { - return $this->canCreate($serviceLocator, $requestedName); + // v2 => need to get parent service locator + $services = $serviceLocator->getServiceLocator(); + + // No parent locator => cannot create service. + if (! $services) { + return false; + } + + return $this->canCreate($services, $requestedName); } /** @@ -94,7 +89,15 @@ public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator */ public function createServiceWithName(ServiceLocatorInterface $inputFilters, $cName, $rName) { - return $this($inputFilters, $rName); + // v2 => need to get parent service locator + $services = $inputFilters->getServiceLocator(); + + // No parent locator => cannot create service. + if (! $services) { + return false; + } + + return $this($services, $rName); } /** @@ -128,7 +131,7 @@ protected function getFilterPluginManager(ServiceLocatorInterface $services) return $services->get('FilterManager'); } - return new FilterPluginManager(new ServiceManager()); + return new FilterPluginManager($services); } /** @@ -141,6 +144,6 @@ protected function getValidatorPluginManager(ServiceLocatorInterface $services) return $services->get('ValidatorManager'); } - return new ValidatorPluginManager(new ServiceManager()); + return new ValidatorPluginManager($services); } } diff --git a/test/InputFilterAbstractServiceFactoryTest.php b/test/InputFilterAbstractServiceFactoryTest.php index 30129807..de133421 100644 --- a/test/InputFilterAbstractServiceFactoryTest.php +++ b/test/InputFilterAbstractServiceFactoryTest.php @@ -24,13 +24,19 @@ */ class InputFilterAbstractServiceFactoryTest extends TestCase { - /** @var ServiceManager */ + /** + * @var ServiceManager + */ protected $services; - /** @var InputFilterPluginManager */ + /** + * @var InputFilterPluginManager + */ protected $filters; - /** @var InputFilterAbstractServiceFactory */ + /** + * @var InputFilterAbstractServiceFactory + */ protected $factory; public function setUp() @@ -44,17 +50,31 @@ public function setUp() public function testCannotCreateServiceIfNoConfigServicePresent() { - $this->assertFalse($this->factory->canCreate($this->getCompatContainer(), 'filter')); - // v2 - $this->assertFalse($this->factory->canCreateServiceWithName($this->getCompatContainer(), 'filter', 'filter')); + if (method_exists($this->services, 'configure')) { + // v3 + $method = 'canCreate'; + $args = [$this->getCompatContainer(), 'filter']; + } else { + // v2 + $method = 'canCreateServiceWithName'; + $args = [$this->getCompatContainer(), 'filter', 'filter']; + } + $this->assertFalse(call_user_func_array([$this->factory, $method], $args)); } public function testCannotCreateServiceIfConfigServiceDoesNotHaveInputFiltersConfiguration() { $this->services->setService('config', []); - $this->assertFalse($this->factory->canCreate($this->getCompatContainer(), 'filter')); - // v2 - $this->assertFalse($this->factory->canCreateServiceWithName($this->getCompatContainer(), 'filter', 'filter')); + if (method_exists($this->services, 'configure')) { + // v3 + $method = 'canCreate'; + $args = [$this->getCompatContainer(), 'filter']; + } else { + // v2 + $method = 'canCreateServiceWithName'; + $args = [$this->getCompatContainer(), 'filter', 'filter']; + } + $this->assertFalse(call_user_func_array([$this->factory, $method], $args)); } public function testCannotCreateServiceIfConfigInputFiltersDoesNotContainMatchingServiceName() @@ -62,9 +82,16 @@ public function testCannotCreateServiceIfConfigInputFiltersDoesNotContainMatchin $this->services->setService('config', [ 'input_filter_specs' => [], ]); - $this->assertFalse($this->factory->canCreate($this->getCompatContainer(), 'filter')); - // v2 - $this->assertFalse($this->factory->canCreateServiceWithName($this->getCompatContainer(), 'filter', 'filter')); + if (method_exists($this->services, 'configure')) { + // v3 + $method = 'canCreate'; + $args = [$this->getCompatContainer(), 'filter']; + } else { + // v2 + $method = 'canCreateServiceWithName'; + $args = [$this->getCompatContainer(), 'filter', 'filter']; + } + $this->assertFalse(call_user_func_array([$this->factory, $method], $args)); } public function testCanCreateServiceIfConfigInputFiltersContainsMatchingServiceName() @@ -74,9 +101,16 @@ public function testCanCreateServiceIfConfigInputFiltersContainsMatchingServiceN 'filter' => [], ], ]); - $this->assertTrue($this->factory->canCreate($this->getCompatContainer(), 'filter')); - // v2 - $this->assertTrue($this->factory->canCreateServiceWithName($this->getCompatContainer(), 'filter', 'filter')); + if (method_exists($this->services, 'configure')) { + // v3 + $method = 'canCreate'; + $args = [$this->getCompatContainer(), 'filter']; + } else { + // v2 + $method = 'canCreateServiceWithName'; + $args = [$this->getCompatContainer(), 'filter', 'filter']; + } + $this->assertTrue(call_user_func_array([$this->factory, $method], $args)); } public function testCreatesInputFilterInstance() @@ -86,11 +120,17 @@ public function testCreatesInputFilterInstance() 'filter' => [], ], ]); - $filter = $this->factory->__invoke($this->getCompatContainer(), 'filter'); + if (method_exists($this->services, 'configure')) { + // v3 + $method = '__invoke'; + $args = [$this->getCompatContainer(), 'filter']; + } else { + // v2 + $method = 'createServiceWithName'; + $args = [$this->getCompatContainer(), 'filter', 'filter']; + } + $filter = call_user_func_array([$this->factory, $method], $args); $this->assertInstanceOf(InputFilterInterface::class, $filter); - // v2 - $v2filter = $this->factory->createServiceWithName($this->getCompatContainer(), 'filter', 'filter'); - $this->assertEquals($filter, $v2filter); } /** @@ -128,11 +168,17 @@ public function testUsesConfiguredValidationAndFilterManagerServicesWhenCreating ]); - $inputFilter = $this->factory->__invoke($this->getCompatContainer(), 'filter'); + if (method_exists($this->services, 'configure')) { + // v3 + $method = '__invoke'; + $args = [$this->getCompatContainer(), 'filter']; + } else { + // v2 + $method = 'createServiceWithName'; + $args = [$this->getCompatContainer(), 'filter', 'filter']; + } + $inputFilter = call_user_func_array([$this->factory, $method], $args); $this->assertTrue($inputFilter->has('input')); - // v2 - $v2InputFilter = $this->factory->createServiceWithName($this->getCompatContainer(), 'filter', 'filter'); - $this->assertEquals($inputFilter, $v2InputFilter); $input = $inputFilter->get('input'); From 41c30e20d3b770693434e9bfaa1ed409194cb061 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 18 Feb 2016 13:17:17 -0600 Subject: [PATCH 8/9] Ensure input filter plugin manager is BC with v2 - Renamed `MigrationTest` to `InputFilterPluginManagerCompatibilityTest` (consistency with other components, and this is specifically for testing migration of the plugin manager). - Added tests to validate that the `InputFilterPluginManager` accepts no arguments and/or a `ConfigInterface` argument to the constructor when using zend-servicemanager v2. - Updated the `InputFilterPluginManager` constructor to mirror that of the 2.7 and 3.0 series of zend-servicemanager; it also populates the initializers prior to calling the parent constructor, allowing overriding. --- src/InputFilterPluginManager.php | 13 +++++----- ...tFilterPluginManagerCompatibilityTest.php} | 25 ++++++++++++++++++- 2 files changed, 31 insertions(+), 7 deletions(-) rename test/{MigrationTest.php => InputFilterPluginManagerCompatibilityTest.php} (53%) diff --git a/src/InputFilterPluginManager.php b/src/InputFilterPluginManager.php index a658260d..b2c8daf4 100644 --- a/src/InputFilterPluginManager.php +++ b/src/InputFilterPluginManager.php @@ -62,15 +62,16 @@ class InputFilterPluginManager extends AbstractPluginManager */ protected $shareByDefault = false; - /** - * @param ContainerInterface $parentLocator - * @param array $config + * @param null|\Zend\ServiceManager\ConfigInterface|ContainerInterface $configOrContainer + * For zend-servicemanager v2, null or a ConfigInterface instance are + * allowed; for v3, a ContainerInterface is expected. + * @param array $v3config Optional configuration array (zend-servicemanager v3 only) */ - public function __construct(ContainerInterface $parentLocator, array $config = []) + public function __construct($configOrContainer = null, array $v3config = []) { - parent::__construct($parentLocator, $config); - $this->addInitializer([$this, 'populateFactory']); + $this->initializers[] = [$this, 'populateFactory']; + parent::__construct($configOrContainer, $v3config); } /** diff --git a/test/MigrationTest.php b/test/InputFilterPluginManagerCompatibilityTest.php similarity index 53% rename from test/MigrationTest.php rename to test/InputFilterPluginManagerCompatibilityTest.php index b91e332f..32de3fb2 100644 --- a/test/MigrationTest.php +++ b/test/InputFilterPluginManagerCompatibilityTest.php @@ -12,10 +12,11 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\InputFilter\Exception\RuntimeException; use Zend\InputFilter\InputFilterPluginManager; +use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; use Zend\ServiceManager\Test\CommonPluginManagerTrait; -class MigrationTest extends TestCase +class InputFilterPluginManagerCompatibilityTest extends TestCase { use CommonPluginManagerTrait; @@ -39,4 +40,26 @@ protected function getInstanceOf() // InputFilterManager accepts multiple instance types return; } + + public function testConstructorArgumentsAreOptionalUnderV2() + { + $plugins = $this->getPluginManager(); + if (method_exists($plugins, 'configure')) { + $this->markTestSkipped('zend-servicemanager v3 plugin managers require a container argument'); + } + + $plugins = new InputFilterPluginManager(); + $this->assertInstanceOf(InputFilterPluginManager::class, $plugins); + } + + public function testConstructorAllowsConfigInstanceAsFirstArgumentUnderV2() + { + $plugins = $this->getPluginManager(); + if (method_exists($plugins, 'configure')) { + $this->markTestSkipped('zend-servicemanager v3 plugin managers require a container argument'); + } + + $plugins = new InputFilterPluginManager(new Config([])); + $this->assertInstanceOf(InputFilterPluginManager::class, $plugins); + } } From 598e20d7ddd352302f4151bdc033d321cb0b6259 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 18 Feb 2016 13:21:08 -0600 Subject: [PATCH 9/9] Removed `shareByDefault()` implementation From what I can tell, it was added for purposes of testing; I updated the test to use `assertAttributeSame`, varying the property to test against based on SM version. --- src/InputFilterPluginManager.php | 5 ----- test/InputFilterPluginManagerTest.php | 6 +++++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/InputFilterPluginManager.php b/src/InputFilterPluginManager.php index b2c8daf4..c9333178 100644 --- a/src/InputFilterPluginManager.php +++ b/src/InputFilterPluginManager.php @@ -158,9 +158,4 @@ public function validatePlugin($plugin) throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e); } } - - public function shareByDefault() - { - return $this->sharedByDefault; - } } diff --git a/test/InputFilterPluginManagerTest.php b/test/InputFilterPluginManagerTest.php index e430f305..a0fdc812 100644 --- a/test/InputFilterPluginManagerTest.php +++ b/test/InputFilterPluginManagerTest.php @@ -52,7 +52,11 @@ public function testIsASubclassOfAbstractPluginManager() public function testIsNotSharedByDefault() { - $this->assertFalse($this->manager->shareByDefault()); + $property = method_exists($this->manager, 'configure') + ? 'sharedByDefault' // v3 + : 'shareByDefault'; // v2 + + $this->assertAttributeSame(false, $property, $this->manager); } public function testRegisteringInvalidElementRaisesException()