Completed
Pull Request — 2.x (#25)
by Akihito
13:28 queued 05:05
created

TwigRenderer::loadTemplate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

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