1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Templating;
13
14/**
15 * DelegatingEngine selects an engine for a given template.
16 *
17 * @author Fabien Potencier <fabien@symfony.com>
18 */
19class DelegatingEngine implements EngineInterface, StreamingEngineInterface
20{
21    /**
22     * @var EngineInterface[]
23     */
24    protected $engines = [];
25
26    /**
27     * @param EngineInterface[] $engines An array of EngineInterface instances to add
28     */
29    public function __construct(array $engines = [])
30    {
31        foreach ($engines as $engine) {
32            $this->addEngine($engine);
33        }
34    }
35
36    /**
37     * {@inheritdoc}
38     */
39    public function render($name, array $parameters = [])
40    {
41        return $this->getEngine($name)->render($name, $parameters);
42    }
43
44    /**
45     * {@inheritdoc}
46     */
47    public function stream($name, array $parameters = [])
48    {
49        $engine = $this->getEngine($name);
50        if (!$engine instanceof StreamingEngineInterface) {
51            throw new \LogicException(sprintf('Template "%s" cannot be streamed as the engine supporting it does not implement StreamingEngineInterface.', $name));
52        }
53
54        $engine->stream($name, $parameters);
55    }
56
57    /**
58     * {@inheritdoc}
59     */
60    public function exists($name)
61    {
62        return $this->getEngine($name)->exists($name);
63    }
64
65    public function addEngine(EngineInterface $engine)
66    {
67        $this->engines[] = $engine;
68    }
69
70    /**
71     * {@inheritdoc}
72     */
73    public function supports($name)
74    {
75        try {
76            $this->getEngine($name);
77        } catch (\RuntimeException $e) {
78            return false;
79        }
80
81        return true;
82    }
83
84    /**
85     * Get an engine able to render the given template.
86     *
87     * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
88     *
89     * @return EngineInterface The engine
90     *
91     * @throws \RuntimeException if no engine able to work with the template is found
92     */
93    public function getEngine($name)
94    {
95        foreach ($this->engines as $engine) {
96            if ($engine->supports($name)) {
97                return $engine;
98            }
99        }
100
101        throw new \RuntimeException(sprintf('No engine is able to work with the template "%s".', $name));
102    }
103}
104