Skip to content

Commit a3f8f5b

Browse files
refactor ChainTemplateRenderer to registry pattern
Separates renderer management from rendering responsibilities by introducing TemplateRendererRegistryInterface. The registry provides renderers instead of rendering directly, improving single responsibility adherence. - Add TemplateRendererRegistryInterface with getRenderer() method - Rename ChainTemplateRenderer to TemplateRendererRegistry - Update TemplateRendererListener to use getRenderer()->render() pattern - Remove render() and supports() methods from registry class - Update all references in DI config, tests, and examples
1 parent 71a4830 commit a3f8f5b

File tree

13 files changed

+203
-160
lines changed

13 files changed

+203
-160
lines changed

demo/config/reference.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
<?php
22

3-
// This file is auto-generated and is for apps only. Bundles SHOULD NOT rely on its content.
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
411

512
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
613

examples/platform/template/mixed-content.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
use Symfony\AI\Platform\Message\Message;
1515
use Symfony\AI\Platform\Message\MessageBag;
1616
use Symfony\AI\Platform\Message\Template;
17-
use Symfony\AI\Platform\Message\TemplateRenderer\ChainTemplateRenderer;
1817
use Symfony\AI\Platform\Message\TemplateRenderer\StringTemplateRenderer;
18+
use Symfony\AI\Platform\Message\TemplateRenderer\TemplateRendererRegistry;
1919
use Symfony\Component\EventDispatcher\EventDispatcher;
2020

2121
require_once dirname(__DIR__, 2).'/bootstrap.php';
2222

2323
$eventDispatcher = new EventDispatcher();
24-
$rendererRegistry = new ChainTemplateRenderer([
24+
$rendererRegistry = new TemplateRendererRegistry([
2525
new StringTemplateRenderer(),
2626
]);
2727
$templateListener = new TemplateRendererListener($rendererRegistry);

examples/platform/template/multiple-messages.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
use Symfony\AI\Platform\Message\Message;
1515
use Symfony\AI\Platform\Message\MessageBag;
1616
use Symfony\AI\Platform\Message\Template;
17-
use Symfony\AI\Platform\Message\TemplateRenderer\ChainTemplateRenderer;
1817
use Symfony\AI\Platform\Message\TemplateRenderer\StringTemplateRenderer;
18+
use Symfony\AI\Platform\Message\TemplateRenderer\TemplateRendererRegistry;
1919
use Symfony\Component\EventDispatcher\EventDispatcher;
2020

2121
require_once dirname(__DIR__, 2).'/bootstrap.php';
2222

2323
$eventDispatcher = new EventDispatcher();
24-
$rendererRegistry = new ChainTemplateRenderer([
24+
$rendererRegistry = new TemplateRendererRegistry([
2525
new StringTemplateRenderer(),
2626
]);
2727
$templateListener = new TemplateRendererListener($rendererRegistry);

examples/platform/template/system-message.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
use Symfony\AI\Platform\Message\Message;
1515
use Symfony\AI\Platform\Message\MessageBag;
1616
use Symfony\AI\Platform\Message\Template;
17-
use Symfony\AI\Platform\Message\TemplateRenderer\ChainTemplateRenderer;
1817
use Symfony\AI\Platform\Message\TemplateRenderer\StringTemplateRenderer;
18+
use Symfony\AI\Platform\Message\TemplateRenderer\TemplateRendererRegistry;
1919
use Symfony\Component\EventDispatcher\EventDispatcher;
2020

2121
require_once dirname(__DIR__, 2).'/bootstrap.php';
2222

2323
$eventDispatcher = new EventDispatcher();
24-
$rendererRegistry = new ChainTemplateRenderer([
24+
$rendererRegistry = new TemplateRendererRegistry([
2525
new StringTemplateRenderer(),
2626
]);
2727
$templateListener = new TemplateRendererListener($rendererRegistry);

examples/platform/template/user-message.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
use Symfony\AI\Platform\Message\Message;
1515
use Symfony\AI\Platform\Message\MessageBag;
1616
use Symfony\AI\Platform\Message\Template;
17-
use Symfony\AI\Platform\Message\TemplateRenderer\ChainTemplateRenderer;
1817
use Symfony\AI\Platform\Message\TemplateRenderer\StringTemplateRenderer;
18+
use Symfony\AI\Platform\Message\TemplateRenderer\TemplateRendererRegistry;
1919
use Symfony\Component\EventDispatcher\EventDispatcher;
2020

2121
require_once dirname(__DIR__, 2).'/bootstrap.php';
2222

2323
$eventDispatcher = new EventDispatcher();
24-
$rendererRegistry = new ChainTemplateRenderer([
24+
$rendererRegistry = new TemplateRendererRegistry([
2525
new StringTemplateRenderer(),
2626
]);
2727
$templateListener = new TemplateRendererListener($rendererRegistry);

src/ai-bundle/config/services.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@
6565
use Symfony\AI\Platform\Contract\JsonSchema\DescriptionParser;
6666
use Symfony\AI\Platform\Contract\JsonSchema\Factory as SchemaFactory;
6767
use Symfony\AI\Platform\EventListener\TemplateRendererListener;
68-
use Symfony\AI\Platform\Message\TemplateRenderer\ChainTemplateRenderer;
6968
use Symfony\AI\Platform\Message\TemplateRenderer\ExpressionLanguageTemplateRenderer;
7069
use Symfony\AI\Platform\Message\TemplateRenderer\StringTemplateRenderer;
70+
use Symfony\AI\Platform\Message\TemplateRenderer\TemplateRendererRegistry;
7171
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
7272
use Symfony\AI\Platform\Serializer\StructuredOutputSerializer;
7373
use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber;
@@ -138,7 +138,7 @@
138138
}
139139

140140
$container->services()
141-
->set('ai.platform.template_renderer_registry', ChainTemplateRenderer::class)
141+
->set('ai.platform.template_renderer_registry', TemplateRendererRegistry::class)
142142
->args([
143143
tagged_iterator('ai.platform.template_renderer'),
144144
])

src/ai-bundle/tests/DependencyInjection/AiBundleTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@
3434
use Symfony\AI\Platform\Bridge\Ollama\OllamaApiCatalog;
3535
use Symfony\AI\Platform\Capability;
3636
use Symfony\AI\Platform\EventListener\TemplateRendererListener;
37-
use Symfony\AI\Platform\Message\TemplateRenderer\ChainTemplateRenderer;
3837
use Symfony\AI\Platform\Message\TemplateRenderer\ExpressionLanguageTemplateRenderer;
3938
use Symfony\AI\Platform\Message\TemplateRenderer\StringTemplateRenderer;
39+
use Symfony\AI\Platform\Message\TemplateRenderer\TemplateRendererRegistry;
4040
use Symfony\AI\Platform\Model;
4141
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
4242
use Symfony\AI\Platform\PlatformInterface;
@@ -7009,7 +7009,7 @@ public function testTemplateRendererServicesAreRegistered()
70097009
// Verify template renderer registry is registered
70107010
$this->assertTrue($container->hasDefinition('ai.platform.template_renderer_registry'));
70117011
$registryDefinition = $container->getDefinition('ai.platform.template_renderer_registry');
7012-
$this->assertSame(ChainTemplateRenderer::class, $registryDefinition->getClass());
7012+
$this->assertSame(TemplateRendererRegistry::class, $registryDefinition->getClass());
70137013

70147014
// Verify template renderer listener is registered as event subscriber
70157015
$this->assertTrue($container->hasDefinition('ai.platform.template_renderer_listener'));

src/platform/src/EventListener/TemplateRendererListener.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use Symfony\AI\Platform\Message\MessageInterface;
1919
use Symfony\AI\Platform\Message\SystemMessage;
2020
use Symfony\AI\Platform\Message\Template;
21-
use Symfony\AI\Platform\Message\TemplateRenderer\ChainTemplateRenderer;
21+
use Symfony\AI\Platform\Message\TemplateRenderer\TemplateRendererRegistryInterface;
2222
use Symfony\AI\Platform\Message\UserMessage;
2323
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2424

@@ -30,7 +30,7 @@
3030
final class TemplateRendererListener implements EventSubscriberInterface
3131
{
3232
public function __construct(
33-
private readonly ChainTemplateRenderer $rendererRegistry,
33+
private readonly TemplateRendererRegistryInterface $rendererRegistry,
3434
) {
3535
}
3636

@@ -78,7 +78,9 @@ private function renderMessage(MessageInterface $message, array $templateVars):
7878
if ($message instanceof SystemMessage) {
7979
$content = $message->getContent();
8080
if ($content instanceof Template) {
81-
$renderedContent = $this->rendererRegistry->render($content, $templateVars);
81+
$renderedContent = $this->rendererRegistry
82+
->getRenderer($content->getType())
83+
->render($content, $templateVars);
8284

8385
return new SystemMessage($renderedContent);
8486
}
@@ -91,7 +93,10 @@ private function renderMessage(MessageInterface $message, array $templateVars):
9193
foreach ($message->getContent() as $content) {
9294
if ($content instanceof Template) {
9395
$hasTemplate = true;
94-
$renderedText = $this->rendererRegistry->render($content, $templateVars);
96+
$renderedText = $this->rendererRegistry
97+
->getRenderer($content->getType())
98+
->render($content, $templateVars);
99+
95100
$renderedContent[] = new Text($renderedText);
96101
} else {
97102
$renderedContent[] = $content;

src/platform/src/Message/TemplateRenderer/ChainTemplateRenderer.php renamed to src/platform/src/Message/TemplateRenderer/TemplateRendererRegistry.php

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,15 @@
1212
namespace Symfony\AI\Platform\Message\TemplateRenderer;
1313

1414
use Symfony\AI\Platform\Exception\InvalidArgumentException;
15-
use Symfony\AI\Platform\Message\Template;
1615

1716
/**
18-
* Composite renderer that chains multiple renderers.
17+
* Registry for managing template renderers.
1918
*
20-
* Implements chain of responsibility pattern - tries each renderer until one supports the type.
19+
* Provides access to template renderers based on template type.
2120
*
2221
* @author Johannes Wachter <[email protected]>
2322
*/
24-
final class ChainTemplateRenderer implements TemplateRendererInterface
23+
final class TemplateRendererRegistry implements TemplateRendererRegistryInterface
2524
{
2625
/**
2726
* @var TemplateRendererInterface[]
@@ -36,25 +35,14 @@ public function __construct(iterable $renderers)
3635
$this->renderers = $renderers instanceof \Traversable ? iterator_to_array($renderers) : $renderers;
3736
}
3837

39-
public function supports(string $type): bool
38+
public function getRenderer(string $type): TemplateRendererInterface
4039
{
4140
foreach ($this->renderers as $renderer) {
4241
if ($renderer->supports($type)) {
43-
return true;
42+
return $renderer;
4443
}
4544
}
4645

47-
return false;
48-
}
49-
50-
public function render(Template $template, array $variables): string
51-
{
52-
foreach ($this->renderers as $renderer) {
53-
if ($renderer->supports($template->getType())) {
54-
return $renderer->render($template, $variables);
55-
}
56-
}
57-
58-
throw new InvalidArgumentException(\sprintf('No renderer found for template type "%s".', $template->getType()));
46+
throw new InvalidArgumentException(\sprintf('No renderer found for template type "%s".', $type));
5947
}
6048
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Message\TemplateRenderer;
13+
14+
use Symfony\AI\Platform\Exception\InvalidArgumentException;
15+
16+
/**
17+
* Registry for managing template renderers.
18+
*
19+
* Provides access to template renderers based on template type.
20+
*
21+
* @author Johannes Wachter <[email protected]>
22+
*/
23+
interface TemplateRendererRegistryInterface
24+
{
25+
/**
26+
* @throws InvalidArgumentException If no renderer supports the type
27+
*/
28+
public function getRenderer(string $type): TemplateRendererInterface;
29+
}

0 commit comments

Comments
 (0)