diff --git a/src/Node/Template.php b/src/Node/Template.php index b406069..43bd935 100644 --- a/src/Node/Template.php +++ b/src/Node/Template.php @@ -23,20 +23,14 @@ final class Template implements NodeInterface, AttributedInterface * @param list $nodes */ public function __construct( - public array $nodes = [] - ) { - } + public array $nodes = [], + ) {} public function setContext(?Context $context = null): void { $this->context = $context; } - public function getContext(): ?Context - { - return $this->context; - } - public function getIterator(): \Generator { yield 'nodes' => $this->nodes; diff --git a/src/Transform/Import/Bundle.php b/src/Transform/Import/Bundle.php index 4c54f2c..3003d24 100644 --- a/src/Transform/Import/Bundle.php +++ b/src/Transform/Import/Bundle.php @@ -22,7 +22,7 @@ final class Bundle implements ImportInterface public function __construct( private string $path, private ?string $prefix = null, - ?Context $context = null + ?Context $context = null, ) { $this->context = $context; } @@ -35,7 +35,11 @@ public function resolve(Builder $builder, string $name): ?Template $path = $name; if ($this->prefix !== null) { - $path = \substr($path, \strlen($this->prefix) + 1); + if (!TagHelper::hasPrefix($name, $this->prefix)) { + return null; + } + + $path = TagHelper::stripPrefix($path, $this->prefix); } /** @var ImportInterface $import */ diff --git a/src/Transform/Import/Directory.php b/src/Transform/Import/Directory.php index 43ab18b..dcd10ed 100644 --- a/src/Transform/Import/Directory.php +++ b/src/Transform/Import/Directory.php @@ -21,7 +21,7 @@ final class Directory implements ImportInterface public function __construct( public string $path, ?string $prefix, - ?Context $context = null + ?Context $context = null, ) { $this->prefix = $prefix ?? \substr($path, \strrpos($path, '/') + 1); $this->context = $context; @@ -29,7 +29,11 @@ public function __construct( public function resolve(Builder $builder, string $name): ?Template { - $path = \substr($name, \strlen((string) $this->prefix) + 1); + if (!TagHelper::hasPrefix($name, $this->prefix)) { + return null; + } + + $path = TagHelper::stripPrefix($name, $this->prefix); $path = \str_replace('.', DIRECTORY_SEPARATOR, $path); return $builder->load($this->path . DIRECTORY_SEPARATOR . $path); diff --git a/src/Transform/Import/TagHelper.php b/src/Transform/Import/TagHelper.php new file mode 100644 index 0000000..b4101ee --- /dev/null +++ b/src/Transform/Import/TagHelper.php @@ -0,0 +1,49 @@ +shouldReceive('load') + ->once() + ->with('path/to/dir') + ->andReturn(new Source('')); + + $builder = new Builder($loader); + + $builder->addVisitor( + new class implements VisitorInterface { + + public function enterNode(mixed $node, VisitorContext $ctx): mixed + { + $n = $ctx->getCurrentNode(); + if ($n instanceof Template) { + $import = m::mock(ImportInterface::class); + $import->shouldNotReceive('resolve'); + $n->setAttribute(ImportContext::class, [$import]); + } + + return $node; + } + + public function leaveNode(mixed $node, VisitorContext $ctx): mixed + { + return $node; + } + }, + ); + + self::assertNull( + $bundle->resolve($builder, $tag), + ); + } + + public static function correctNamespaceProvider(): iterable + { + yield ['test.span']; + yield ['test:span']; + yield ['test/span']; + } + + #[DataProvider('correctNamespaceProvider')] + public function testResolveTagWithCorrectNamespace(string $tag): void + { + $bundle = new Bundle('path/to/dir', 'test'); + $loader = m::mock(LoaderInterface::class); + + $loader + ->shouldReceive('load') + ->once() + ->with('path/to/dir') + ->andReturn(new Source('')); + + $builder = new Builder($loader); + $template = new Template(); + + $builder->addVisitor( + new class($builder, $template) implements VisitorInterface { + public function __construct( + private readonly Builder $builder, + private readonly Template $template, + ) {} + + public function enterNode(mixed $node, VisitorContext $ctx): mixed + { + $n = $ctx->getCurrentNode(); + if ($n instanceof Template) { + $import = m::mock(ImportInterface::class); + $import + ->shouldReceive('resolve') + ->once() + ->with($this->builder, 'span') + ->andReturn($this->template); + $n->setAttribute(ImportContext::class, [$import]); + } + + return $node; + } + + public function leaveNode(mixed $node, VisitorContext $ctx): mixed + { + return $node; + } + }, + ); + + self::assertSame( + $template, + $bundle->resolve($builder, $tag), + ); + } +} diff --git a/tests/Transform/Import/DirectoryTest.php b/tests/Transform/Import/DirectoryTest.php new file mode 100644 index 0000000..cdbdfe9 --- /dev/null +++ b/tests/Transform/Import/DirectoryTest.php @@ -0,0 +1,63 @@ +resolve(new Builder($loader), $tag), + ); + } + + public static function correctNamespaceProvider(): iterable + { + yield ['test.span']; + yield ['test:span']; + yield ['test/span']; + } + + #[DataProvider('correctNamespaceProvider')] + public function testResolveTagWithCorrectNamespace(string $tag): void + { + $directory = new Directory('path/to/dir', 'test'); + + $loader = m::mock(LoaderInterface::class); + + $loader + ->shouldReceive('load') + ->once() + ->with($path = 'path/to/dir/span') + ->andReturn(new Source('')); + + $template = $directory->resolve(new Builder($loader), $tag); + + self::assertSame($path, $template->getContext()->getPath()); + } +} diff --git a/tests/Transform/Import/TagHelperTest.php b/tests/Transform/Import/TagHelperTest.php new file mode 100644 index 0000000..33b46e8 --- /dev/null +++ b/tests/Transform/Import/TagHelperTest.php @@ -0,0 +1,57 @@ +