Skip to content

Commit

Permalink
feat: add costume directive use by Templator (#384)
Browse files Browse the repository at this point in the history
  • Loading branch information
SonyPradana authored Sep 14, 2024
1 parent 439fcb3 commit 5966265
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/System/View/Exceptions/DirectiveCanNotBeRegister.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace System\View\Exceptions;

/**
* @internal
*/
final class DirectiveCanNotBeRegister extends \InvalidArgumentException
{
public function __construct(string $name, string $use_by)
{
parent::__construct("Directive '$name' cant be use, this has been use in '$use_by'.");
}
}
16 changes: 16 additions & 0 deletions src/System/View/Exceptions/DirectiveNotRegister.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace System\View\Exceptions;

/**
* @internal
*/
final class DirectiveNotRegister extends \InvalidArgumentException
{
public function __construct(string $name)
{
parent::__construct("Directive '$name' is not registered.");
}
}
2 changes: 2 additions & 0 deletions src/System/View/Templator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use System\View\Templator\BreakTemplator;
use System\View\Templator\CommentTemplator;
use System\View\Templator\ContinueTemplator;
use System\View\Templator\DirectiveTemplator;
use System\View\Templator\EachTemplator;
use System\View\Templator\IfTemplator;
use System\View\Templator\IncludeTemplator;
Expand Down Expand Up @@ -132,6 +133,7 @@ public function templates(string $template): string
SectionTemplator::class,
IncludeTemplator::class,
PHPTemplator::class,
DirectiveTemplator::class,
NameTemplator::class,
IfTemplator::class,
EachTemplator::class,
Expand Down
75 changes: 75 additions & 0 deletions src/System/View/Templator/DirectiveTemplator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace System\View\Templator;

use System\View\AbstractTemplatorParse;
use System\View\Exceptions\DirectiveCanNotBeRegister;
use System\View\Exceptions\DirectiveNotRegister;

class DirectiveTemplator extends AbstractTemplatorParse
{
/**
* @var array<string, \Closure>
*/
private static array $directive = [];

/**
* Excludes list of directive alredy use by Templator.
*
* @var array<string, string>
*/
public static array $excludeList = [
'break' => BreakTemplator::class,
'continue' => ContinueTemplator::class,
'else' => IfTemplator::class,
'extend' => SectionTemplator::class,
'foreach' => EachTemplator::class,
'if' => IfTemplator::class,
'include' => IncludeTemplator::class,
'php' => PHPTemplator::class,
'raw' => NameTemplator::class,
'section' => SectionTemplator::class,
'set' => SetTemplator::class,
'use' => UseTemplator::class,
];

public static function register(string $name, \Closure $callable): void
{
if (array_key_exists($name, self::$excludeList)) {
throw new DirectiveCanNotBeRegister($name, self::$excludeList[$name]);
}

self::$directive[$name] = $callable;
}

public static function call(string $name, mixed ...$parameters): string
{
if (false === array_key_exists($name, self::$directive)) {
throw new DirectiveNotRegister($name);
}

$callback = self::$directive[$name];

return (string) $callback(...$parameters);
}

public function parse(string $template): string
{
return preg_replace_callback(
'/{%\s*(\w+)\((.*?)\)\s*%}/',
function ($matches) {
$name = $matches[1];
$params = explode(',', $matches[2]);
$params = array_map(fn ($param) => ltrim($param), $params);

return array_key_exists($name, self::$excludeList)
? $matches[0]
: '<?php echo System\View\Templator\DirectiveTemplator::call(\'' . $name . '\', ' . implode(', ', $params) . '); ?>'
;
},
$template
);
}
}
47 changes: 47 additions & 0 deletions tests/View/Templator/DirectiveTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace System\Test\View\Templator;

use PHPUnit\Framework\TestCase;
use System\View\Exceptions\DirectiveCanNotBeRegister;
use System\View\Exceptions\DirectiveNotRegister;
use System\View\Templator;
use System\View\Templator\DirectiveTemplator;
use System\View\TemplatorFinder;

final class DirectiveTest extends TestCase
{
/**
* @test
*/
public function itCanRenderEachBreak()
{
DirectiveTemplator::register('sum', fn ($a, $b): int => $a + $b);
$templator = new Templator(new TemplatorFinder([__DIR__], ['']), __DIR__);
$out = $templator->templates('<html><head></head><body>{% sum(1, 2) %}</body></html>');
$this->assertEquals("<html><head></head><body><?php echo System\View\Templator\DirectiveTemplator::call('sum', 1, 2); ?></body></html>", $out);
}

/**
* @test
*/
public function itThowExcaptionDueDirectiveNotRegister()
{
$this->expectException(DirectiveNotRegister::class);
DirectiveTemplator::call('unknow', 0);
}

public function itCanNotRegisterDirective(): void
{
$this->expectException(DirectiveCanNotBeRegister::class);
DirectiveTemplator::register('include', fn ($file): string => $file);
}

public function itCanRegisterAndCallDirective(): void
{
DirectiveTemplator::register('sum', fn ($a, $b): int => $a + $b);
$this->assertEquals(2, DirectiveTemplator::call('sum', 1, 1));
}
}

0 comments on commit 5966265

Please sign in to comment.