Renderer::render()   A
last analyzed

Complexity

Conditions 6
Paths 11

Size

Total Lines 28
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 18
c 1
b 0
f 0
dl 0
loc 28
ccs 16
cts 16
cp 1
rs 9.0444
cc 6
nc 11
nop 2
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Conia\Renderer\Boiler;
6
7
use Conia\Boiler\Engine;
8
use Conia\Chuck\Factory;
9
use Conia\Chuck\Renderer\Renderer as RendererInterface;
10
use Conia\Chuck\Response;
11
use Throwable;
12
use Traversable;
13
14
/**
15
 * @psalm-api
16
 *
17
 * @psalm-import-type DirsInput from \Conia\Boiler\Engine
18
 */
19
class Renderer implements RendererInterface
20
{
21
    /**
22
     * @psalm-param DirsInput $dirs
23
     * @psalm-param list<class-string> $whitelist
24
     */
25 9
    public function __construct(
26
        protected Factory $factory,
27
        protected string|array $dirs,
28
        protected array $defaults = [],
29
        protected array $whitelist = [],
30
        protected bool $autoescape = true,
31
    ) {
32 9
    }
33
34 9
    public function render(mixed $data, mixed ...$args): string
35
    {
36 9
        if ($data instanceof Traversable) {
37 1
            $context = iterator_to_array($data);
38 8
        } elseif (is_array($data)) {
39 7
            $context = $data;
40
        } else {
41 1
            throw new RendererException('The template context must be an array or a Traversable');
42
        }
43
44
        try {
45 8
            $templateName = (string)$args[0];
46 7
            assert(!empty($templateName));
47 1
        } catch (Throwable) {
48 1
            throw new RendererException('The template must be passed to the renderer');
49
        }
50
51 7
        if (is_string($this->dirs)) {
52 1
            $this->dirs = [$this->dirs];
53
        } else {
54 6
            if (count($this->dirs) === 0) {
55 1
                throw new RendererException('Provide at least one template directory');
56
            }
57
        }
58
59 6
        $engine = $this->createEngine($this->dirs);
60
61 6
        return $engine->render($templateName, $context);
62
    }
63
64 9
    public function response(mixed $data, mixed ...$args): Response
65
    {
66 9
        $response = Response::fromFactory($this->factory)->status(
67 9
            (int)($args['statusCode'] ?? 200),
68 9
            (string)($args['reasonPhrase'] ?? ''),
69 9
        );
70
71 9
        return $response
72 9
            ->header('Content-Type', (string)(($args['contentType'] ?? null) ?: 'text/html'))
73 9
            ->body($this->render($data, ...$args));
74
    }
75
76
    /** @psalm-param DirsInput $dirs */
77 6
    protected function createEngine(string|array $dirs): Engine
78
    {
79 6
        return new Engine($dirs, $this->defaults, $this->whitelist, $this->autoescape);
80
    }
81
}
82