Skip to content

Commit c0d7943

Browse files
authored
Merge pull request #25 from dingo-d/feature/mj-wrapper
Implement mj-wrapper element
2 parents 2bda62f + c5bd465 commit c0d7943

File tree

2 files changed

+466
-0
lines changed

2 files changed

+466
-0
lines changed
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
<?php
2+
3+
/**
4+
* PHP MJML Renderer library
5+
*
6+
* @package MadeByDenis\PhpMjmlRenderer
7+
* @link https://github.com/dingo-d/php-mjml-renderer
8+
* @license https://opensource.org/licenses/MIT MIT
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace MadeByDenis\PhpMjmlRenderer\Elements\BodyComponents;
14+
15+
use MadeByDenis\PhpMjmlRenderer\Elements\AbstractElement;
16+
17+
/**
18+
* Mjml Wrapper Element
19+
*
20+
* Wrapper enables to wrap multiple sections together and provide
21+
* a full-width background.
22+
*
23+
* @link https://documentation.mjml.io/#mj-wrapper
24+
*
25+
* @since 1.0.0
26+
*/
27+
class MjWrapper extends AbstractElement
28+
{
29+
public const string TAG_NAME = 'mj-wrapper';
30+
31+
public const bool ENDING_TAG = false;
32+
33+
/**
34+
* List of allowed attributes on the element
35+
*
36+
* @var array<string, array<string, string>>
37+
*/
38+
protected array $allowedAttributes = [
39+
'background-color' => [
40+
'unit' => 'color',
41+
'type' => 'color',
42+
'description' => 'wrapper background color',
43+
'default_value' => '',
44+
],
45+
'background-url' => [
46+
'unit' => 'string',
47+
'type' => 'string',
48+
'description' => 'wrapper background image url',
49+
'default_value' => '',
50+
],
51+
'background-repeat' => [
52+
'unit' => 'string',
53+
'type' => 'string',
54+
'description' => 'wrapper background repeat value',
55+
'default_value' => 'repeat',
56+
],
57+
'background-size' => [
58+
'unit' => 'string',
59+
'type' => 'string',
60+
'description' => 'wrapper background size',
61+
'default_value' => 'auto',
62+
],
63+
'background-position' => [
64+
'unit' => 'string',
65+
'type' => 'string',
66+
'description' => 'wrapper background position',
67+
'default_value' => 'top center',
68+
],
69+
'background-position-x' => [
70+
'unit' => 'string',
71+
'type' => 'string',
72+
'description' => 'wrapper background position x value',
73+
'default_value' => '',
74+
],
75+
'background-position-y' => [
76+
'unit' => 'string',
77+
'type' => 'string',
78+
'description' => 'wrapper background position y value',
79+
'default_value' => '',
80+
],
81+
'border' => [
82+
'unit' => 'string',
83+
'type' => 'string',
84+
'description' => 'wrapper border format',
85+
'default_value' => 'none',
86+
],
87+
'border-bottom' => [
88+
'unit' => 'string',
89+
'type' => 'string',
90+
'description' => 'wrapper border bottom',
91+
'default_value' => '',
92+
],
93+
'border-left' => [
94+
'unit' => 'string',
95+
'type' => 'string',
96+
'description' => 'wrapper border left',
97+
'default_value' => '',
98+
],
99+
'border-radius' => [
100+
'unit' => 'px',
101+
'type' => 'measure',
102+
'description' => 'wrapper border radius',
103+
'default_value' => '',
104+
],
105+
'border-right' => [
106+
'unit' => 'string',
107+
'type' => 'string',
108+
'description' => 'wrapper border right',
109+
'default_value' => '',
110+
],
111+
'border-top' => [
112+
'unit' => 'string',
113+
'type' => 'string',
114+
'description' => 'wrapper border top',
115+
'default_value' => '',
116+
],
117+
'css-class' => [
118+
'unit' => 'string',
119+
'type' => 'string',
120+
'description' => 'class name added to root HTML element',
121+
'default_value' => '',
122+
],
123+
'padding' => [
124+
'unit' => 'px',
125+
'type' => 'string',
126+
'description' => 'supports up to 4 parameters',
127+
'default_value' => '20px 0',
128+
],
129+
'padding-bottom' => [
130+
'unit' => 'px',
131+
'type' => 'measure',
132+
'description' => 'bottom offset',
133+
'default_value' => '',
134+
],
135+
'padding-left' => [
136+
'unit' => 'px',
137+
'type' => 'measure',
138+
'description' => 'left offset',
139+
'default_value' => '',
140+
],
141+
'padding-right' => [
142+
'unit' => 'px',
143+
'type' => 'measure',
144+
'description' => 'right offset',
145+
'default_value' => '',
146+
],
147+
'padding-top' => [
148+
'unit' => 'px',
149+
'type' => 'measure',
150+
'description' => 'top offset',
151+
'default_value' => '',
152+
],
153+
'text-align' => [
154+
'unit' => 'string',
155+
'type' => 'alignment',
156+
'description' => 'left/right/center/justify',
157+
'default_value' => 'center',
158+
],
159+
];
160+
161+
protected array $defaultAttributes = [
162+
'background-repeat' => 'repeat',
163+
'background-size' => 'auto',
164+
'background-position' => 'top center',
165+
'border' => 'none',
166+
'padding' => '20px 0',
167+
'text-align' => 'center',
168+
];
169+
170+
public function render(): string
171+
{
172+
$tableAttributes = $this->getHtmlAttributes([
173+
'align' => 'center',
174+
'class' => $this->getAttribute('css-class'),
175+
'background' => $this->getAttribute('background-url'),
176+
'border' => '0',
177+
'cellpadding' => '0',
178+
'cellspacing' => '0',
179+
'role' => 'presentation',
180+
'style' => 'table',
181+
]);
182+
183+
$tdAttributes = $this->getHtmlAttributes([
184+
'style' => 'td',
185+
]);
186+
187+
$children = $this->getChildren() ?? [];
188+
$content = $this->renderChildren($children, []);
189+
190+
return "<table $tableAttributes>
191+
<tbody>
192+
<tr>
193+
<td $tdAttributes>
194+
$content
195+
</td>
196+
</tr>
197+
</tbody>
198+
</table>";
199+
}
200+
201+
/**
202+
* @return array<string, array<string, string>>
203+
*/
204+
public function getStyles(): array
205+
{
206+
$background = $this->getAttribute('background-url') ?
207+
[
208+
'background' => $this->getBackground(),
209+
'background-position' => $this->getAttribute('background-position'),
210+
'background-repeat' => $this->getAttribute('background-repeat'),
211+
'background-size' => $this->getAttribute('background-size'),
212+
] :
213+
[
214+
'background' => $this->getAttribute('background-color'),
215+
'background-color' => $this->getAttribute('background-color'),
216+
];
217+
218+
return [
219+
'table' => array_merge($background, [
220+
'width' => '100%',
221+
'border-radius' => $this->getAttribute('border-radius'),
222+
]),
223+
'td' => [
224+
'border' => $this->getAttribute('border'),
225+
'border-bottom' => $this->getAttribute('border-bottom'),
226+
'border-left' => $this->getAttribute('border-left'),
227+
'border-right' => $this->getAttribute('border-right'),
228+
'border-top' => $this->getAttribute('border-top'),
229+
'direction' => 'ltr',
230+
'font-size' => '0px',
231+
'padding' => $this->getAttribute('padding'),
232+
'padding-bottom' => $this->getAttribute('padding-bottom'),
233+
'padding-left' => $this->getAttribute('padding-left'),
234+
'padding-right' => $this->getAttribute('padding-right'),
235+
'padding-top' => $this->getAttribute('padding-top'),
236+
'text-align' => $this->getAttribute('text-align'),
237+
],
238+
];
239+
}
240+
241+
private function getBackground(): string
242+
{
243+
$bgUrl = $this->getAttribute('background-url');
244+
$bgSize = $this->getAttribute('background-size');
245+
246+
$backgroundParts = [];
247+
248+
if ($this->getAttribute('background-color')) {
249+
$backgroundParts[] = $this->getAttribute('background-color');
250+
}
251+
252+
if ($bgUrl) {
253+
$backgroundParts[] = "url('$bgUrl')";
254+
$backgroundParts[] = $this->getAttribute('background-position');
255+
$backgroundParts[] = "/ $bgSize";
256+
$backgroundParts[] = $this->getAttribute('background-repeat');
257+
}
258+
259+
return implode(' ', array_filter($backgroundParts));
260+
}
261+
}

0 commit comments

Comments
 (0)