Skip to content

Commit

Permalink
Merge pull request #7 from PhantPHP/email-builder
Browse files Browse the repository at this point in the history
Email builder service
  • Loading branch information
lennyrouanet authored Mar 29, 2024
2 parents ca060aa + 49e259f commit 4f2b4c8
Show file tree
Hide file tree
Showing 12 changed files with 363 additions and 13 deletions.
12 changes: 0 additions & 12 deletions component/Port/EmailBuilder.php

This file was deleted.

84 changes: 84 additions & 0 deletions component/Service/EmailBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

declare(strict_types=1);

namespace Phant\EmailSender\Service;

use Twig\Environment as Twig;
use Twig\Loader\FilesystemLoader;

class EmailBuilder
{
public const TemplateEmail = 'layout.twig';
public const TemplateComponentCta = 'component/cta.twig';
public const TemplateComponentOtp = 'component/otp.twig';
public const TemplateComponentMeta = 'component/meta.twig';

protected Twig $twig;

public function __construct()
{
$loader = new FilesystemLoader(__DIR__ . '/../Template/');

$this->twig = new Twig($loader, [
'debug' => true,
'auto_reload' => true,
]);
}

public function build(
string $bodyHtml,
?string $headerLogo,
?string $footerLogo,
?string $footerHtml
): string {
return $this->twig->render(
self::TemplateEmail,
[
'body_html' => $bodyHtml,
'header_logo' => $headerLogo,
'footer_logo' => $footerLogo,
'footer_html' => $footerHtml,
]
);
}

public function buildCta(
string $url,
string $label,
?string $backgroundColor = '#1E88E5',
?string $textColor = '#ffffff'
): string {
return $this->twig->render(
self::TemplateComponentCta,
[
'url' => $url,
'label' => $label,
'background_color' => $backgroundColor,
'text_color' => $textColor,
]
);
}

public function buildOtp(
string $otp
): string {
return $this->twig->render(
self::TemplateComponentOtp,
[
'otp' => $otp,
]
);
}

public function buildMeta(
array $metas
): string {
return $this->twig->render(
self::TemplateComponentMeta,
[
'metas' => $metas,
]
);
}
}
21 changes: 21 additions & 0 deletions component/Template/component/cta.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<table width="100%" cellspacing="0" cellpadding="0">
<tr>
<td width="100%" height="15"></td>
</tr>
<tr>
<td>
<table cellspacing="0" cellpadding="0">
<tr>
<td bgcolor="{{ background_color }}" style="border-radius:5px;">
<a href="{{ url }}" target="_blank" style="display:inline-block;padding:5px 15px;border:1px solid {{ background_color }};border-radius:5px;font-family:Helvetica,Arial,sans-serif,sans-serif;font-size:14px;color:{{ text_color }};text-decoration:none;font-weight:bold">
{{ label }}
</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="100%" height="30"></td>
</tr>
</table>
10 changes: 10 additions & 0 deletions component/Template/component/meta.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% if metas %}
<table style="margin:20px 0 0 0;border-collapse:separate;border-spacing:5px;font-size:12px;">
{% for key, value in metas %}
<tr>
<th align="left" valign="top">{{ key }}</th>
<td align="left" valign="top">{{ value }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
16 changes: 16 additions & 0 deletions component/Template/component/otp.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

<table width="100%" cellspacing="0" cellpadding="0">
<tr>
<td width="100%" height="30"></td>
</tr>
<tr>
<td align="center">
<div style="text-align:center;color:#000000;font-size:34px;letter-spacing:10px">
<b>{{ otp }}</b>
</div>
</td>
</tr>
<tr>
<td width="100%" height="30"></td>
</tr>
</table>
72 changes: 72 additions & 0 deletions component/Template/layout.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{{ subject }}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<style type="text/css">
*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
body{font-family:arial}
table{margin:0 auto}
div,a,li,td{-webkit-text-size-adjust:none}
@media only screen and (max-width:640px){table[class=full]{width:100%!important}}
</style>
</body>
</head>
<body style="margin:0;background-color:#fcfcfc;">
<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td height="30" width="100%"></td>
</tr>
<tr>
<td align="center">
<table align="center" border="0" cellpadding="0" cellspacing="0" class="full" width="570" style="padding:0px 5px">
<tbody>
{% if header_logo %}
<tr>
<td width="100%" valign="middle" align="center" style="text-align:center">
<img src="{{ header_logo }}" alt="" width="150" height="32" style="vertical-align:bottom;border:0px solid;max-width:100%;width:auto;height:32px;outline:none !important"/>
</td>
</tr>
<tr>
<td width="100%" height="20"></td>
</tr>
{% endif %}
<tr>
<td width="100%" valign="middle" align="left" bgcolor="#FFFFFF" style="background-color:#ffffff;border:solid 1px #e8e8e8;border-radius:3px;box-shadow:0 0 15px rgba(0,0,0,.03);padding:20px;font-family:Helvetica,Arial,sans-serif;font-size:14px;line-height:24px;color:#000000">

{{ body_html|raw }}

</td>
</tr>
{% if footer_logo or footer_html %}
<tr>
<td width="100%" height="20"></td>
</tr>
<tr>
<td width="100%" valign="middle" align="center" style="padding:20px;font-family:Helvetica,Arial,sans-serif;font-size:11px;line-height:16px;color:#999999;text-align:center">

{% if footer_logo %}
<img src="{{ footer_logo }}" alt="" width="80" height="16" style="vertical-align:bottom;border:0px solid;max-width:100%;width:auto;height:16px;outline:none !important"/><br/>
{% endif %}

{% if footer_logo and footer_html %}
<br/>
{% endif %}

{{ footer_html|raw }}

</td>
</tr>
{% endif %}
</tbody>
</table>
</td>
</tr>
<tr>
<td height="30" width="100%"></td>
</tr>
</tbody>
</table>
</html>
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"php": ">=8.1",
"phant/data-structure": "4.*",
"phant/domain-name": "2.*",
"guzzlehttp/guzzle": "^7.4"
"guzzlehttp/guzzle": "^7.4",
"twig/twig": "^3.8"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
Expand Down
35 changes: 35 additions & 0 deletions demo/build-email-cta.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

include '../vendor/autoload.php';

use Phant\EmailSender\Service\EmailBuilder;

$emailBuilder = new EmailBuilder();

$bodyHtml = nl2br(
'Hello,
Would you like to find out more about our work?
Visit our Github page:'
);
$bodyHtml .= $emailBuilder->buildCta(
'https://github.com/PhantPHP',
'Github'
);
$bodyHtml .= nl2br(
'Thank you for your trust,
The Phant team'
);

$html = $emailBuilder->build(
$bodyHtml,
'image/logo.png',
'image/logo.png',
nl2br(
'Made with passion, in France
© Phant ' . date('Y')
)
);

echo $html;
29 changes: 29 additions & 0 deletions demo/build-email-information.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

include '../vendor/autoload.php';

use Phant\EmailSender\Service\EmailBuilder;

$emailBuilder = new EmailBuilder();

$bodyHtml = nl2br(
'<b>Lorem ipsum dolor sit amet</b>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
);

$html = $emailBuilder->build(
$bodyHtml,
'image/logo.png',
'image/logo.png',
nl2br(
'Made with passion, in France
© Phant ' . date('Y')
)
);

echo $html;
37 changes: 37 additions & 0 deletions demo/build-email-otp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

include '../vendor/autoload.php';

use Phant\EmailSender\Service\EmailBuilder;

$emailBuilder = new EmailBuilder();

$bodyHtml = nl2br(
'Hello,
Here is the verification code you requested :'
);
$bodyHtml .= $emailBuilder->buildOtp('123456');
$bodyHtml .= nl2br(
'This single-use code will expire in 15 minutes.
Thank you for your trust,
The Phant team'
);
$bodyHtml .= $emailBuilder->buildMeta([
'IP address' => $_SERVER['REMOTE_ADDR'],
'Browser' => $_SERVER['HTTP_USER_AGENT'],
'Request date' => date('Y/m/d H:i:s'),
]);

$html = $emailBuilder->build(
$bodyHtml,
'image/logo.png',
'image/logo.png',
nl2br(
'Made with passion, in France
© Phant ' . date('Y')
)
);

echo $html;
Binary file added demo/image/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 57 additions & 0 deletions test/Service/EmailBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

namespace Test\Service;

use Phant\EmailSender\Service\EmailBuilder;

final class EmailBuilderTest extends \PHPUnit\Framework\TestCase
{
protected EmailBuilder $fixture;

public function setUp(): void
{
$this->fixture = new EmailBuilder();
}

public function testBuild(): void
{
$html = $this->fixture->build(
'<b>Lorem ipsum dolor sit amet</b>',
'image/logo.png',
'image/logo.png',
'<b>Lorem ipsum dolor sit amet</b>'
);

$this->assertIsString($html);
}

public function testBuildCta(): void
{
$html = $this->fixture->buildCta(
'https://github.com/PhantPHP',
'Github',
'#000000',
'#FFFFFF'
);

$this->assertIsString($html);
}

public function testBuildOtp(): void
{
$html = $this->fixture->buildOtp('123456');

$this->assertIsString($html);
}

public function testBuildMeta(): void
{
$html = $this->fixture->buildMeta([
'key' => 'value',
]);

$this->assertIsString($html);
}
}

0 comments on commit 4f2b4c8

Please sign in to comment.