diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 7b123cf..62f28cb 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -266,7 +266,8 @@
getBodyParams
getBodyParams
-
+
+ $matches
$matches
$matches
$matches
diff --git a/src/ContentValidationListener.php b/src/ContentValidationListener.php
index 1094f51..8046352 100644
--- a/src/ContentValidationListener.php
+++ b/src/ContentValidationListener.php
@@ -221,7 +221,10 @@ public function onRoute(MvcEvent $e)
$inputFilter = $this->getInputFilter($inputFilterService);
- if ($isCollection && ! in_array($method, $this->methodsWithoutBodies)) {
+ if (
+ $isCollection && ! in_array($method, $this->methodsWithoutBodies)
+ && ! $inputFilter instanceof CollectionInputFilter
+ ) {
$collectionInputFilter = new CollectionInputFilter();
$collectionInputFilter->setInputFilter($inputFilter);
$inputFilter = $collectionInputFilter;
diff --git a/test/ContentValidationListenerTest.php b/test/ContentValidationListenerTest.php
index 2fbe4ba..e489cd7 100644
--- a/test/ContentValidationListenerTest.php
+++ b/test/ContentValidationListenerTest.php
@@ -2945,4 +2945,53 @@ public function testRemoveEmptyDataIsNotSetSoEmptyDataAreNotRemoved(): void
$dataParams->getBodyParams()
);
}
+
+ /**
+ * @dataProvider listMethods
+ */
+ public function testDoNotOverwriteCustomCollectionInputFilter(string $method): void
+ {
+ $services = new ServiceManager();
+
+ $customCollectionInputFilter = new TestAsset\CustomCollectionInputFilter();
+ $customCollectionInputFilter->setInputFilter(
+ [
+ 'foo' => [
+ 'name' => 'foo',
+ 'required' => false,
+ ],
+ ]
+ );
+
+ $services->setService(TestAsset\CustomCollectionInputFilter::class, $customCollectionInputFilter);
+ $listener = new ContentValidationListener(
+ [
+ 'Foo' => ["{$method}_COLLECTION" => TestAsset\CustomCollectionInputFilter::class],
+ ],
+ $services,
+ [
+ 'Foo' => 'foo_id',
+ ]
+ );
+
+ $request = new HttpRequest();
+ $request->setMethod($method);
+
+ $matches = $this->createRouteMatch(['controller' => 'Foo']);
+
+ $dataParams = new ParameterDataContainer();
+ $dataParams->setBodyParams([['foo' => '']]);
+
+ $event = new MvcEvent();
+ $event->setName('route');
+ $event->setRequest($request);
+ $event->setRouteMatch($matches);
+ $event->setParam('LaminasContentNegotiationParameterData', $dataParams);
+ // if ContentValidationListener overwrites CustomCollectionInputFilter with instance of CollectionInputFilter
+ // it sets CustomCollectionInputFilter to CollectionInputFilter::inputFilter property
+ // as a consequence it throws InvalidArgumentException in CollectionInputFilter::setData()
+ $this->assertNull($listener->onRoute($event));
+ $inputFilter = $event->getParam('Laminas\ApiTools\ContentValidation\InputFilter');
+ $this->assertInstanceOf(TestAsset\CustomCollectionInputFilter::class, $inputFilter);
+ }
}
diff --git a/test/TestAsset/CustomCollectionInputFilter.php b/test/TestAsset/CustomCollectionInputFilter.php
new file mode 100644
index 0000000..ebd7713
--- /dev/null
+++ b/test/TestAsset/CustomCollectionInputFilter.php
@@ -0,0 +1,18 @@
+