diff --git a/Contract/RenderableInterface.php b/Contract/RenderableInterface.php index ea1874e45..0415d4366 100644 --- a/Contract/RenderableInterface.php +++ b/Contract/RenderableInterface.php @@ -30,9 +30,11 @@ interface RenderableInterface /** * Get the evaluated contents of the object. * + * @param mixed ...$data Data to pass to renderer + * * @return string Returns rendered output * * @since 1.0.0 */ - public function render() : string; + public function render(...$data) : string; } diff --git a/Message/Http/HttpResponse.php b/Message/Http/HttpResponse.php index e92e66791..b91d32796 100644 --- a/Message/Http/HttpResponse.php +++ b/Message/Http/HttpResponse.php @@ -106,7 +106,7 @@ final class HttpResponse extends ResponseAbstract implements RenderableInterface * * @since 1.0.0 */ - public function render(bool $optimize = false) : string + public function render(...$data) : string { $types = $this->header->get('Content-Type'); @@ -116,7 +116,7 @@ final class HttpResponse extends ResponseAbstract implements RenderableInterface } } - return $this->getRaw($optimize); + return $this->getRaw($data[0]); } /** @@ -196,4 +196,14 @@ final class HttpResponse extends ResponseAbstract implements RenderableInterface return $result; } + + public function endAllOutputBuffering() : void + { + $this->header->push(); + + $levels = \ob_get_level(); + for ($i = 0; $i < $levels; ++$i) { + \ob_end_clean(); + } + } } diff --git a/Model/Html/Head.php b/Model/Html/Head.php index 321bd20b5..55e99fa35 100644 --- a/Model/Html/Head.php +++ b/Model/Html/Head.php @@ -142,11 +142,13 @@ final class Head implements RenderableInterface /** * Get the evaluated contents of the object. * + * @param mixed ...$data Data to pass to renderer + * * @return string * * @since 1.0.0 */ - public function render() : string + public function render(...$data) : string { $head = ''; $head .= $this->meta->render(); diff --git a/Model/Html/Meta.php b/Model/Html/Meta.php index 527809b8a..46c11637a 100644 --- a/Model/Html/Meta.php +++ b/Model/Html/Meta.php @@ -227,7 +227,7 @@ final class Meta implements RenderableInterface /** * {@inheritdoc} */ - public function render() : string + public function render(...$data) : string { return (\count($this->keywords) > 0 ? '' : '') . (!empty($this->author) ? '' : '') diff --git a/Views/ViewAbstract.php b/Views/ViewAbstract.php index be72be635..65663f67a 100644 --- a/Views/ViewAbstract.php +++ b/Views/ViewAbstract.php @@ -35,6 +35,14 @@ abstract class ViewAbstract implements RenderableInterface */ private const BASE_PATH = __DIR__ . '/../..'; + /** + * Output is buffered + * + * @var bool + * @since 1.0.0 + */ + public bool $isBuffered = true; + /** * Template. * @@ -230,7 +238,9 @@ abstract class ViewAbstract implements RenderableInterface $ob = ''; try { - \ob_start(); + if ($this->isBuffered) { + \ob_start(); + } $path = $this->template; if (!\is_file($path)) { @@ -239,13 +249,48 @@ abstract class ViewAbstract implements RenderableInterface /** @noinspection PhpIncludeInspection */ $includeData = include $path; - $ob = (string) \ob_get_clean(); + + if ($this->isBuffered) { + $ob = (string) \ob_get_clean(); + } if (\is_array($includeData)) { $ob = (string) \json_encode($includeData); } } catch (\Throwable $e) { - \ob_end_clean(); + if ($this->isBuffered) { + \ob_end_clean(); + } + + $ob = ''; + } finally { + return $ob; + } + } + + /** + * Very similar to render, except that it executes the template file and returns its response as is. + * This allows to build the template as any datatype (e.g. pdf). + * + * @param mixed ...$data Data to pass to build + * + * @return mixed + * + * @since 1.0.0 + */ + public function build(...$data) : mixed + { + $ob = ''; + + try { + $path = $this->template; + if (!\is_file($path)) { + throw new PathException($path); + } + + /** @noinspection PhpIncludeInspection */ + $ob = include $path; + } catch (\Throwable $e) { $ob = ''; } finally { return $ob;