ViewDispatcherService::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 3
1
<?php
2
3
namespace pjpawel\Magis;
4
5
use pjpawel\Magis\Exception\TemplateException;
6
use pjpawel\Magis\View\AbstractView;
7
use pjpawel\Magis\View\DirectView;
8
use pjpawel\Magis\View\MagicView;
9
10
/**
11
 * Class provides dispatcher to different views class modes,
12
 * should be used as Service in Dependency Injection
13
 *
14
 * @author Paweł Podgórski <[email protected]>
15
 */
16
class ViewDispatcherService
17
{
18
19
    /**
20
     * @var string Class namespace
21
     */
22
    private string $defaultViewClass;
23
    /**
24
     * @var string Absolute path to templates directory
25
     */
26
    private string $templateDir;
27
    /**
28
     * @var array<string, object> Services to inject into view
29
     */
30
    private array $services;
31
    /**
32
     * Dispatcher options of views mode
33
     * All classes must implement ViewInterface
34
     */
35
    public const VIEW_MODE = [
36
        'direct' => DirectView::class,
37
        'magic' => MagicView::class,
38
    ];
39
    /**
40
     * Allows to pass php template name without extension
41
     */
42
    private const DEFAULT_EXTENSION = '.php';
43
44
    /**
45
     * @param string $viewMode
46
     * @param string $templateDir
47
     * @param array<string, object> $services
48
     * @throws TemplateException
49
     */
50
    public function __construct(string $viewMode, string $templateDir, array $services = [])
51
    {
52
        $this->setDefaultViewMode($viewMode);
53
        $this->templateDir = $templateDir;
54
        $this->services = $services;
55
    }
56
57
    /**
58
     * @param string $templateName Template name e.g. 'index.php'
59
     * @param array<string, mixed> $params Params that will be used as variables.
60
     *  Key will be used as variable name, and value as var value
61
     * @param string|null $viewMode Set different view mode
62
     * @return string Rendered content
63
     * @throws TemplateException
64
     */
65
    public function render(string $templateName, array $params = [], ?string $viewMode = null): string
66
    {
67
        if ($viewMode === null) {
68
            $viewClass = $this->defaultViewClass;
69
        } else {
70
            $viewClass = $this->getViewClassFromMode($viewMode);
71
        }
72
        $this->ensureTemplateNameHasExtension($templateName);
73
74
        /** @var AbstractView $view */
75
        $view = new $viewClass($this->templateDir);
76
77
        foreach ($this->services as $name => $service) {
78
            $view->addService($name, $service);
79
        }
80
81
        return $view->render($templateName, $params);
82
    }
83
84
    /**
85
     * @param string $mode
86
     * @return void
87
     * @throws TemplateException
88
     */
89
    public function setDefaultViewMode(string $mode): void
90
    {
91
        $this->defaultViewClass = $this->getViewClassFromMode($mode);
92
    }
93
94
    /**
95
     * @param string $mode
96
     * @return string
97
     * @throws TemplateException
98
     */
99
    protected function getViewClassFromMode(string $mode): string
100
    {
101
        if (isset(self::VIEW_MODE[$mode])) {
102
            $class = self::VIEW_MODE[$mode];
103
        } elseif (false !== $key = array_search($mode, self::VIEW_MODE)) {
104
            $class = self::VIEW_MODE[$key];
105
        } else {
106
            throw new TemplateException('Unknown view mode ' . $mode);
107
        }
108
        if (!is_subclass_of($class, AbstractView::class)) {
109
            throw new TemplateException("View mode doesn't inherit from " . AbstractView::class);
110
        }
111
        return $class;
112
    }
113
114
    /**
115
     * @return string
116
     */
117
    public function getDefaultViewClass(): string
118
    {
119
        return $this->defaultViewClass;
120
    }
121
122
    /**
123
     * @param string $templateDir
124
     */
125
    public function setTemplateDir(string $templateDir): void
126
    {
127
        $this->templateDir = $templateDir;
128
    }
129
130
    /**
131
     * @return string
132
     */
133
    public function getTemplateDir(): string
134
    {
135
        return $this->templateDir;
136
    }
137
138
    /**
139
     * Service can be passed as :
140
     *  object: it will be passed directly
141
     *  string: service will be given from container //NOT NOW!
142
     *
143
     * @param string $alias
144
     * @param object $object   // Object or alias from container
145
     * @return void
146
     */
147
    public function addService(string $alias, object$object): void
148
    {
149
        $this->services[$alias] = $object;
150
    }
151
152
    /**
153
     * Provide possibility to pass name of template without php extension
154
     *
155
     * @param string $templateName
156
     * @return void
157
     */
158
    protected function ensureTemplateNameHasExtension(string &$templateName): void
159
    {
160
        if (!str_ends_with($templateName, self::DEFAULT_EXTENSION)) {
161
            $templateName .= self::DEFAULT_EXTENSION;
162
        }
163
    }
164
165
}