Skip to content

Commit

Permalink
allow extractors to be array of extractors instead of single one
Browse files Browse the repository at this point in the history
  • Loading branch information
reinfi committed Sep 24, 2023
1 parent c6492e2 commit 97a8b3d
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 18 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
## Changelog
### v5.5.0
- extractor configuration can now contain an array of extractors
### v5.0.0
- deprecated PHP 7.3
- add PHP 8.1
Expand Down
48 changes: 30 additions & 18 deletions src/Service/Extractor/Factory/ExtractorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,7 @@ public function __invoke(ContainerInterface $container): ExtractorInterface
/** @var array $config */
$config = $container->get(ModuleConfig::class);

$extractors = [];

$extractorFromConfig = $this->extractorFromConfig($container, $config);

if ($extractorFromConfig instanceof ExtractorInterface) {
$extractors[] = $extractorFromConfig;
}
$extractors = $this->extractorsFromConfig($container, $config);

if (class_exists('Doctrine\Common\Annotations\AnnotationReader')) {
$extractors[] = $container->get(AnnotationExtractor::class);
Expand All @@ -41,27 +35,45 @@ public function __invoke(ContainerInterface $container): ExtractorInterface
return new ExtractorChain($extractors);
}

private function extractorFromConfig(
/**
* @return ExtractorInterface[]
*/
private function extractorsFromConfig(
ContainerInterface $container,
array $config
): ?ExtractorInterface {
): array {
$extractorConfiguration = $config['extractor'] ?? null;

if ($extractorConfiguration === null) {
return null;
return [];
}

$extractor = $container->get($extractorConfiguration);
if (! is_string($extractorConfiguration) && ! is_array($extractorConfiguration)) {
throw new InvalidArgumentException(
'Configuration property "extractor" must be of either string or array of strings'
);
}

if ($extractor instanceof ExtractorInterface) {
return $extractor;
if (is_string($extractorConfiguration)) {
$extractorConfiguration = [$extractorConfiguration];
}

throw new InvalidArgumentException(
sprintf(
'Configuration property "extractor" must be of type %s',
ExtractorInterface::class
)
return array_map(
function (string $extractorClassName) use ($container): ExtractorInterface {
$extractor = $container->get($extractorClassName);

if ($extractor instanceof ExtractorInterface) {
return $extractor;
}

throw new InvalidArgumentException(
sprintf(
'Configuration property "extractor" must be of type %s',
ExtractorInterface::class
)
);
},
$extractorConfiguration
);
}
}
51 changes: 51 additions & 0 deletions test/Unit/Service/Extractor/Factory/ExtractorFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,57 @@ public function testItReturnsExtractorDefinedInConfig(): void
self::assertContainsOnlyInstancesOf(ExtractorInterface::class, $chain);
}

public function testItReturnsArrayOfExtractorsDefinedInConfig(): void
{
$isPhp8OrAbove = version_compare(PHP_VERSION, '8.0.0') >= 0;

$moduleConfig = new Config([
'extractor' => [
YamlExtractor::class,
],
]);

$yamlExtractor = $this->prophesize(YamlExtractor::class);
$annotationExtractor = $this->prophesize(AnnotationExtractor::class);
$attributeExtractor = $this->prophesize(AttributeExtractor::class);
$container = $this->prophesize(ContainerInterface::class);

$container->get(ModuleConfig::class)
->willReturn($moduleConfig->toArray())
->shouldBeCalled();
$container->get(YamlExtractor::class)
->willReturn($yamlExtractor->reveal())
->shouldBeCalled();
$container->get(AnnotationExtractor::class)
->willReturn($annotationExtractor->reveal())
->shouldBeCalled();
$container->get(AttributeExtractor::class)
->willReturn($attributeExtractor->reveal())
->shouldBeCalledTimes($isPhp8OrAbove ? 1 : 0);

$factory = new ExtractorFactory();

$extractor = $factory($container->reveal());

self::assertInstanceOf(ExtractorChain::class, $extractor);

$reflectionClass = new ReflectionClass($extractor);
$chainProperty = $reflectionClass->getProperty('chain');
$chainProperty->setAccessible(true);

$chain = $chainProperty->getValue($extractor);

self::assertTrue(is_array($chain));

if ($isPhp8OrAbove) {
self::assertCount(3, $chain);
} else {
self::assertCount(2, $chain);
}

self::assertContainsOnlyInstancesOf(ExtractorInterface::class, $chain);
}

public function testItReturnsAnnotationExtractorIfNoneDefined(): void
{
$isPhp8OrAbove = version_compare(PHP_VERSION, '8.0.0') >= 0;
Expand Down

0 comments on commit 97a8b3d

Please sign in to comment.