diff --git a/composer.json b/composer.json index 1943e9a0e..a91de89bc 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "ext-json": "*", "ext-mbstring": "*", "doctrine/lexer": "^3.0", + "jawira/plantuml-encoding": "^1.1", "league/commonmark": "^2.4", "league/flysystem": "^1.0.5", "league/tactician": "^1.1", diff --git a/composer.lock b/composer.lock index 98e2f5212..0db5dd905 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "90b062fa06ee3fa4fe3e17715ae6c6f8", + "content-hash": "f32e73eac99d54da37e0095604dbeb83", "packages": [ { "name": "dflydev/dot-access-data", @@ -158,6 +158,59 @@ ], "time": "2022-12-15T16:57:16+00:00" }, + { + "name": "jawira/plantuml-encoding", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/jawira/plantuml-encoding.git", + "reference": "cec097dfc062e7e13655d9594eacce5f9df639ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jawira/plantuml-encoding/zipball/cec097dfc062e7e13655d9594eacce5f9df639ad", + "reference": "cec097dfc062e7e13655d9594eacce5f9df639ad", + "shasum": "" + }, + "require": { + "ext-zlib": "*", + "php": ">=7.0" + }, + "require-dev": { + "jawira/skeleton": "^2.14", + "phpstan/phpstan": "^1.0", + "vimeo/psalm": "^4.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/plantuml_functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jawira Portugal", + "homepage": "https://jawira.com" + } + ], + "description": "PlantUML encoding functions", + "keywords": [ + "encodep", + "encoding", + "functions", + "plantuml", + "uml" + ], + "support": { + "issues": "https://github.com/jawira/plantuml-encoding/issues", + "source": "https://github.com/jawira/plantuml-encoding/tree/v1.1.0" + }, + "time": "2022-05-31T18:58:21+00:00" + }, { "name": "league/commonmark", "version": "2.4.1", @@ -1212,9 +1265,10 @@ "dist": { "type": "path", "url": "./packages/guides-graphs", - "reference": "e0346f5ecc58ad13431c0dbd2aa1855ba436dfa2" + "reference": "d1ab7dc42848da693c624a0c3a2cd97155ff492c" }, "require": { + "jawira/plantuml-encoding": "^1.0", "php": "^8.1", "phpdocumentor/guides": "self.version", "phpdocumentor/guides-restructured-text": "self.version", diff --git a/packages/guides-cli/src/DependencyInjection/ContainerFactory.php b/packages/guides-cli/src/DependencyInjection/ContainerFactory.php index d5a1f82d5..0ac26c52e 100644 --- a/packages/guides-cli/src/DependencyInjection/ContainerFactory.php +++ b/packages/guides-cli/src/DependencyInjection/ContainerFactory.php @@ -43,7 +43,7 @@ public function __construct(array $defaultExtensions = []) $this->configLoader = new XmlFileLoader(new FileLocator()); foreach ([new GuidesExtension(), new ReStructuredTextExtension(), ...$defaultExtensions] as $extension) { - $this->registerExtension($extension); + $this->registerExtension($extension, []); } } @@ -54,7 +54,7 @@ public function loadExtensionConfig(string $extension, array $config): void $extensionAlias = $this->registeredExtensions[$extensionFqcn] ?? false; if (!$extensionAlias) { - $this->registerExtension(new $extensionFqcn()); + $this->registerExtension(new $extensionFqcn(), $config); return; } @@ -79,10 +79,11 @@ public function create(string $vendorDir): Container return $this->container; } - private function registerExtension(ExtensionInterface $extension): void + /** @param array $config */ + private function registerExtension(ExtensionInterface $extension, array $config): void { $this->container->registerExtension($extension); - $this->container->loadFromExtension($extension->getAlias()); + $this->container->loadFromExtension($extension->getAlias(), $config); $this->registeredExtensions[$extension::class] = $extension->getAlias(); } diff --git a/packages/guides-graphs/composer.json b/packages/guides-graphs/composer.json index ba08135ba..6117dd56f 100644 --- a/packages/guides-graphs/composer.json +++ b/packages/guides-graphs/composer.json @@ -24,7 +24,11 @@ "php": "^8.1", "phpdocumentor/guides": "self.version", "phpdocumentor/guides-restructured-text": "self.version", + "jawira/plantuml-encoding": "^1.0", "symfony/process": "^5.4 || ^6.3", "twig/twig": "~2.0 || ^3.0" + }, + "suggest": { + "jawira/plantuml": "To render graphs locally using plant uml" } } diff --git a/packages/guides-graphs/resources/config/guides-graphs.php b/packages/guides-graphs/resources/config/guides-graphs.php index 9ae2d0a93..bcd940df6 100644 --- a/packages/guides-graphs/resources/config/guides-graphs.php +++ b/packages/guides-graphs/resources/config/guides-graphs.php @@ -3,7 +3,12 @@ declare(strict_types=1); use phpDocumentor\Guides\Graphs\Directives\UmlDirective; -use phpDocumentor\Guides\RestructuredText\Directives\BaseDirective; +use phpDocumentor\Guides\Graphs\Nodes\UmlNode; +use phpDocumentor\Guides\Graphs\Renderer\DiagramRenderer; +use phpDocumentor\Guides\Graphs\Renderer\PlantumlRenderer; +use phpDocumentor\Guides\Graphs\Renderer\PlantumlServerRenderer; +use phpDocumentor\Guides\Graphs\Twig\UmlExtension; +use phpDocumentor\Guides\NodeRenderers\TemplateNodeRenderer; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; return static function (ContainerConfigurator $container): void { @@ -11,7 +16,24 @@ ->defaults() ->autowire() ->autoconfigure() - ->instanceof(BaseDirective::class) + ->set(UmlDirective::class) ->tag('phpdoc.guides.directive') - ->set(UmlDirective::class); + + ->set('phpdoc.guides.', TemplateNodeRenderer::class) + ->tag('phpdoc.guides.noderenderer.html') + ->arg('$template', 'body/uml.html.twig') + ->arg('$nodeClass', UmlNode::class) + + ->set(PlantumlRenderer::class) + ->arg('$plantUmlBinaryPath', '%guides.graphs.plantuml_binary%') + + ->set(PlantumlServerRenderer::class) + ->arg( + '$plantumlServerUrl', + '%guides.graphs.plantuml_server%', + ) + ->alias(DiagramRenderer::class, PlantumlServerRenderer::class) + + ->set(UmlExtension::class) + ->tag('twig.extension'); }; diff --git a/packages/guides/resources/template/html/body/uml.html.twig b/packages/guides-graphs/resources/template/html/body/uml.html.twig similarity index 100% rename from packages/guides/resources/template/html/body/uml.html.twig rename to packages/guides-graphs/resources/template/html/body/uml.html.twig diff --git a/packages/guides-graphs/src/Graphs/DependencyInjection/Configuration.php b/packages/guides-graphs/src/Graphs/DependencyInjection/Configuration.php new file mode 100644 index 000000000..d53ff1d15 --- /dev/null +++ b/packages/guides-graphs/src/Graphs/DependencyInjection/Configuration.php @@ -0,0 +1,37 @@ +getRootNode(); + assert($rootNode instanceof ArrayNodeDefinition); + + $rootNode->children() + ->scalarNode('renderer') + ->defaultValue('plantuml-server') + ->info('Render engine to use for generating graphs') + ->end() + ->scalarNode('plantuml_server') + ->defaultValue('https://www.plantuml.com/plantuml') + ->info('URL of the PlantUML server to use') + ->end() + ->scalarNode('plantuml_binary') + ->defaultValue('plantuml') + ->info('Path to your local PlantUML binary') + ->end(); + + return $treeBuilder; + } +} diff --git a/packages/guides-graphs/src/Graphs/DependencyInjection/GraphsExtension.php b/packages/guides-graphs/src/Graphs/DependencyInjection/GraphsExtension.php index b8ef59ceb..6c8931405 100644 --- a/packages/guides-graphs/src/Graphs/DependencyInjection/GraphsExtension.php +++ b/packages/guides-graphs/src/Graphs/DependencyInjection/GraphsExtension.php @@ -7,15 +7,25 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use function dirname; -class GraphsExtension extends Extension +class GraphsExtension extends Extension implements PrependExtensionInterface { /** @param mixed[] $configs */ public function load(array $configs, ContainerBuilder $container): void { + $config = $this->processConfiguration( + $this->getConfiguration($configs, $container), + $configs, + ); + + $container->setParameter('guides.graphs.renderer', $config['renderer']); + $container->setParameter('guides.graphs.plantuml_binary', $config['plantuml_binary']); + $container->setParameter('guides.graphs.plantuml_server', $config['plantuml_server']); + $loader = new PhpFileLoader( $container, new FileLocator(dirname(__DIR__, 3) . '/resources/config'), @@ -23,4 +33,11 @@ public function load(array $configs, ContainerBuilder $container): void $loader->load('guides-graphs.php'); } + + public function prepend(ContainerBuilder $container): void + { + $container->prependExtensionConfig('guides', [ + 'base_template_paths' => [dirname(__DIR__, 3) . '/resources/template/html'], + ]); + } } diff --git a/packages/guides-graphs/src/Graphs/Renderer/PlantumlServerRenderer.php b/packages/guides-graphs/src/Graphs/Renderer/PlantumlServerRenderer.php new file mode 100644 index 000000000..c833804b4 --- /dev/null +++ b/packages/guides-graphs/src/Graphs/Renderer/PlantumlServerRenderer.php @@ -0,0 +1,38 @@ +httpClient->request( + 'GET', + $this->plantumlServerUrl . '/svg/' . $encodedDiagram, + ); + + if ($response->getStatusCode() !== 200) { + $this->logger->error('Failed to render diagram using server:' . $this->plantumlServerUrl); + + return null; + } + + return $response->getContent(); + } +} diff --git a/tests/Integration/tests/graphs/plantuml-inline/expected/index.html b/tests/Integration/tests/graphs/plantuml-inline/expected/index.html new file mode 100644 index 000000000..adb14f2ef --- /dev/null +++ b/tests/Integration/tests/graphs/plantuml-inline/expected/index.html @@ -0,0 +1,17 @@ + + + + Uml Directive + + + +
+

Uml Directive

+ +
classclassotherClassotherClassmessage
+
+ + + diff --git a/tests/Integration/tests/graphs/plantuml-inline/input/guides.xml b/tests/Integration/tests/graphs/plantuml-inline/input/guides.xml new file mode 100644 index 000000000..2b316bbdc --- /dev/null +++ b/tests/Integration/tests/graphs/plantuml-inline/input/guides.xml @@ -0,0 +1,9 @@ + + + + plantuml-server + /usr/bin/plantuml + + diff --git a/tests/Integration/tests/graphs/plantuml-inline/input/index.rst b/tests/Integration/tests/graphs/plantuml-inline/input/index.rst new file mode 100644 index 000000000..1f75596b2 --- /dev/null +++ b/tests/Integration/tests/graphs/plantuml-inline/input/index.rst @@ -0,0 +1,7 @@ +============== +Uml Directive +============== + +.. uml:: + + class -> otherClass : message