Skip to content

Commit

Permalink
Implement template execution error handling
Browse files Browse the repository at this point in the history
Closes #16.
  • Loading branch information
0xEAB committed Jul 29, 2024
1 parent 53f4c20 commit aa7be9b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 4 deletions.
19 changes: 15 additions & 4 deletions tools/ddct-src/Util/TemplateEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ final class TemplateEngine
private const phpPrintTag = '<?= ';
private const phpCloseTagLF = " ?>\n\n";
private const phpCloseTag = " ?>\n";
private const phpIncludeOpenTag = '<?php eval($_te->getCompiledTemplate(\'';
private const phpIncludeCloseTag = '\'))?>';
private const phpIncludeOpenTag = '<?php $_eh->push(\'';
private const phpIncludeMiddle = '\');eval($_te->getCompiledTemplate(\'';
private const phpIncludeCloseTag = '\'));$_eh->pop()?>';
private const tab = "\t";

private array $cache = [];
private TemplateExecutionErrorHandlers $errorHandlers;

public function __construct(
private string $templatesDir,
) {
$this->errorHandlers = new TemplateExecutionErrorHandlers();
}

public function compile(string $templateName): void
Expand Down Expand Up @@ -104,6 +107,8 @@ public function compile(string $templateName): void
$line = substr($line, 4, ($lineLength - 8));
unset($lineLength);
$result .= $line;
$result .= self::phpIncludeMiddle;
$result .= $line;
$result .= self::phpIncludeCloseTag;
continue;
}
Expand Down Expand Up @@ -131,7 +136,7 @@ public function compileIfNotInCache(string $templateName): void
// Shall write compiled template to file?
if (isset($_SERVER['TPL_DEBUG']) && ($_SERVER['TPL_DEBUG'] === 'file')) {
file_put_contents(
$this->makeTemplatePath($templateName) . '.compiled-tpl.php',
$this->makeTemplatePath($templateName) . TemplateExecutionErrorHandlers::fileEndingCompiledTemplate,
$this->cache[$templateName]
);
}
Expand Down Expand Up @@ -173,16 +178,22 @@ public function execute(string $templateName, array $variables): void

private function executeTemplate(string $templateName, array $variables)
{
(function (TemplateEngine $_te, string $_tplCode, array $_variables) {
$this->errorHandlers->push($templateName);

(function (TemplateEngine $_te, TemplateExecutionErrorHandlers $_eh, string $_tplCode, array $_variables) {
foreach ($_variables as $_name => $_value) {
$$_name = $_value;
}
eval($_tplCode);
})(
$this,
$this->errorHandlers,
$this->cache[$templateName],
$variables,
);

$this->errorHandlers->pop();
$this->errorHandlers->resetAndCheck();
}

private function makeTemplatePath(string $templateName): string
Expand Down
41 changes: 41 additions & 0 deletions tools/ddct-src/Util/TemplateExecutionErrorHandlers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace DlangDockerized\Ddct\Util;

use Exception;
use LogicException;

final class TemplateExecutionErrorHandlers
{
public const fileEndingCompiledTemplate = '.compiled-tpl.php';

private int $counter = 0;

public function push(string $templateName): void
{
$fileEnding = self::fileEndingCompiledTemplate;
set_error_handler(function ($errno, $errstr, $errfile, $errline) use ($templateName, $fileEnding) {
throw new Exception(
"Template execution error (code: {$errno})"
. " in `{$templateName}{$fileEnding}`({$errline}): {$errstr}"
);
}, E_ALL);

++$this->counter;
}

public function pop(): void
{
restore_error_handler();
--$this->counter;
}

public function resetAndCheck(): void
{
if ($this->counter !== 0) {
throw new LogicException('Popped less error handlers than pushed.');
}
}
}

0 comments on commit aa7be9b

Please sign in to comment.