Completed
Pull Request — 2.0.x (#6)
by Andrew
06:23
created

HTMLRenderer::includeWithAnonymousScope()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 16
rs 9.4286
cc 2
eloc 6
nc 2
nop 2
1
<?php
2
/**
3
 * @author     Andrew Coulton <[email protected]>
4
 * @copyright  2015 inGenerator Ltd
5
 * @license    http://kohanaframework.org/license
6
 */
7
8
namespace Ingenerator\KohanaView\Renderer;
9
10
11
use Ingenerator\KohanaView\Renderer;
12
use Ingenerator\KohanaView\TemplateManager;
13
use Ingenerator\KohanaView\ViewModel;
14
use Ingenerator\KohanaView\ViewTemplateSelector;
15
16
/**
17
 * Renders a ViewModel to an HTML string for return to the user. The template is rendered with an anonymous scope
18
 * which only has access to the ViewModel, the Renderer (for rendering any subviews) and the template file path.
19
 *
20
 * @package Ingenerator\KohanaView\Renderer
21
 */
22
class HTMLRenderer implements Renderer
23
{
24
25
    /**
26
     * @var TemplateManager
27
     */
28
    protected $template_manager;
29
30
    /**
31
     * @var ViewTemplateSelector
32
     */
33
    protected $template_selector;
34
35
    public function __construct(ViewTemplateSelector $template_selector, TemplateManager $template_manager)
36
    {
37
        $this->template_selector = $template_selector;
38
        $this->template_manager  = $template_manager;
39
    }
40
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function render(ViewModel $view)
46
    {
47
        $template_path = $this->getTemplatePath($view);
48
49
        ob_start();
50
        try {
51
            $this->includeWithAnonymousScope($view, $template_path);
52
        } finally {
53
            $output = ob_get_clean();
54
        }
55
56
        return $output;
57
    }
58
59
    /**
60
     * @param ViewModel $view
61
     *
62
     * @return string
63
     */
64
    protected function getTemplatePath(ViewModel $view)
65
    {
66
        $template_name = $this->template_selector->getTemplateName($view);
67
        $template      = $this->template_manager->getPath($template_name);
68
69
        return $template;
70
    }
71
72
    /**
73
     * @param ViewModel $view
74
     * @param string    $template_path
75
     */
76
    protected function includeWithAnonymousScope(ViewModel $view, $template_path)
77
    {
78
        /** @noinspection PhpUnusedParameterInspection */
79
        /** @noinspection PhpDocSignatureInspection */
80
        $bound_capture = function (ViewModel $view, Renderer $renderer, $template) {
81
            /** @noinspection PhpIncludeInspection */
82
            return include $template;
83
        };
84
        $anon_capture  = $bound_capture->bindTo(NULL);
85
86
        // A user's own error handler may throw an exception here if the include fails - which we will bubble as-is.
87
        // If they have not configured an error handler, we need to throw an exception of our own.
88
        if ($anon_capture($view, $this, $template_path) === FALSE) {
89
            throw new \UnexpectedValueException('Failed to include template '.$template_path);
90
        }
91
    }
92
93
}
94