Skip to content

Commit

Permalink
auto extract template variables on send test modal
Browse files Browse the repository at this point in the history
  • Loading branch information
danilopolani committed Mar 16, 2024
1 parent 1356a34 commit cd68603
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 1 deletion.
51 changes: 51 additions & 0 deletions src/Helpers/TemplateManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace MailCarrier\Helpers;

use MailCarrier\Models\Template;
use Twig\Environment;
use Twig\Loader\ArrayLoader;
use Twig\Source;

class TemplateManager
{
public function __construct(protected Template $template)
{
//
}

public static function make(Template $template): static
{
return new static($template);

Check failure on line 19 in src/Helpers/TemplateManager.php

View workflow job for this annotation

GitHub Actions / PHP 8.1

Unsafe usage of new static().

Check failure on line 19 in src/Helpers/TemplateManager.php

View workflow job for this annotation

GitHub Actions / PHP 8.2

Unsafe usage of new static().

Check failure on line 19 in src/Helpers/TemplateManager.php

View workflow job for this annotation

GitHub Actions / PHP 8.3

Unsafe usage of new static().
}

public function extractVariableNames(): array
{
$source = $this->template->layout?->content . $this->template->content;

$twig = new Environment(new ArrayLoader());
$nodes = $twig->parse(
$twig->tokenize(new Source($source, ''))
)->getNode('body')->getNode('0');

preg_match_all("|Twig\\\Node\\\Expression\\\NameExpression\(name\: '(.*)'|mi", (string) $nodes, $matches);

return array_values(array_unique($matches[1]));
}

protected function getLoader(): ArrayLoader
{
$mainFileName = sprintf('main-%d.html', $this->template->id);
$layoutFileName = !$this->template->layout_id ? null : sprintf('layout-%d.html', $this->template->layout_id);
$mainFileContent = !$this->template->layout_id ? $this->template->content : sprintf(
'{%% extends "%s" %%}{%% block content %%}%s{%% endblock %%}',
$layoutFileName,
$this->template->content,
);

return new ArrayLoader([
$mainFileName => $mainFileContent,
$layoutFileName => $this->template->layout?->content,
]);
}
}
11 changes: 10 additions & 1 deletion src/Resources/TemplateResource/Actions/SendTestAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Illuminate\Support\HtmlString;
use MailCarrier\Actions\SendMail;
use MailCarrier\Dto\SendMailDto;
use MailCarrier\Helpers\TemplateManager;

class SendTestAction extends Action
{
Expand All @@ -25,6 +26,7 @@ protected function setUp(): void

$this->label('Send test');
$this->icon('heroicon-o-paper-airplane');
$this->modalHeading('Send test email');
$this->modalSubmitActionLabel('Send');
$this->modalFooterActionsAlignment(Alignment::End);
$this->extraAttributes([
Expand All @@ -37,7 +39,14 @@ protected function setUp(): void
->required(),
Forms\Components\KeyValue::make('variables')
->keyLabel('Variable name')
->valueLabel('Variable value'),
->valueLabel('Variable value')
->valuePlaceholder('Fill or delete')
->default(
Arr::mapWithKeys(
TemplateManager::make($this->getRecord())->extractVariableNames(),

Check failure on line 46 in src/Resources/TemplateResource/Actions/SendTestAction.php

View workflow job for this annotation

GitHub Actions / PHP 8.1

Parameter #1 $template of static method MailCarrier\Helpers\TemplateManager::make() expects MailCarrier\Models\Template, Illuminate\Database\Eloquent\Model|null given.

Check failure on line 46 in src/Resources/TemplateResource/Actions/SendTestAction.php

View workflow job for this annotation

GitHub Actions / PHP 8.2

Parameter #1 $template of static method MailCarrier\Helpers\TemplateManager::make() expects MailCarrier\Models\Template, Illuminate\Database\Eloquent\Model|null given.

Check failure on line 46 in src/Resources/TemplateResource/Actions/SendTestAction.php

View workflow job for this annotation

GitHub Actions / PHP 8.3

Parameter #1 $template of static method MailCarrier\Helpers\TemplateManager::make() expects MailCarrier\Models\Template, Illuminate\Database\Eloquent\Model|null given.
fn (string $value) => [$value => null]
)
),
Forms\Components\Checkbox::make('enqueue'),
]);

Expand Down
69 changes: 69 additions & 0 deletions tests/Unit/TemplateManager/ExtractVariableNamesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

use MailCarrier\Helpers\TemplateManager;
use MailCarrier\Models\Layout;
use MailCarrier\Models\Template;

it('returns empty array if template has no variables', function () {
$template = new Template([
'content' => 'Hello',
]);

$output = TemplateManager::make($template)->extractVariableNames();

expect($output)->toBe([]);
});

it('returns all the variables of the template', function () {
$template = new Template([
'content' => <<<'TWIG'
Hello {{ name }},
<a href="{{ ctaUrl }}">
Sign in
</a>
{% if isPremium|default(false) %}
{{ tierLevel|title }}
{% endif %}
TWIG,
]);

$output = TemplateManager::make($template)->extractVariableNames();

expect($output)->toBe(['name', 'ctaUrl', 'isPremium', 'tierLevel']);
});

it('returns all the variables of the template along with its layout', function () {
$template = new Template([
'content' => <<<'TWIG'
Hello {{ name }},
<a href="{{ ctaUrl }}">
Sign in
</a>
{% if isPremium|default(false) %}
{{ tierLevel|title }}
{% endif %}
TWIG,
]);

$template->setRelation('layout', new Layout([
'content' => <<<'TWIG'
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>{{ headline }}</h1>
{% block content %}{% endblock %}
</body>
</html>
TWIG,
]));

$output = TemplateManager::make($template)->extractVariableNames();

expect($output)->toBe(['headline', 'name', 'ctaUrl', 'isPremium', 'tierLevel']);
});

0 comments on commit cd68603

Please sign in to comment.