1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
|
4
|
|
|
namespace TheCodingMachine\CMS\Theme; |
5
|
|
|
|
6
|
|
|
use Psr\Http\Message\StreamInterface; |
7
|
|
|
use TheCodingMachine\CMS\Block\BlockInterface; |
8
|
|
|
use TheCodingMachine\CMS\Block\BlockRendererInterface; |
9
|
|
|
use TheCodingMachine\CMS\CMSException; |
10
|
|
|
use TheCodingMachine\CMS\RenderableInterface; |
11
|
|
|
use Zend\Diactoros\Stream; |
12
|
|
|
|
13
|
|
|
class TwigTheme implements RenderableInterface |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* @var \Twig_Environment |
17
|
|
|
*/ |
18
|
|
|
private $twig; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @var string |
22
|
|
|
*/ |
23
|
|
|
private $template; |
24
|
|
|
/** |
25
|
|
|
* @var BlockRendererInterface |
26
|
|
|
*/ |
27
|
|
|
private $blockRenderer; |
28
|
|
|
|
29
|
|
|
public function __construct(\Twig_Environment $twig, string $template, BlockRendererInterface $blockRenderer) |
30
|
|
|
{ |
31
|
|
|
$this->twig = $twig; |
32
|
|
|
$this->template = $template; |
33
|
|
|
$this->blockRenderer = $blockRenderer; |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Renders (as a stream) the data passed in parameter. |
39
|
|
|
* |
40
|
|
|
* @param mixed[] $context |
41
|
|
|
* @return StreamInterface |
42
|
|
|
*/ |
43
|
|
|
public function render(array $context): StreamInterface |
44
|
|
|
{ |
45
|
|
|
$parent = $context['parent'] ?? null; |
46
|
|
|
unset($context['parent']); |
47
|
|
|
$page = $context['page'] ?? null; |
48
|
|
|
unset($context['page']); |
49
|
|
|
|
50
|
|
|
foreach ($context as $key => &$value) { |
51
|
|
|
$value = $this->contextValueToString($value, $context); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
if ($parent !== null) { |
55
|
|
|
$context['parent'] = $parent; |
56
|
|
|
} |
57
|
|
|
if ($page !== null) { |
58
|
|
|
$context['page'] = $page; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
$text = $this->twig->render($this->template, $context); |
62
|
|
|
|
63
|
|
|
$stream = new Stream('php://temp', 'wb+'); |
64
|
|
|
$stream->write($text); |
65
|
|
|
$stream->rewind(); |
66
|
|
|
|
67
|
|
|
return $stream; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @param mixed $value |
72
|
|
|
* @param mixed[] $context |
73
|
|
|
* @return string |
74
|
|
|
* @throws CMSException |
75
|
|
|
*/ |
76
|
|
|
private function contextValueToString($value, array $context) : string |
77
|
|
|
{ |
78
|
|
|
if ($value instanceof BlockInterface) { |
79
|
|
|
$additionalContext = [ |
80
|
|
|
'parent' => $context, |
81
|
|
|
'page' => $context['page'] ?? $context |
82
|
|
|
]; |
83
|
|
|
|
84
|
|
|
return (string) $this->blockRenderer->renderBlock($value, $additionalContext); |
85
|
|
|
} |
86
|
|
|
if (is_array($value)) { |
87
|
|
|
$str = ''; |
88
|
|
|
foreach ($value as $item) { |
89
|
|
|
$str .= $this->contextValueToString($item, $context); |
90
|
|
|
} |
91
|
|
|
return $str; |
92
|
|
|
} |
93
|
|
|
if (is_string($value)) { |
94
|
|
|
return $value; |
95
|
|
|
} |
96
|
|
|
throw new CMSException('Unable to handle a context value. It must be a string or an array or a BlockInterface'); |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
|