Skip to content

Commit a5f485a

Browse files
committed
[Mime] added classes for generating MIME messages
1 parent 91c5b14 commit a5f485a

File tree

102 files changed

+8205
-17
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+8205
-17
lines changed
+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Twig\Mime;
13+
14+
use League\HTMLToMarkdown\HtmlConverter;
15+
use Twig\Environment;
16+
17+
/**
18+
* @author Fabien Potencier <fabien@symfony.com>
19+
*
20+
* @experimental in 4.3
21+
*/
22+
final class Renderer
23+
{
24+
private $twig;
25+
private $context;
26+
private $converter;
27+
28+
public function __construct(Environment $twig, array $context = [])
29+
{
30+
$this->twig = $twig;
31+
$this->context = $context;
32+
if (class_exists(HtmlConverter::class)) {
33+
$this->converter = new HtmlConverter([
34+
'hard_break' => true,
35+
'strip_tags' => true,
36+
'remove_nodes' => 'head style',
37+
]);
38+
}
39+
}
40+
41+
public function render(TemplatedEmail $email): TemplatedEmail
42+
{
43+
$email = clone $email;
44+
45+
$vars = array_merge($this->context, $email->getContext(), [
46+
'email' => new WrappedTemplatedEmail($this->twig, $email),
47+
]);
48+
49+
if ($template = $email->getTemplate()) {
50+
$this->renderFull($email, $template, $vars);
51+
}
52+
53+
if ($template = $email->getTextTemplate()) {
54+
$email->text($this->twig->render($template, $vars));
55+
}
56+
57+
if ($template = $email->getHtmlTemplate()) {
58+
$email->html($this->twig->render($template, $vars));
59+
}
60+
61+
// if text body is empty, compute one from the HTML body
62+
if (!$email->getTextBody() && null !== $html = $email->getHtmlBody()) {
63+
$email->text($this->convertHtmlToText(\is_resource($html) ? stream_get_contents($html) : $html));
64+
}
65+
66+
return $email;
67+
}
68+
69+
private function renderFull(TemplatedEmail $email, string $template, array $vars): void
70+
{
71+
$template = $this->twig->load($template);
72+
73+
if ($template->hasBlock('subject', $vars)) {
74+
$email->subject($template->renderBlock('subject', $vars));
75+
}
76+
77+
if ($template->hasBlock('text', $vars)) {
78+
$email->text($template->renderBlock('text', $vars));
79+
}
80+
81+
if ($template->hasBlock('html', $vars)) {
82+
$email->html($template->renderBlock('html', $vars));
83+
}
84+
85+
if ($template->hasBlock('config', $vars)) {
86+
// we discard the output as we're only interested
87+
// in the side effect of calling email methods
88+
$template->renderBlock('config', $vars);
89+
}
90+
}
91+
92+
private function convertHtmlToText(string $html): string
93+
{
94+
if (null !== $this->converter) {
95+
return $this->converter->convert($html);
96+
}
97+
98+
return strip_tags($html);
99+
}
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Twig\Mime;
13+
14+
use Symfony\Component\Mime\Email;
15+
16+
/**
17+
* @author Fabien Potencier <fabien@symfony.com>
18+
*
19+
* @experimental in 4.3
20+
*/
21+
class TemplatedEmail extends Email
22+
{
23+
private $template;
24+
private $htmlTemplate;
25+
private $textTemplate;
26+
private $context = [];
27+
28+
public function template(?string $template): self
29+
{
30+
$this->template = $template;
31+
32+
return $this;
33+
}
34+
35+
public function textTemplate(?string $template): self
36+
{
37+
$this->textTemplate = $template;
38+
39+
return $this;
40+
}
41+
42+
public function htmlTemplate(?string $template): self
43+
{
44+
$this->htmlTemplate = $template;
45+
46+
return $this;
47+
}
48+
49+
public function getTemplate(): ?string
50+
{
51+
return $this->template;
52+
}
53+
54+
public function getTextTemplate(): ?string
55+
{
56+
return $this->textTemplate;
57+
}
58+
59+
public function getHtmlTemplate(): ?string
60+
{
61+
return $this->htmlTemplate;
62+
}
63+
64+
public function context(array $context): self
65+
{
66+
$this->context = $context;
67+
68+
return $this;
69+
}
70+
71+
public function getContext(): array
72+
{
73+
return $this->context;
74+
}
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Twig\Mime;
13+
14+
use Symfony\Component\Mime\Address;
15+
use Symfony\Component\Mime\NamedAddress;
16+
use Twig\Environment;
17+
18+
/**
19+
* @internal
20+
*
21+
* @author Fabien Potencier <fabien@symfony.com>
22+
*
23+
* @experimental in 4.3
24+
*/
25+
final class WrappedTemplatedEmail
26+
{
27+
private $twig;
28+
private $message;
29+
30+
public function __construct(Environment $twig, TemplatedEmail $message)
31+
{
32+
$this->twig = $twig;
33+
$this->message = $message;
34+
}
35+
36+
public function toName(): string
37+
{
38+
$to = $this->message->getTo()[0];
39+
40+
return $to instanceof NamedAddress ? $to->getName() : '';
41+
}
42+
43+
public function image(string $image, string $contentType = null): string
44+
{
45+
$file = $this->twig->getLoader()->getSourceContext($image);
46+
if ($path = $file->getPath()) {
47+
$this->message->embedFromPath($path, $image, $contentType);
48+
} else {
49+
$this->message->embed($file->getCode(), $image, $contentType);
50+
}
51+
52+
return 'cid:'.$image;
53+
}
54+
55+
public function attach(string $file, string $name = null, string $contentType = null): void
56+
{
57+
$file = $this->twig->getLoader()->getSourceContext($file);
58+
if ($path = $file->getPath()) {
59+
$this->message->attachFromPath($path, $name, $contentType);
60+
} else {
61+
$this->message->attach($file->getCode(), $name, $contentType);
62+
}
63+
}
64+
65+
public function setSubject(string $subject): self
66+
{
67+
$this->message->subject($subject);
68+
69+
return $this;
70+
}
71+
72+
public function getSubject(): ?string
73+
{
74+
return $this->message->getSubject();
75+
}
76+
77+
public function setReturnPath(string $address): self
78+
{
79+
$this->message->returnPath($address);
80+
81+
return $this;
82+
}
83+
84+
public function getReturnPath(): string
85+
{
86+
return $this->message->getReturnPath();
87+
}
88+
89+
public function addFrom(string $address, string $name = null): self
90+
{
91+
$this->message->addFrom($name ? new NamedAddress($address, $name) : new Address($address));
92+
93+
return $this;
94+
}
95+
96+
/**
97+
* @return (Address|NamedAddress)[]
98+
*/
99+
public function getFrom(): array
100+
{
101+
return $this->message->getFrom();
102+
}
103+
104+
public function addReplyTo(string $address): self
105+
{
106+
$this->message->addReplyTo($address);
107+
108+
return $this;
109+
}
110+
111+
/**
112+
* @return Address[]
113+
*/
114+
public function getReplyTo(): array
115+
{
116+
return $this->message->getReplyTo();
117+
}
118+
119+
public function addTo(string $address, string $name = null): self
120+
{
121+
$this->message->addTo($name ? new NamedAddress($address, $name) : new Address($address));
122+
123+
return $this;
124+
}
125+
126+
/**
127+
* @return (Address|NamedAddress)[]
128+
*/
129+
public function getTo(): array
130+
{
131+
return $this->message->getTo();
132+
}
133+
134+
public function addCc(string $address, string $name = null): self
135+
{
136+
$this->message->addCc($name ? new NamedAddress($address, $name) : new Address($address));
137+
138+
return $this;
139+
}
140+
141+
/**
142+
* @return (Address|NamedAddress)[]
143+
*/
144+
public function getCc(): array
145+
{
146+
return $this->message->getCc();
147+
}
148+
149+
public function addBcc(string $address, string $name = null): self
150+
{
151+
$this->message->addBcc($name ? new NamedAddress($address, $name) : new Address($address));
152+
153+
return $this;
154+
}
155+
156+
/**
157+
* @return (Address|NamedAddress)[]
158+
*/
159+
public function getBcc(): array
160+
{
161+
return $this->message->getBcc();
162+
}
163+
164+
public function setPriority(int $priority): self
165+
{
166+
$this->message->setPriority($priority);
167+
168+
return $this;
169+
}
170+
171+
public function getPriority(): int
172+
{
173+
return $this->message->getPriority();
174+
}
175+
}

0 commit comments

Comments
 (0)