Renderer::render_partial()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 3
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the ICanBoogie package.
5
 *
6
 * (c) Olivier Laviale <[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 ICanBoogie\Render;
13
14
/**
15
 * Renders a target or an array of options.
16
 */
17
class Renderer
18
{
19
	const OPTION_LAYOUT = 'layout';
20
	const OPTION_PARTIAL = 'partial';
21
	const OPTION_TEMPLATE = 'template';
22
	const OPTION_CONTENT = 'content';
23
	const OPTION_LOCALS = 'locals';
24
25
	/**
26
	 * @var EngineCollection
27
	 */
28
	private $engines;
29
30
	/**
31
	 * @var TemplateResolver
32
	 */
33
	protected $template_resolver;
34
35
	/**
36
	 * @param TemplateResolver $template_resolver
37
	 * @param EngineCollection $engines
38
	 */
39
	public function __construct(TemplateResolver $template_resolver, EngineCollection $engines)
40
	{
41
		$this->template_resolver = $template_resolver;
42
		$this->engines = $engines;
43
	}
44
45
	/**
46
	 * Resolve a template pathname from its name and type.
47
	 *
48
	 * @param string $name
49
	 *
50
	 * @return string Template pathname.
51
	 *
52
	 * @throws TemplateNotFound if the template pathname cannot be resolved.
53
	 */
54
	public function resolve_template($name)
55
	{
56
		$template_pathname = $this->template_resolver->resolve($name, $this->engines->extensions, $tried);
57
58
		if (!$template_pathname)
59
		{
60
			throw new TemplateNotFound("There is no template matching `$name`.", $tried ?: []);
61
		}
62
63
		return $template_pathname;
64
	}
65
66
	/**
67
	 * Renders a target or options.
68
	 *
69
	 * @param mixed $target_or_options The target or options to render.
70
	 * @param array $additional_options Additional render options.
71
	 *
72
	 * @return string
73
	 */
74
	public function render($target_or_options, array $additional_options = [])
75
	{
76
		if (!$target_or_options && !$additional_options)
77
		{
78
			return null;
79
		}
80
81
		$options = $this->resolve_options($target_or_options, $additional_options);
82
		$content = $options[self::OPTION_CONTENT];
83
		$variables = $options[self::OPTION_LOCALS];
84
85
		#
86
87
		$template = $options[self::OPTION_PARTIAL];
88
89
		if ($template)
90
 	 	{
91
			$content = $this->render_partial($template, $content, $variables);
92
		}
93
94
		$template = $options[self::OPTION_TEMPLATE];
95
96
		if ($template)
97
		{
98
			$content = $this->render_template($template, $content, $variables);
99
		}
100
101
		$template = $options[self::OPTION_LAYOUT];
102
103
		if ($template)
104
		{
105
			$content = $this->render_layout($template, [ self::OPTION_CONTENT => $content ] + $variables);
106
		}
107
108
		return $content;
109
	}
110
111
	/**
112
	 * Renders partial.
113
	 *
114
	 * @param string $template
115
	 * @param mixed $content
116
	 * @param array $variables
117
	 *
118
	 * @return string
119
	 */
120
	protected function render_partial($template, $content, $variables)
121
	{
122
		return $this->render_template(
123
			$this->resolve_template_name($template)->as_partial,
124
			$content,
125
			$variables
126
		);
127
	}
128
129
	/**
130
	 * Renders layout.
131
	 *
132
	 * @param string $template
133
	 * @param array $variables
134
	 *
135
	 * @return string
136
	 */
137
	protected function render_layout($template, array $variables)
138
	{
139
		return $this->render_template(
140
			$this->resolve_template_name($template)->as_layout,
141
			null,
142
			$variables
143
		);
144
	}
145
146
	/**
147
	 * Renders template.
148
	 *
149
	 * @param string $name
150
	 * @param string $content
151
	 * @param array $variables
152
	 *
153
	 * @return string
154
	 */
155
	protected function render_template($name, $content, $variables)
156
	{
157
		return $this->engines->render(
158
			$this->resolve_template($name),
159
			$content,
160
			$variables
161
		);
162
	}
163
164
	/**
165
	 * Resolves template name.
166
	 *
167
	 * @param mixed $content
168
	 *
169
	 * @return TemplateName
170
	 */
171
	protected function resolve_template_name($content)
172
	{
173
		return TemplateName::from($content);
174
	}
175
176
	/**
177
	 * Resolves rendering options.
178
	 *
179
	 * @param mixed $target_or_options
180
	 * @param array $additional_options
181
	 *
182
	 * @return array
183
	 *
184
	 * @throws InvalidRenderTarget if rendering target is invalid.
185
	 */
186
	protected function resolve_options($target_or_options, array $additional_options = [])
187
	{
188
		$options = [];
189
190
		if (is_object($target_or_options))
191
		{
192
			$additional_options[self::OPTION_CONTENT] = $target_or_options;
193
			$additional_options[self::OPTION_LOCALS]['this'] = $target_or_options;
194
195
			if (empty($additional_options[self::OPTION_PARTIAL]) && empty($additional_options[self::OPTION_TEMPLATE]))
196
			{
197
				$additional_options[self::OPTION_PARTIAL] = $this->resolve_template_name($target_or_options);
198
			}
199
		}
200
		else if (is_array($target_or_options))
201
		{
202
			$options = $target_or_options;
203
		}
204
		else
205
		{
206
			throw new InvalidRenderTarget($target_or_options);
207
		}
208
209
		return $additional_options + $options + [
210
211
			self::OPTION_CONTENT => null,
212
			self::OPTION_PARTIAL => null,
213
			self::OPTION_TEMPLATE => null,
214
			self::OPTION_LAYOUT => null,
215
			self::OPTION_LOCALS => []
216
217
		];
218
	}
219
}
220