Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c741006

Browse filesBrowse files
committed
[Mime] added classes for generating MIME messages
1 parent 91c5b14 commit c741006
Copy full SHA for c741006

File tree

Expand file treeCollapse file tree

103 files changed

+8303
-17
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

103 files changed

+8303
-17
lines changed

‎composer.json

Copy file name to clipboardExpand all lines: composer.json
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"symfony/contracts": "^1.0.2",
3232
"symfony/polyfill-ctype": "~1.8",
3333
"symfony/polyfill-intl-icu": "~1.0",
34+
"symfony/polyfill-intl-idn": "^1.10",
3435
"symfony/polyfill-mbstring": "~1.0",
3536
"symfony/polyfill-php72": "~1.5",
3637
"symfony/polyfill-php73": "^1.8"
+100Lines changed: 100 additions & 0 deletions
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+
}
+87Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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+
/**
29+
* @return $this
30+
*/
31+
public function template(?string $template)
32+
{
33+
$this->template = $template;
34+
35+
return $this;
36+
}
37+
38+
/**
39+
* @return $this
40+
*/
41+
public function textTemplate(?string $template)
42+
{
43+
$this->textTemplate = $template;
44+
45+
return $this;
46+
}
47+
48+
/**
49+
* @return $this
50+
*/
51+
public function htmlTemplate(?string $template)
52+
{
53+
$this->htmlTemplate = $template;
54+
55+
return $this;
56+
}
57+
58+
public function getTemplate(): ?string
59+
{
60+
return $this->template;
61+
}
62+
63+
public function getTextTemplate(): ?string
64+
{
65+
return $this->textTemplate;
66+
}
67+
68+
public function getHtmlTemplate(): ?string
69+
{
70+
return $this->htmlTemplate;
71+
}
72+
73+
/**
74+
* @return $this
75+
*/
76+
public function context(array $context)
77+
{
78+
$this->context = $context;
79+
80+
return $this;
81+
}
82+
83+
public function getContext(): array
84+
{
85+
return $this->context;
86+
}
87+
}
+175Lines changed: 175 additions & 0 deletions
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.