Skip to content

Commit

Permalink
feat: template support add filter and directive
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Nov 7, 2021
1 parent 756da34 commit 0f32934
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 11 deletions.
34 changes: 32 additions & 2 deletions app/Lib/Template/Compiler/AbstractCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@ abstract class AbstractCompiler implements CompilerInterface
public string $openTag = '{{';
public string $closeTag = '}}';

/**
* custom filter for handle result.
*
* @var array{string, callable(mixed): string}
*/
public array $customFilters = [];

/**
* custom directive, control statement token.
*
* eg: implement include()
*
* @var array
* @var array{string, callable(string, string): string}
*/
public array $customTokens = [];
public array $customDirectives = [];

/**
* @param string $open
Expand All @@ -42,4 +49,27 @@ public function setOpenCloseTag(string $open, string $close): self
return $this;
}

/**
* @param string $name
* @param callable $filter
*
* @return $this
*/
public function addFilter(string $name, callable $filter): self
{
$this->customFilters[$name] = $filter;
return $this;
}

/**
* @param string $name
* @param callable $handler
*
* @return $this
*/
public function addDirective(string $name, callable $handler): self
{
$this->customDirectives[$name] = $handler;
return $this;
}
}
16 changes: 12 additions & 4 deletions app/Lib/Template/Compiler/PregCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
namespace Inhere\Kite\Lib\Template\Compiler;

use function addslashes;
use function array_keys;
use function explode;
use function implode;
use function is_numeric;
use function preg_match;
use function preg_replace_callback;
use function strlen;
use function substr;
use function trim;

/**
Expand Down Expand Up @@ -58,8 +60,6 @@ public function compile(string $tplCode): string
return $tplCode;
}

$this->prevTokenType = '';

$openTagE = $this->openTagE;
$closeTagE = $this->closeTagE;

Expand Down Expand Up @@ -109,9 +109,12 @@ public function parseCodeBlock(string $block): string
$isInline = !str_contains($trimmed, "\n");
$kwPattern = Token::getBlockNamePattern();

$directive = '';
$userPattern = Token::buildDirectivePattern(array_keys($this->customDirectives));

// default is define statement.
$type = Token::T_DEFINE;
$open = self::PHP_TAG_OPEN . "\n";
$open = self::PHP_TAG_OPEN . ($isInline ? ' ' : "\n");
$close = ($isInline ? ' ' : "\n") . self::PHP_TAG_CLOSE;

if ($trimmed[0] === '=') {
Expand Down Expand Up @@ -143,14 +146,19 @@ public function parseCodeBlock(string $block): string
$close = ': ' . self::PHP_TAG_CLOSE;
}
}
} elseif ($userPattern && preg_match($userPattern, $trimmed, $matches)) {
$directive = $type = $matches[1];
$handlerFn = $this->customDirectives[$directive];

$trimmed = $handlerFn(substr($trimmed, strlen($directive)), $directive);
} elseif ($isInline && !str_contains($trimmed, '=')) {
// inline and not define expr, as echo expr.
$type = Token::T_ECHO;
$open = self::PHP_TAG_ECHO1 . ' ';
}

// not need continue handle
if (Token::isAloneToken($type)) {
if ($directive || Token::isAloneToken($type)) {
return $open . $trimmed . $close;
}

Expand Down
16 changes: 15 additions & 1 deletion app/Lib/Template/Compiler/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,21 @@ class Token
public static function getBlockNamePattern(): string
{
// ~^(if|elseif|else|endif|for|endfor|foreach|endforeach)~
return '~^(' . implode('|', self::BLOCK_NAMES) . ')[^\w-]~';
return self::buildDirectivePattern(self::BLOCK_NAMES);
}

/**
* @param string[] $names
*
* @return string
*/
public static function buildDirectivePattern(array $names): string
{
if (!$names) {
return '';
}

return '~^(' . implode('|', $names) . ')[^\w-]~';
}

/**
Expand Down
36 changes: 33 additions & 3 deletions app/Lib/Template/EasyTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ public function __construct(array $config = [])
parent::__construct($config);

$this->compiler = new PregCompiler();
$this->compiler->addDirective(
'include',
function (string $body, string $name) {
return 'echo $this->' . $name . $body;
}
);
}

/**
Expand Down Expand Up @@ -64,6 +70,19 @@ public function renderFile(string $tplFile, array $tplVars): string
return $this->doRenderFile($phpFile, $tplVars);
}

/**
* @param string $tplFile
* @param array $tplVars
*
* @return string
*/
protected function include(string $tplFile, array $tplVars): string
{
$phpFile = $this->compileFile($tplFile);

return $this->doRenderFile($phpFile, $tplVars);
}

/**
* @param string $tplFile
*
Expand Down Expand Up @@ -95,16 +114,27 @@ public function compileCode(string $code): string
return $this->compiler->compile($code);
}

/**
* @param string $name
* @param callable $filter
*
* @return $this
*/
public function addFilter(string $name, callable $filter): self
{
$this->compiler->addFilter($name, $filter);
return $this;
}

/**
* @param string $name
* @param callable $handler
*
* @return $this
*/
public function addFilter(string $name, callable $handler): self
public function addDirective(string $name, callable $handler): self
{
//
// $this->compiler->addFilter();
$this->compiler->addDirective($name, $handler);
return $this;
}

Expand Down
2 changes: 1 addition & 1 deletion app/Lib/Template/easy-template.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Text2Template
# EasyTemplate

## Using the filters

Expand Down
25 changes: 25 additions & 0 deletions test/unittest/Lib/Template/PregCompilerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public function testCompileCode_inline_echo():void
['{{ $name }}', '<?= $name ?>'],
['{{ $name ?: "inhere" }}', '<?= $name ?: "inhere" ?>'],
['{{ $name ?? "inhere" }}', '<?= $name ?? "inhere" ?>'],
['{{ some_func() }}', '<?= some_func() ?>'],
['{{ $this->include("header.tpl") }}', '<?= $this->include("header.tpl") ?>'],
];
foreach ($simpleTests as [$in, $out]) {
$this->assertEquals($out, $p->compile($in));
Expand Down Expand Up @@ -107,6 +109,29 @@ public function testCompileCode_inline_echo():void
,$compiled);
}

public function testCompile_customDirective():void
{
$p = new PregCompiler();
$p->addDirective('include', function (string $body, string $name) {
return 'echo $this->' . $name . $body;
});

$tests = [
['{{ include("header.tpl") }}', '<?php echo $this->include("header.tpl") ?>'],
['{{ include("header.tpl", [
"key1" => "value1",
]) }}', '<?php
echo $this->include("header.tpl", [
"key1" => "value1",
])
?>'],
];
foreach ($tests as [$in, $out]) {
$this->assertEquals($out, $p->compile($in));
}

}

public function testCompile_if_block():void
{
$p = new PregCompiler();
Expand Down

0 comments on commit 0f32934

Please sign in to comment.