diff --git a/packages/guides/src/Handlers/RenderDocumentCommand.php b/packages/guides/src/Handlers/RenderDocumentCommand.php index 4dd828c7b..dafc1fb24 100644 --- a/packages/guides/src/Handlers/RenderDocumentCommand.php +++ b/packages/guides/src/Handlers/RenderDocumentCommand.php @@ -27,6 +27,6 @@ public function getContext(): RenderContext public function getFileDestination(): string { - return $this->renderContext->getCurrentFileDestination(); + return $this->renderContext->getDestinationPath() . '/' . $this->renderContext->getCurrentFileName() . '.' . $this->renderContext->getOutputFormat(); } } diff --git a/packages/guides/src/NodeRenderers/Html/MenuEntryRenderer.php b/packages/guides/src/NodeRenderers/Html/MenuEntryRenderer.php index c28ea808f..343301f62 100644 --- a/packages/guides/src/NodeRenderers/Html/MenuEntryRenderer.php +++ b/packages/guides/src/NodeRenderers/Html/MenuEntryRenderer.php @@ -8,13 +8,16 @@ use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode; use phpDocumentor\Guides\Nodes\Node; use phpDocumentor\Guides\RenderContext; +use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; use phpDocumentor\Guides\TemplateRenderer; /** @implements NodeRenderer */ final class MenuEntryRenderer implements NodeRenderer { - public function __construct(private readonly TemplateRenderer $renderer) - { + public function __construct( + private readonly TemplateRenderer $renderer, + private readonly UrlGeneratorInterface $urlGenerator, + ) { } public function supports(Node $node): bool @@ -28,7 +31,7 @@ public function render(Node $node, RenderContext $renderContext): string $renderContext, 'body/menu/menu-item.html.twig', [ - 'url' => $renderContext->generateCanonicalOutputUrl($node->getUrl(), $node->getValue()->getId()), + 'url' => $this->urlGenerator->generateCanonicalOutputUrl($renderContext, $node->getUrl(), $node->getValue()->getId()), 'node' => $node, ], ); diff --git a/packages/guides/src/Parser.php b/packages/guides/src/Parser.php index 9b593dec0..7c5bb3ef6 100644 --- a/packages/guides/src/Parser.php +++ b/packages/guides/src/Parser.php @@ -50,10 +50,7 @@ public function registerStrategy(MarkupLanguageParser $strategy): void $this->parserStrategies[] = $strategy; } - /** - * @psalm-assert ParserContext $this->parserContext - * @psalm-assert Metas $this->metas - */ + /** @psalm-assert ParserContext $this->parserContext */ public function prepare( FilesystemInterface|null $origin, string $sourcePath, diff --git a/packages/guides/src/ReferenceResolvers/AnchorReferenceResolver.php b/packages/guides/src/ReferenceResolvers/AnchorReferenceResolver.php index 59adc059d..6d857efe0 100644 --- a/packages/guides/src/ReferenceResolvers/AnchorReferenceResolver.php +++ b/packages/guides/src/ReferenceResolvers/AnchorReferenceResolver.php @@ -6,6 +6,7 @@ use phpDocumentor\Guides\Nodes\Inline\LinkInlineNode; use phpDocumentor\Guides\RenderContext; +use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; /** * Resolves references with an anchor URL. @@ -18,6 +19,7 @@ class AnchorReferenceResolver implements ReferenceResolver public function __construct( private readonly AnchorReducer $anchorReducer, + private readonly UrlGeneratorInterface $urlGenerator, ) { } @@ -29,7 +31,7 @@ public function resolve(LinkInlineNode $node, RenderContext $renderContext): boo return false; } - $node->setUrl($renderContext->generateCanonicalOutputUrl($target->getDocumentPath(), $target->getAnchor())); + $node->setUrl($this->urlGenerator->generateCanonicalOutputUrl($renderContext, $target->getDocumentPath(), $target->getAnchor())); if ($node->getValue() === '') { $node->setValue($target->getTitle() ?? ''); } diff --git a/packages/guides/src/ReferenceResolvers/DocReferenceResolver.php b/packages/guides/src/ReferenceResolvers/DocReferenceResolver.php index b5d9ffc49..75114add1 100644 --- a/packages/guides/src/ReferenceResolvers/DocReferenceResolver.php +++ b/packages/guides/src/ReferenceResolvers/DocReferenceResolver.php @@ -7,11 +7,18 @@ use phpDocumentor\Guides\Nodes\Inline\DocReferenceNode; use phpDocumentor\Guides\Nodes\Inline\LinkInlineNode; use phpDocumentor\Guides\RenderContext; +use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; class DocReferenceResolver implements ReferenceResolver { public final const PRIORITY = 1000; + public function __construct( + private readonly UrlGeneratorInterface $urlGenerator, + private readonly DocumentNameResolverInterface $documentNameResolver, + ) { + } + public function resolve(LinkInlineNode $node, RenderContext $renderContext): bool { if (!$node instanceof DocReferenceNode) { @@ -19,13 +26,13 @@ public function resolve(LinkInlineNode $node, RenderContext $renderContext): boo } $document = $renderContext->getProjectNode()->findDocumentEntry( - $renderContext->canonicalUrl($node->getTargetReference()), + $this->documentNameResolver->canonicalUrl($renderContext->getDirName(), $node->getTargetReference()), ); if ($document === null) { return false; } - $node->setUrl($renderContext->generateCanonicalOutputUrl($document->getFile())); + $node->setUrl($this->urlGenerator->generateCanonicalOutputUrl($renderContext, $document->getFile())); if ($node->getValue() === '') { $node->setValue($document->getTitle()->toString()); } diff --git a/packages/guides/src/RenderContext.php b/packages/guides/src/RenderContext.php index 71836a513..cd300c90c 100644 --- a/packages/guides/src/RenderContext.php +++ b/packages/guides/src/RenderContext.php @@ -15,35 +15,28 @@ use Exception; use League\Flysystem\FilesystemInterface; +use LogicException; use phpDocumentor\Guides\Nodes\DocumentNode; use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode; use phpDocumentor\Guides\Nodes\Node; use phpDocumentor\Guides\Nodes\ProjectNode; -use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; -use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; use function dirname; -use function trim; class RenderContext { - private string $destinationPath; - private DocumentNode $document; /** @var DocumentNode[] */ private array $allDocuments; private function __construct( - private readonly string $outputFolder, - private readonly string $currentFileName, + private readonly string $destinationPath, + private readonly string|null $currentFileName, private readonly FilesystemInterface $origin, private readonly FilesystemInterface $destination, - private readonly UrlGeneratorInterface $urlGenerator, - private readonly DocumentNameResolverInterface $documentNameResolver, private readonly string $outputFormat, private readonly ProjectNode $projectNode, ) { - $this->destinationPath = trim($outputFolder, '/'); } /** @param DocumentNode[] $allDocumentNodes */ @@ -53,8 +46,6 @@ public static function forDocument( FilesystemInterface $origin, FilesystemInterface $destination, string $destinationPath, - UrlGeneratorInterface $urlGenerator, - DocumentNameResolverInterface $documentNameResolver, string $ouputFormat, ProjectNode $projectNode, ): self { @@ -63,8 +54,6 @@ public static function forDocument( $documentNode->getFilePath(), $origin, $destination, - $urlGenerator, - $documentNameResolver, $ouputFormat, $projectNode, ); @@ -75,6 +64,23 @@ public static function forDocument( return $self; } + public static function forProject( + ProjectNode $projectNode, + FilesystemInterface $origin, + FilesystemInterface $destination, + string $destinationPath, + string $ouputFormat, + ): self { + return new self( + $destinationPath, + null, + $origin, + $destination, + $ouputFormat, + $projectNode, + ); + } + /** * @param TType $default * @@ -94,37 +100,9 @@ public function getLink(string $name): string return $link ?? ''; } - public function canonicalUrl(string $url): string - { - return $this->documentNameResolver->canonicalUrl($this->getDirName(), $url); - } - - /** - * Generate a canonical output URL with the configured file extension and anchor - */ - public function generateCanonicalOutputUrl(string $linkedDocument, string|null $anchor = null): string - { - if ($this->projectNode->findDocumentEntry($linkedDocument) !== null) { - // todo: this is a hack, existing documents are expected to be handled like absolute links in some places - $linkedDocument = '/' . $linkedDocument; - } - - $canonicalUrl = $this->documentNameResolver->canonicalUrl( - $this->getDirName(), - $linkedDocument, - ); - - $fileUrl = $this->urlGenerator->createFileUrl($canonicalUrl, $this->outputFormat, $anchor); - - return $this->urlGenerator->generateInternalUrl( - $this, - $fileUrl, - ); - } - - private function getDirName(): string + public function getDirName(): string { - $dirname = dirname($this->currentFileName); + $dirname = dirname($this->getCurrentFileName()); if ($dirname === '.') { return ''; @@ -135,10 +113,14 @@ private function getDirName(): string public function getCurrentFileName(): string { + if ($this->currentFileName === null) { + throw new LogicException('Cannot get current file name when not rendering a document'); + } + return $this->currentFileName; } - /** @return array */ + /** @return array */ public function getLoggerInformation(): array { return [ @@ -153,7 +135,7 @@ public function getOrigin(): FilesystemInterface public function getCurrentDocumentEntry(): DocumentEntryNode|null { - return $this->projectNode->findDocumentEntry($this->currentFileName); + return $this->projectNode->findDocumentEntry($this->getCurrentFileName()); } public function getDestinationPath(): string @@ -161,21 +143,11 @@ public function getDestinationPath(): string return $this->destinationPath; } - public function setDestinationPath(string $path): void - { - $this->destinationPath = $path; - } - public function getDestination(): FilesystemInterface { return $this->destination; } - public function getCurrentFileDestination(): string - { - return $this->destinationPath . '/' . $this->currentFileName . '.' . $this->outputFormat; - } - public function getProjectNode(): ProjectNode { return $this->projectNode; @@ -201,9 +173,4 @@ public function getOutputFormat(): string { return $this->outputFormat; } - - public function getOutputFolder(): string - { - return $this->outputFolder; - } } diff --git a/packages/guides/src/Renderer/BaseTypeRenderer.php b/packages/guides/src/Renderer/BaseTypeRenderer.php index 7ff542e4d..a7b8c75d7 100644 --- a/packages/guides/src/Renderer/BaseTypeRenderer.php +++ b/packages/guides/src/Renderer/BaseTypeRenderer.php @@ -7,17 +7,12 @@ use League\Tactician\CommandBus; use phpDocumentor\Guides\Handlers\RenderCommand; use phpDocumentor\Guides\Handlers\RenderDocumentCommand; -use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; use phpDocumentor\Guides\RenderContext; -use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; abstract class BaseTypeRenderer implements TypeRenderer { - public function __construct( - protected readonly CommandBus $commandBus, - private readonly UrlGeneratorInterface $urlGenerator, - private readonly DocumentNameResolverInterface $documentNameResolver, - ) { + public function __construct(protected readonly CommandBus $commandBus) + { } public function render(RenderCommand $renderCommand): void @@ -32,8 +27,6 @@ public function render(RenderCommand $renderCommand): void $renderCommand->getOrigin(), $renderCommand->getDestination(), $renderCommand->getDestinationPath(), - $this->urlGenerator, - $this->documentNameResolver, $renderCommand->getOutputFormat(), $renderCommand->getProjectNode(), ), diff --git a/packages/guides/src/Renderer/IntersphinxRenderer.php b/packages/guides/src/Renderer/IntersphinxRenderer.php index ed462842e..8c7e68230 100644 --- a/packages/guides/src/Renderer/IntersphinxRenderer.php +++ b/packages/guides/src/Renderer/IntersphinxRenderer.php @@ -6,6 +6,7 @@ use phpDocumentor\Guides\Handlers\RenderCommand; use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; +use phpDocumentor\Guides\RenderContext; use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; use function json_encode; @@ -35,10 +36,18 @@ public function render(RenderCommand $renderCommand): void ]; $projectNode = $renderCommand->getProjectNode(); + $context = RenderContext::forProject( + $projectNode, + $renderCommand->getOrigin(), + $renderCommand->getDestination(), + $renderCommand->getDestinationPath(), + 'html', + ); + foreach ($renderCommand->getProjectNode()->getAllDocumentEntries() as $key => $documentEntry) { $url = $this->documentNameResolver->canonicalUrl( '', - $this->urlGenerator->createFileUrl($documentEntry->getFile(), 'html'), + $this->urlGenerator->createFileUrl($context, $documentEntry->getFile()), ); $inventory['std:doc'][$key] = [ $projectNode->getTitle(), @@ -51,7 +60,7 @@ public function render(RenderCommand $renderCommand): void foreach ($renderCommand->getProjectNode()->getAllInternalTargets() as $key => $internalTarget) { $url = $this->documentNameResolver->canonicalUrl( '', - $this->urlGenerator->createFileUrl($internalTarget->getDocumentPath(), 'html', $internalTarget->getAnchor()), + $this->urlGenerator->createFileUrl($context, $internalTarget->getDocumentPath(), $internalTarget->getAnchor()), ); $inventory['std:label'][$key] = [ $projectNode->getTitle(), diff --git a/packages/guides/src/Renderer/UrlGenerator/AbsoluteUrlGenerator.php b/packages/guides/src/Renderer/UrlGenerator/AbsoluteUrlGenerator.php index c39c5c66f..6e6c9f509 100644 --- a/packages/guides/src/Renderer/UrlGenerator/AbsoluteUrlGenerator.php +++ b/packages/guides/src/Renderer/UrlGenerator/AbsoluteUrlGenerator.php @@ -23,10 +23,10 @@ public function generateInternalPathFromRelativeUrl( RenderContext $renderContext, string $canonicalUrl, ): string { - if ($renderContext->getOutputFolder() === '') { + if ($renderContext->getDestinationPath() === '') { return $canonicalUrl; } - return rtrim($renderContext->getOutputFolder(), '/') . '/' . $canonicalUrl; + return rtrim($renderContext->getDestinationPath(), '/') . '/' . $canonicalUrl; } } diff --git a/packages/guides/src/Renderer/UrlGenerator/AbstractUrlGenerator.php b/packages/guides/src/Renderer/UrlGenerator/AbstractUrlGenerator.php index f54ac1c41..b77e6cbe7 100644 --- a/packages/guides/src/Renderer/UrlGenerator/AbstractUrlGenerator.php +++ b/packages/guides/src/Renderer/UrlGenerator/AbstractUrlGenerator.php @@ -15,6 +15,7 @@ use Exception; use League\Uri\UriInfo; +use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; use phpDocumentor\Guides\RenderContext; use phpDocumentor\Guides\UriFactory; @@ -22,9 +23,13 @@ abstract class AbstractUrlGenerator implements UrlGeneratorInterface { - public function createFileUrl(string $filename, string $outputFormat = 'html', string|null $anchor = null): string + public function __construct(private readonly DocumentNameResolverInterface $documentNameResolver) { - return $filename . '.' . $outputFormat . + } + + public function createFileUrl(RenderContext $context, string $filename, string|null $anchor = null): string + { + return $filename . '.' . $context->getOutputFormat() . ($anchor !== null ? '#' . $anchor : ''); } @@ -33,6 +38,27 @@ abstract public function generateInternalPathFromRelativeUrl( string $canonicalUrl, ): string; + /** + * Generate a canonical output URL with the configured file extension and anchor + */ + public function generateCanonicalOutputUrl(RenderContext $context, string $linkedDocument, string|null $anchor = null): string + { + if ($context->getProjectNode()->findDocumentEntry($linkedDocument) !== null) { + // todo: this is a hack, existing documents are expected to be handled like absolute links in some places + $linkedDocument = '/' . $linkedDocument; + } + + $canonicalUrl = $this->documentNameResolver->canonicalUrl( + $context->getDirName(), + $linkedDocument, + ); + + return $this->generateInternalUrl( + $context, + $this->createFileUrl($context, $canonicalUrl, $anchor), + ); + } + public function generateInternalUrl( RenderContext $renderContext, string $canonicalUrl, @@ -50,4 +76,9 @@ private function isRelativeUrl(string $url): bool return UriInfo::isRelativePath($uri); } + + public function getCurrentFileUrl(RenderContext $renderContext): string + { + return $this->createFileUrl($renderContext, $renderContext->getCurrentFileName()); + } } diff --git a/packages/guides/src/Renderer/UrlGenerator/ConfigurableUrlGenerator.php b/packages/guides/src/Renderer/UrlGenerator/ConfigurableUrlGenerator.php index c3b524386..679f94e9f 100644 --- a/packages/guides/src/Renderer/UrlGenerator/ConfigurableUrlGenerator.php +++ b/packages/guides/src/Renderer/UrlGenerator/ConfigurableUrlGenerator.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Guides\Renderer\UrlGenerator; +use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; use phpDocumentor\Guides\RenderContext; use phpDocumentor\Guides\Settings\SettingsManager; @@ -22,13 +23,9 @@ public function __construct( private readonly SettingsManager $settingsManager, private readonly AbsoluteUrlGenerator $absoluteUrlGenerator, private readonly RelativeUrlGenerator $relativeUrlGenerator, + DocumentNameResolverInterface $documentNameResolver, ) { - } - - public function createFileUrl(string $filename, string $outputFormat = 'html', string|null $anchor = null): string - { - return $filename . '.' . $outputFormat . - ($anchor !== null ? '#' . $anchor : ''); + parent::__construct($documentNameResolver); } public function generateInternalPathFromRelativeUrl( diff --git a/packages/guides/src/Renderer/UrlGenerator/RelativeUrlGenerator.php b/packages/guides/src/Renderer/UrlGenerator/RelativeUrlGenerator.php index a585f6921..a8e72240b 100644 --- a/packages/guides/src/Renderer/UrlGenerator/RelativeUrlGenerator.php +++ b/packages/guides/src/Renderer/UrlGenerator/RelativeUrlGenerator.php @@ -30,7 +30,7 @@ public function generateInternalPathFromRelativeUrl( RenderContext $renderContext, string $canonicalUrl, ): string { - $currentPathUri = Uri::createFromString($this->createFileUrl($renderContext->getCurrentFileName(), $renderContext->getOutputFormat())); + $currentPathUri = Uri::createFromString($this->createFileUrl($renderContext, $renderContext->getCurrentFileName())); $canonicalUrlUri = Uri::createFromString($canonicalUrl); $canonicalAnchor = $canonicalUrlUri->getFragment(); diff --git a/packages/guides/src/Renderer/UrlGenerator/UrlGeneratorInterface.php b/packages/guides/src/Renderer/UrlGenerator/UrlGeneratorInterface.php index 3f22e1bf4..3c123d3cd 100644 --- a/packages/guides/src/Renderer/UrlGenerator/UrlGeneratorInterface.php +++ b/packages/guides/src/Renderer/UrlGenerator/UrlGeneratorInterface.php @@ -11,7 +11,9 @@ interface UrlGeneratorInterface /** * Create a url with a file ending derived from the output format */ - public function createFileUrl(string $filename, string $outputFormat = 'html', string|null $anchor = null): string; + public function createFileUrl(RenderContext $context, string $filename, string|null $anchor = null): string; + + public function generateCanonicalOutputUrl(RenderContext $context, string $linkedDocument, string|null $anchor = null): string; public function generateInternalUrl( RenderContext $renderContext, diff --git a/packages/guides/src/Twig/AssetsExtension.php b/packages/guides/src/Twig/AssetsExtension.php index 27721fa4d..f77c32652 100644 --- a/packages/guides/src/Twig/AssetsExtension.php +++ b/packages/guides/src/Twig/AssetsExtension.php @@ -26,6 +26,7 @@ use phpDocumentor\Guides\Nodes\Node; use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; use phpDocumentor\Guides\RenderContext; +use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; use Psr\Log\LoggerInterface; use RuntimeException; use Stringable; @@ -44,6 +45,7 @@ public function __construct( private readonly LoggerInterface $logger, private readonly NodeRenderer $nodeRenderer, private readonly DocumentNameResolverInterface $documentNameResolver, + private readonly UrlGeneratorInterface $urlGenerator, ) { } @@ -121,7 +123,7 @@ public function renderNode(array $context, Node|array|null $node): string public function renderTarget(array $context, Target $target): string { if ($target instanceof InternalTarget) { - return $this->getRenderContext($context)->generateCanonicalOutputUrl($target->getDocumentPath(), $target->getAnchor()); + return $this->urlGenerator->generateCanonicalOutputUrl($this->getRenderContext($context), $target->getDocumentPath(), $target->getAnchor()); } return $target->getUrl(); @@ -153,7 +155,7 @@ public function renderMenu(array $context, string $menuType, int $maxMenuCount = /** @param array{env: RenderContext} $context */ public function renderLink(array $context, string $url, string|null $anchor = null): string { - return $this->getRenderContext($context)->generateCanonicalOutputUrl($url, $anchor); + return $this->urlGenerator->generateCanonicalOutputUrl($this->getRenderContext($context), $url, $anchor); } private function copyAsset( @@ -164,7 +166,7 @@ private function copyAsset( return $sourcePath; } - $canonicalUrl = $renderContext->canonicalUrl($sourcePath); + $canonicalUrl = $this->documentNameResolver->canonicalUrl($renderContext->getDirName(), $sourcePath); $outputPath = $this->documentNameResolver->absoluteUrl( $renderContext->getDestinationPath(), $canonicalUrl, diff --git a/packages/guides/tests/unit/Event/PostRenderDocumentTest.php b/packages/guides/tests/unit/Event/PostRenderDocumentTest.php index 121bad3ae..e80c17cc5 100644 --- a/packages/guides/tests/unit/Event/PostRenderDocumentTest.php +++ b/packages/guides/tests/unit/Event/PostRenderDocumentTest.php @@ -9,9 +9,7 @@ use phpDocumentor\Guides\NodeRenderers\NodeRenderer; use phpDocumentor\Guides\Nodes\DocumentNode; use phpDocumentor\Guides\Nodes\ProjectNode; -use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; use phpDocumentor\Guides\RenderContext; -use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; use PHPUnit\Framework\TestCase; class PostRenderDocumentTest extends TestCase @@ -27,8 +25,6 @@ public function testEventCreation(): void $this->createMock(FilesystemInterface::class), $this->createMock(FilesystemInterface::class), '/path', - $this->createMock(UrlGeneratorInterface::class), - $this->createMock(DocumentNameResolverInterface::class), 'html', new ProjectNode(), ), diff --git a/packages/guides/tests/unit/Event/PreRenderDocumentTest.php b/packages/guides/tests/unit/Event/PreRenderDocumentTest.php index 6de3d67e6..5dd469c38 100644 --- a/packages/guides/tests/unit/Event/PreRenderDocumentTest.php +++ b/packages/guides/tests/unit/Event/PreRenderDocumentTest.php @@ -9,9 +9,7 @@ use phpDocumentor\Guides\NodeRenderers\NodeRenderer; use phpDocumentor\Guides\Nodes\DocumentNode; use phpDocumentor\Guides\Nodes\ProjectNode; -use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; use phpDocumentor\Guides\RenderContext; -use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; use PHPUnit\Framework\TestCase; class PreRenderDocumentTest extends TestCase @@ -27,8 +25,6 @@ public function testCreateEvent(): void $this->createMock(FilesystemInterface::class), $this->createMock(FilesystemInterface::class), '/path', - $this->createMock(UrlGeneratorInterface::class), - $this->createMock(DocumentNameResolverInterface::class), 'html', new ProjectNode(), ), diff --git a/packages/guides/tests/unit/ReferenceResolvers/AnchorReferenceResolverTest.php b/packages/guides/tests/unit/ReferenceResolvers/AnchorReferenceResolverTest.php index c6679b0fd..8f02454a2 100644 --- a/packages/guides/tests/unit/ReferenceResolvers/AnchorReferenceResolverTest.php +++ b/packages/guides/tests/unit/ReferenceResolvers/AnchorReferenceResolverTest.php @@ -8,7 +8,9 @@ use phpDocumentor\Guides\Nodes\Inline\ReferenceNode; use phpDocumentor\Guides\Nodes\ProjectNode; use phpDocumentor\Guides\RenderContext; +use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface; use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; final class AnchorReferenceResolverTest extends TestCase @@ -17,6 +19,7 @@ final class AnchorReferenceResolverTest extends TestCase private RenderContext&MockObject $renderContext; private ProjectNode&MockObject $projectNode; private AnchorReferenceResolver $subject; + private Stub&UrlGeneratorInterface $urlGenerator; protected function setUp(): void { @@ -26,7 +29,11 @@ protected function setUp(): void $this->anchorReducer = $this->createMock(AnchorReducer::class); $this->renderContext = $this->createMock(RenderContext::class); $this->renderContext->expects(self::once())->method('getProjectNode')->willReturn($this->projectNode); - $this->subject = new AnchorReferenceResolver($this->anchorReducer); + $this->urlGenerator = self::createStub(UrlGeneratorInterface::class); + $this->subject = new AnchorReferenceResolver( + $this->anchorReducer, + $this->urlGenerator, + ); } public function testAnchorReducerGetsCalledOndResolvingReference(): void @@ -38,7 +45,7 @@ public function testAnchorReducerGetsCalledOndResolvingReference(): void public function testResolvedReferenceReturnsCanonicalUrl(): void { - $this->renderContext->expects(self::once())->method('generateCanonicalOutputUrl')->willReturn('canonical-url'); + $this->urlGenerator->method('generateCanonicalOutputUrl')->willReturn('canonical-url'); $input = new ReferenceNode('lorem-ipsum'); self::assertTrue($this->subject->resolve($input, $this->renderContext)); self::assertEquals('canonical-url', $input->getUrl()); diff --git a/packages/guides/tests/unit/RenderContextTest.php b/packages/guides/tests/unit/RenderContextTest.php deleted file mode 100644 index 909c8c523..000000000 --- a/packages/guides/tests/unit/RenderContextTest.php +++ /dev/null @@ -1,83 +0,0 @@ -addDocumentEntry(new DocumentEntryNode( - 'getting-started/configuration', - TitleNode::emptyNode(), - )); - - $context = RenderContext::forDocument( - $documentNode, - [$documentNode], - self::createStub(FilesystemInterface::class), - self::createStub(FilesystemInterface::class), - $destinationPath, - new AbsoluteUrlGenerator(), - new DocumentNameResolver(), - 'txt', - $projectNode, - ); - - self::assertSame($result, $context->generateCanonicalOutputUrl($linkedDocument, $anchor)); - } - - /** @return string[][] */ - public static function documentPathProvider(): array - { - return [ - [ - 'filePath' => 'getting-started/configuration', - 'destinationPath' => 'guide/', - 'linkedDocument' => 'installing', - 'result' => 'guide/getting-started/installing.txt', - ], - [ - 'filePath' => 'getting-started/configuration', - 'destinationPath' => 'guide/', - 'linkedDocument' => '/installing', - 'result' => 'guide/installing.txt', - ], - [ - 'filePath' => 'getting-started/configuration', - 'destinationPath' => 'guide', - 'linkedDocument' => 'getting-started/configuration', - 'result' => 'guide/getting-started/configuration.txt#composer', - 'anchor' => 'composer', - ], - [ - 'filePath' => 'getting-started/configuration', - 'destinationPath' => 'guide/', - 'linkedDocument' => '../references/installing', - 'result' => 'guide/references/installing.txt', - ], - ]; - } -} diff --git a/packages/guides/tests/unit/Renderer/UrlGenerator/AbsoluteUrlGeneratorTest.php b/packages/guides/tests/unit/Renderer/UrlGenerator/AbsoluteUrlGeneratorTest.php index 30758585b..d26d79394 100644 --- a/packages/guides/tests/unit/Renderer/UrlGenerator/AbsoluteUrlGeneratorTest.php +++ b/packages/guides/tests/unit/Renderer/UrlGenerator/AbsoluteUrlGeneratorTest.php @@ -4,18 +4,27 @@ namespace phpDocumentor\Guides\Renderer\UrlGenerator; +use League\Flysystem\FilesystemInterface; +use phpDocumentor\Guides\Nodes\DocumentNode; +use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode; +use phpDocumentor\Guides\Nodes\ProjectNode; +use phpDocumentor\Guides\Nodes\TitleNode; +use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolver; +use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; use phpDocumentor\Guides\RenderContext; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; +use function md5; + final class AbsoluteUrlGeneratorTest extends TestCase { #[DataProvider('generateAbsoluteInternalUrlProvider')] public function testGenerateAbsoluteInternalUrl(string $expected, string $canonicalUrl, string $destinationPath): void { - $urlGenerator = new AbsoluteUrlGenerator(); + $urlGenerator = new AbsoluteUrlGenerator(self::createStub(DocumentNameResolverInterface::class)); $renderContext = $this->createMock(RenderContext::class); - $renderContext->method('getOutputFolder')->willReturn($destinationPath); + $renderContext->method('getDestinationPath')->willReturn($destinationPath); self::assertSame($expected, $urlGenerator->generateInternalPathFromRelativeUrl($renderContext, $canonicalUrl)); } @@ -50,4 +59,66 @@ public static function generateAbsoluteInternalUrlProvider(): array ], ]; } + + #[DataProvider('documentPathProvider')] + public function testRelativeDocUrl( + string $filePath, + string $destinationPath, + string $linkedDocument, + string $result, + string|null $anchor = null, + ): void { + $urlGenerator = new AbsoluteUrlGenerator(new DocumentNameResolver()); + $documentNode = new DocumentNode(md5('hash'), $filePath); + + $projectNode = new ProjectNode(); + $projectNode->addDocumentEntry(new DocumentEntryNode( + 'getting-started/configuration', + TitleNode::emptyNode(), + )); + + $context = RenderContext::forDocument( + $documentNode, + [$documentNode], + self::createStub(FilesystemInterface::class), + self::createStub(FilesystemInterface::class), + $destinationPath, + 'txt', + $projectNode, + ); + + self::assertSame($result, $urlGenerator->generateCanonicalOutputUrl($context, $linkedDocument, $anchor)); + } + + /** @return string[][] */ + public static function documentPathProvider(): array + { + return [ + [ + 'filePath' => 'getting-started/configuration', + 'destinationPath' => 'guide/', + 'linkedDocument' => 'installing', + 'result' => 'guide/getting-started/installing.txt', + ], + [ + 'filePath' => 'getting-started/configuration', + 'destinationPath' => 'guide/', + 'linkedDocument' => '/installing', + 'result' => 'guide/installing.txt', + ], + [ + 'filePath' => 'getting-started/configuration', + 'destinationPath' => 'guide', + 'linkedDocument' => 'getting-started/configuration', + 'result' => 'guide/getting-started/configuration.txt#composer', + 'anchor' => 'composer', + ], + [ + 'filePath' => 'getting-started/configuration', + 'destinationPath' => 'guide/', + 'linkedDocument' => '../references/installing', + 'result' => 'guide/references/installing.txt', + ], + ]; + } } diff --git a/packages/guides/tests/unit/Renderer/UrlGenerator/RelativeUrlGeneratorTest.php b/packages/guides/tests/unit/Renderer/UrlGenerator/RelativeUrlGeneratorTest.php index fa936f988..9a5208a21 100644 --- a/packages/guides/tests/unit/Renderer/UrlGenerator/RelativeUrlGeneratorTest.php +++ b/packages/guides/tests/unit/Renderer/UrlGenerator/RelativeUrlGeneratorTest.php @@ -4,6 +4,7 @@ namespace phpDocumentor\Guides\Renderer\UrlGenerator; +use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface; use phpDocumentor\Guides\RenderContext; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -13,7 +14,7 @@ final class RelativeUrlGeneratorTest extends TestCase #[DataProvider('generateRelativeInternalUrlProvider')] public function testGenerateRelativeInternalUrl(string $expected, string $canonicalUrl, string $currentFileName): void { - $urlGenerator = new RelativeUrlGenerator(); + $urlGenerator = new RelativeUrlGenerator(self::createStub(DocumentNameResolverInterface::class)); $renderContext = $this->createMock(RenderContext::class); $renderContext->method('getCurrentFileName')->willReturn($currentFileName); $renderContext->method('getOutputFormat')->willReturn('html'); @@ -69,8 +70,11 @@ public function testCreateFileUrl(string $expected, string $filename, string $ou self::markTestSkipped($skip); } - $urlGenerator = new RelativeUrlGenerator(); - self::assertSame($expected, $urlGenerator->createFileUrl($filename, $outputFormat, $anchor)); + $urlGenerator = new RelativeUrlGenerator(self::createStub(DocumentNameResolverInterface::class)); + $renderContext = $this->createMock(RenderContext::class); + $renderContext->method('getCurrentFileName')->willReturn($filename); + $renderContext->method('getOutputFormat')->willReturn($outputFormat); + self::assertSame($expected, $urlGenerator->createFileUrl($renderContext, $filename, $anchor)); } /** @return array> */ diff --git a/tests/Functional/FunctionalTest.php b/tests/Functional/FunctionalTest.php index 5c14d504d..e5757a503 100644 --- a/tests/Functional/FunctionalTest.php +++ b/tests/Functional/FunctionalTest.php @@ -17,9 +17,7 @@ use phpDocumentor\Guides\NodeRenderers\DelegatingNodeRenderer; use phpDocumentor\Guides\Nodes\ProjectNode; use phpDocumentor\Guides\Parser; -use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolver; use phpDocumentor\Guides\RenderContext; -use phpDocumentor\Guides\Renderer\UrlGenerator\AbsoluteUrlGenerator; use phpDocumentor\Guides\Settings\ProjectSettings; use phpDocumentor\Guides\Settings\SettingsManager; use PHPUnit\Framework\Attributes\DataProvider; @@ -114,11 +112,8 @@ public function testFunctional( $inputFilesystem, $outfs = new Filesystem(new MemoryAdapter()), '', - new AbsoluteUrlGenerator(), - new DocumentNameResolver(), $format, new ProjectNode(), - $settingsManager, ); $rendered = '';