Completed
Push — 2.x ( a525cc...6c7340 )
by Akihito
23s queued 10s
created

TwigRenderer::load()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 4
cts 4
cp 1
rs 9.9332
c 0
b 0
f 0
cc 3
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 Madapaja\TwigModule\Annotation\TwigRedirectPath;
13
use Ray\Aop\WeavedInterface;
14
use Twig\Environment;
15
use Twig\Error\LoaderError;
16
use Twig\Loader\FilesystemLoader;
17
use Twig\TemplateWrapper;
18
19
class TwigRenderer implements RenderInterface
20
{
21
    /**
22
     * File extension
23
     *
24
     * @var string
25
     */
26
    const EXT = '.html.twig';
27
28
    /**
29
     * @var \Twig\Environment
30
     */
31
    public $twig;
32
33
    /**
34 23
     * @var string
35
     */
36 23
    private $redirectPage;
37 23
38 23
    /**
39
     * @var TemplateFinderInterface
40
     */
41
    private $templateFinder;
42
43 15
    /**
44
     * @TwigRedirectPath("redirectPage")
45 15
     */
46 15
    public function __construct(Environment $twig, string $redirectPage, TemplateFinderInterface $templateFinder = null)
47
    {
48 13
        $this->twig = $twig;
49
        $this->redirectPage = $redirectPage;
50
        $this->templateFinder = $templateFinder ?: new TemplateFinder;
51 15
    }
52
53 15
    /**
54 15
     * {@inheritdoc}
55
     */
56 15
    public function render(ResourceObject $ro)
57
    {
58 14
        $this->setContentType($ro);
59
60 14
        if ($this->isNoContent($ro)) {
61
            $ro->view = '';
62 12
        } elseif ($this->isRedirect($ro)) {
63
            $ro->view = $this->renderRedirectView($ro);
64
        } else {
65
            $ro->view = $this->renderView($ro);
66
        }
67
68 14
        return $ro->view;
69
    }
70
71 14
    private function setContentType(ResourceObject $ro)
72 3
    {
73 3
        if (! isset($ro->headers['content-type'])) {
74 1
            $ro->headers['content-type'] = 'text/html; charset=utf-8';
75
        }
76
    }
77
78 2
    private function renderView(ResourceObject $ro)
79
    {
80
        $template = $this->load($ro);
81 15
82
        return $template ? $template->render($this->buildBody($ro)) : '';
83 15
    }
84
85
    private function renderRedirectView(ResourceObject $ro)
86 14
    {
87
        $url = $ro->headers['Location'];
88 14
89 14
        return $this->twig->render($this->redirectPage, ['url' => $url]);
90 10
    }
91 10
92
    /**
93 10
     * @return null|\Twig\TemplateWrapper
94
     */
95
    private function load(ResourceObject $ro)
96 4
    {
97
        try {
98
            return $this->loadTemplate($ro);
99 14
        } catch (LoaderError $e) {
100
            if ($ro->code === 200) {
101 14
                throw new Exception\TemplateNotFound($e->getMessage(), 500, $e);
102 1
            }
103
        }
104
    }
105 13
106
    private function isNoContent(ResourceObject $ro) : bool
107
    {
108 11
        return $ro->code === Code::NO_CONTENT || $ro->view === '';
109
    }
110 11
111 11
    private function isRedirect(ResourceObject $ro) : bool
112
    {
113 11
        return \in_array($ro->code, [
114
            Code::MOVED_PERMANENTLY,
115
            Code::FOUND,
116
            Code::SEE_OTHER,
117
            Code::TEMPORARY_REDIRECT,
118
            Code::PERMANENT_REDIRECT,
119
        ], true) && isset($ro->headers['Location']);
120
    }
121
122
    private function loadTemplate(ResourceObject $ro) : TemplateWrapper
123
    {
124
        $loader = $this->twig->getLoader();
125
        if ($loader instanceof FilesystemLoader) {
126
            $classFile = $this->getReflection($ro)->getFileName();
127
            $templateFile = ($this->templateFinder)($classFile);
128
129
            return $this->twig->load($templateFile);
130
        }
131
132
        return $this->twig->load($this->getReflection($ro)->name . self::EXT);
133
    }
134
135
    private function getReflection(ResourceObject $ro) : \ReflectionClass
136
    {
137
        if ($ro instanceof WeavedInterface) {
138
            return (new \ReflectionClass($ro))->getParentClass();
139
        }
140
141
        return new \ReflectionClass($ro);
142
    }
143
144
    private function buildBody(ResourceObject $ro) : array
145
    {
146
        $body = \is_array($ro->body) ? $ro->body : [];
147
        $body += ['_ro' => $ro];
148
149
        return $body;
150
    }
151
}
152