Completed
Pull Request — 1.x (#19)
by IWASAKI
09:16 queued 05:43
created

TwigRenderer   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 24
c 3
b 0
f 0
lcom 1
cbo 7
dl 0
loc 133
ccs 48
cts 48
cp 1
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getTemplate() 0 12 3
A __construct() 0 5 2
A render() 0 7 2
A beforeRender() 0 6 2
A renderView() 0 6 2
A load() 0 12 3
A isNoContent() 0 4 2
A loadTemplate() 0 14 3
A getReflection() 0 8 2
A getTemplatePath() 0 6 1
A buildBody() 0 7 2
1
<?php
2
3
namespace Madapaja\TwigModule;
4
5
use BEAR\Resource\Code;
6
use BEAR\Resource\RenderInterface;
7
use BEAR\Resource\ResourceObject;
8
use Ray\Aop\WeavedInterface;
9
use Twig_Environment;
10
11
class TwigRenderer implements RenderInterface
12
{
13
    /**
14
     * File extension
15
     *
16
     * @var string
17
     */
18
    const EXT = '.html.twig';
19
20
    /**
21
     * @var Twig_Environment
22
     */
23
    public $twig;
24
25
    /**
26
     * @var TemplateFinderInterface
27
     */
28
    private $templateFinder;
29
30 21
    public function __construct(Twig_Environment $twig, TemplateFinderInterface $templateFinder = null)
31
    {
32 21
        $this->twig = $twig;
33 21
        $this->templateFinder = $templateFinder ?: new TemplateFinder;
34 21
    }
35
36 14
    public function render(ResourceObject $ro)
37
    {
38 14
        $this->beforeRender($ro);
39 14
        $ro->view = $this->isNoContent($ro) ? '' : $this->renderView($ro);
40
41 12
        return $ro->view;
42
    }
43
44 14
    private function beforeRender(ResourceObject $ro)
45
    {
46 14
        if (!isset($ro->headers['content-type'])) {
47 14
            $ro->headers['content-type'] = 'text/html; charset=utf-8';
48
        }
49 14
    }
50
51 13
    private function renderView(ResourceObject $ro)
52
    {
53 13
        $template = $this->load($ro);
54
55 11
        return $template ? $template->render($this->buildBody($ro)) : '';
56
    }
57
58 13
    private function load(ResourceObject $ro)
59
    {
60
        try {
61 13
            return $this->loadTemplate($ro);
62 3
        } catch (\Twig_Error_Loader $e) {
63 3
            if ($ro->code !== 200) {
64 1
                return false;
65
            }
66
        }
67
68 2
        throw new Exception\TemplateNotFound($e->getMessage(), 500, $e);
69
    }
70
71 14
    private function isNoContent(ResourceObject $ro)
72
    {
73 14
        return $ro->code === Code::NO_CONTENT || $ro->view === '';
74
    }
75
76
    /**
77
     * @return \Twig_TemplateWrapper
78
     */
79 13
    private function loadTemplate(ResourceObject $ro)
80
    {
81 13
        $loader = $this->twig->getLoader();
82 13
        if ($loader instanceof \Twig_Loader_Filesystem) {
83 9
            list($file, $dir) = $this->getTemplate($ro, $loader->getPaths());
84 9
            if ($dir) {
85
                // if the file not in paths, register the directory
86 1
                $loader->prependPath($dir);
87
            }
88
89 9
            return $this->twig->load($file);
90
        }
91 4
        return $this->twig->load($this->getReflection($ro)->name . self::EXT);
92
    }
93
94
    /**
95
     * @return \ReflectionClass
96
     */
97 13
    private function getReflection(ResourceObject $ro)
98
    {
99 13
        if ($ro instanceof WeavedInterface) {
100 1
            return (new \ReflectionClass($ro))->getParentClass();
101
        }
102
103 12
        return (new \ReflectionClass($ro));
104
    }
105
106
    /**
107
     * return template file full path
108
     *
109
     * @return string
110
     */
111 9
    private function getTemplatePath(ResourceObject $ro)
112
    {
113 9
        $file = $this->getReflection($ro)->getFileName();
114
115 9
        return $this->templateFinder->__invoke($file);
116
    }
117
118
    /**
119
     * return template path and directory
120
     *
121
     * @return array
122
     */
123 9
    private function getTemplate(ResourceObject $ro, array $paths = [])
124
    {
125 9
        $file = $this->getTemplatePath($ro);
126
127 9
        foreach ($paths as $path) {
128 8
            if (strpos($file, $path . '/') === 0) {
129 8
                return [substr($file, strlen($path . '/')), null];
130
            }
131
        }
132
133 1
        return [basename($file), dirname($file)];
134
    }
135
136 10
    private function buildBody(ResourceObject $ro)
137
    {
138 10
        $body = is_array($ro->body) ? $ro->body : [];
139 10
        $body += ['_code' => $ro->code, '_headers' => $ro->headers];
140
141 10
        return $body;
142
    }
143
}
144