Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
42 / 42
100.00% covered (success)
100.00%
15 / 15
CRAP
100.00% covered (success)
100.00%
1 / 1
View
100.00% covered (success)
100.00%
42 / 42
100.00% covered (success)
100.00%
15 / 15
32
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
 hasTemplate
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTemplate
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getOutput
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isFile
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 isStream
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 getData
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTemplate
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
7
 setData
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 set
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 merge
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 filter
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 render
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\View;
15
16use Pop\Filter\FilterableTrait;
17use Pop\Utils;
18
19/**
20 * View class
21 *
22 * @category   Pop
23 * @package    Pop\View
24 * @author     Nick Sagona, III <dev@nolainteractive.com>
25 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
26 * @license    http://www.popphp.org/license     New BSD License
27 * @version    4.0.0
28 */
29class View extends Utils\ArrayObject
30{
31
32    use FilterableTrait;
33
34    /**
35     * View template object
36     * @var ?Template\TemplateInterface
37     */
38    protected ?Template\TemplateInterface $template = null;
39
40    /**
41     * Model data
42     * @var mixed
43     */
44    protected mixed $data = [];
45
46    /**
47     * View output string
48     * @var ?string
49     */
50    protected ?string $output = null;
51
52    /**
53     * Constructor
54     *
55     * Instantiate the view object
56     *
57     * @param  mixed  $template
58     * @param  ?array $data
59     * @param  mixed  $filters
60     */
61    public function __construct(mixed $template = null, ?array $data = null, mixed $filters = null)
62    {
63        if ($template !== null) {
64            $this->setTemplate($template);
65        }
66        if ($data !== null) {
67            parent::__construct($data);
68        }
69        if ($filters !== null) {
70            if (is_array($filters)) {
71                $this->addFilters($filters);
72            } else {
73                $this->addFilter($filters);
74            }
75        }
76    }
77
78    /**
79     * Has a view template
80     *
81     * @return bool
82     */
83    public function hasTemplate(): bool
84    {
85        return ($this->template !== null);
86    }
87
88    /**
89     * Get view template
90     *
91     * @return Template\TemplateInterface
92     */
93    public function getTemplate(): Template\TemplateInterface
94    {
95        return $this->template;
96    }
97
98    /**
99     * Get rendered output
100     *
101     * @return string
102     */
103    public function getOutput(): string
104    {
105        return $this->output;
106    }
107
108    /**
109     * Is view template a file
110     *
111     * @return bool
112     */
113    public function isFile(): bool
114    {
115        return (($this->template !== null) && ($this->template instanceof Template\File));
116    }
117
118    /**
119     * Is view template a stream
120     *
121     * @return bool
122     */
123    public function isStream(): bool
124    {
125        return (($this->template !== null) && ($this->template instanceof Template\Stream));
126    }
127
128    /**
129     * Get all model data
130     *
131     * @return array
132     */
133    public function getData(): array
134    {
135        return $this->data;
136    }
137
138    /**
139     * Get data
140     *
141     * @param  string $key
142     * @return mixed
143     */
144    public function get(string $key): mixed
145    {
146        return $this->data[$key] ?? null;
147    }
148
149    /**
150     * Set view template
151     *
152     * @param  mixed $template
153     * @return static
154     */
155    public function setTemplate(mixed $template): static
156    {
157        if (!($template instanceof Template\TemplateInterface)) {
158            // If a native PHP file template
159            if (((str_ends_with($template, '.phtml')) ||
160                    (substr($template, -5, 4) == '.php') ||
161                    (str_ends_with($template, '.php'))) && (strlen($template) <= 255) && (file_exists($template))) {
162                $template = new Template\File($template);
163            // If a string template, or a string template from a non-PHP file
164            } else {
165                $template = new Template\Stream($template);
166            }
167        }
168        $this->template = $template;
169        return $this;
170    }
171
172    /**
173     * Set all model data
174     *
175     * @param  array $data
176     * @return static
177     */
178    public function setData(array $data = []): static
179    {
180        $this->data = $data;
181        return $this;
182    }
183
184    /**
185     * Set model data
186     *
187     * @param  string $name
188     * @param  mixed  $value
189     * @return static
190     */
191    public function set(string $name, mixed $value): static
192    {
193        $this->data[$name] = $value;
194        return $this;
195    }
196
197    /**
198     * Merge new model data
199     *
200     * @param  array $data
201     * @return static
202     */
203    public function merge(array $data): static
204    {
205        $this->data = array_merge($this->data, $data);
206        return $this;
207    }
208
209    /**
210     * Filter values
211     *
212     * @param  mixed $values
213     * @return mixed
214     */
215    public function filter(mixed $values): mixed
216    {
217        foreach ($this->filters as $filter) {
218            if (is_array($values)) {
219                foreach ($values as $key => $value) {
220                    $values[$key] = $filter->filter($value, $key);
221                }
222            } else {
223                $values = [$filter->filter($values)];
224            }
225        }
226
227        return $values;
228    }
229
230    /**
231     * Render the view
232     *
233     * @throws Exception|Template\Exception
234     * @return ?string
235     */
236    public function render(): ?string
237    {
238        if ($this->template === null) {
239            throw new Exception('A template asset has not been assigned.');
240        }
241
242        if ($this->hasFilters()) {
243            $this->data = $this->filter($this->data);
244        }
245
246        $this->output = $this->template->render($this->data);
247        return $this->output;
248    }
249
250    /**
251     * Return rendered view as string
252     *
253     * @return string
254     */
255    public function __toString(): string
256    {
257        return $this->render();
258    }
259
260}