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;