PluginProbe
YayMail – WooCommerce Email Customizer / 4.4.2
YayMail – WooCommerce Email Customizer v4.4.2
4.4.4 4.4.3 4.4.2 4.4.1 trunk 1.9.6 2.1.4 2.1.5 3.2.2 3.2.6 3.2.7.1 3.2.8.1 3.2.9 3.3 3.3.1 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4 3.4.1 3.4.2 3.4.3 All 55 releases
yaymail / src / Utils / TemplateHelpers.php

TemplateHelpers.php in YayMail – WooCommerce Email Customizer 4.4.2, at src/Utils/TemplateHelpers.php

525 lines 18.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace YayMail\Utils;
4
5 use YayMail\Constants\AttributesData;
6 use YayMail\Shortcodes\ShortcodesExecutor;
7 use YayMail\YayMailTemplate;
8
9 defined( 'ABSPATH' ) || exit;
10
11 /**
12 * TemplateHelpers Classes
13 * Define all utility functions to be used inside templates
14 */
15 class TemplateHelpers {
16
17 /**
18 * @deprecated
19 */
20 public static function get_attribute_data( $attribute_data ) {
21 $data = [];
22 foreach ( $attribute_data as $key => $attribute ) {
23 if ( 'image_box' === $key || 'image_list' === $key || 'text_list' === $key ) {
24 if ( isset( $attribute['column_1'] ) ) {
25 $data['column_1'] = self::get_attribute_data( $attribute['column_1'] );
26 }
27 if ( isset( $attribute['column_2'] ) ) {
28 $data['column_2'] = self::get_attribute_data( $attribute['column_2'] );
29 }
30 if ( isset( $attribute['column_3'] ) ) {
31 $data['column_3'] = self::get_attribute_data( $attribute['column_3'] );
32 }
33 } elseif ( 'inner_background_color' === $key ) {
34 $data[ $key ] = $attribute;
35 } else {
36 $data[ $key ] = $attribute['default_value'];
37 }
38 }
39 return $data;
40 }
41
42 public static function get_spacing_value( $spacing, $unit = 'px' ) {
43 $unit = esc_attr( $unit );
44 return sprintf(
45 '%d%s %d%s %d%s %d%s',
46 isset( $spacing['top'] ) ? $spacing['top'] : 0,
47 $unit,
48 isset( $spacing['right'] ) ? $spacing['right'] : 0,
49 $unit,
50 isset( $spacing['bottom'] ) ? $spacing['bottom'] : 0,
51 $unit,
52 isset( $spacing['left'] ) ? $spacing['left'] : 0,
53 $unit
54 );
55 }
56
57 public static function get_border_radius_value( $border_radius, $unit = 'px' ) {
58 $unit = esc_attr( $unit );
59 return sprintf(
60 '%d%s %d%s %d%s %d%s',
61 isset( $border_radius['top_left'] ) ? $border_radius['top_left'] : 0,
62 $unit,
63 isset( $border_radius['top_right'] ) ? $border_radius['top_right'] : 0,
64 $unit,
65 isset( $border_radius['bottom_right'] ) ? $border_radius['bottom_right'] : 0,
66 $unit,
67 isset( $border_radius['bottom_left'] ) ? $border_radius['bottom_left'] : 0,
68 $unit
69 );
70 }
71
72 /**
73 * Inner border radius for column_layout children: only the four outer corners of the row
74 * (first column left, last column right; single column gets all four).
75 *
76 * @param array $inner_border_radius Keys top_left, top_right, bottom_left, bottom_right.
77 * @param int $total_columns amount_of_columns from parent column_layout.
78 * @param int $column_index Zero-based column index.
79 * @return array{top_left:int,top_right:int,bottom_right:int,bottom_left:int}
80 */
81 public static function get_inner_column_border_radius( $inner_border_radius, $total_columns, $column_index ) {
82 $tl = isset( $inner_border_radius['top_left'] ) ? (int) $inner_border_radius['top_left'] : 0;
83 $tr = isset( $inner_border_radius['top_right'] ) ? (int) $inner_border_radius['top_right'] : 0;
84 $br = isset( $inner_border_radius['bottom_right'] ) ? (int) $inner_border_radius['bottom_right'] : 0;
85 $bl = isset( $inner_border_radius['bottom_left'] ) ? (int) $inner_border_radius['bottom_left'] : 0;
86
87 $total_columns = max( 1, (int) $total_columns );
88 $column_index = max( 0, (int) $column_index );
89
90 if ( 1 === $total_columns ) {
91 return [
92 'top_left' => $tl,
93 'top_right' => $tr,
94 'bottom_right' => $br,
95 'bottom_left' => $bl,
96 ];
97 }
98
99 if ( 0 === $column_index ) {
100 return [
101 'top_left' => $tl,
102 'top_right' => 0,
103 'bottom_right' => 0,
104 'bottom_left' => $bl,
105 ];
106 }
107
108 if ( $column_index === $total_columns - 1 ) {
109 return [
110 'top_left' => 0,
111 'top_right' => $tr,
112 'bottom_right' => $br,
113 'bottom_left' => 0,
114 ];
115 }
116
117 return [
118 'top_left' => 0,
119 'top_right' => 0,
120 'bottom_right' => 0,
121 'bottom_left' => 0,
122 ];
123 }
124
125 public static function get_dimension_value( $dimension, $unit = 'px' ) {
126 $unit = esc_attr( $unit );
127 $dimension = floatval( $dimension );
128 return "$dimension$unit";
129 }
130
131 public static function get_font_family_value( $font_family ) {
132 if ( empty( $font_family ) ) {
133 return 'inherit';
134 }
135 return str_replace( [ '\"','"' ], '', $font_family );
136 }
137
138 public static function wp_kses_allowed_html( $cus_attr_tags = [] ) {
139 $allowed_html_tags = wp_kses_allowed_html( 'post' );
140 $allowed_html_tags['style'] = true;
141 $allowed_html_tags['html'] = [];
142 $allowed_html_tags['header'] = [];
143 $allowed_html_tags['meta'] = [];
144 $allowed_html_attr = $cus_attr_tags;
145
146 $allowed_html_attr ['data-yaymail-element-type'] = true;
147 $allowed_html_attr ['charset'] = true;
148 $allowed_html_attr ['http-equiv'] = true;
149 $allowed_html_attr ['content'] = true;
150 $allowed_html_attr ['name'] = true;
151 return array_map(
152 function ( $item ) use ( $allowed_html_attr ) {
153 return is_array( $item ) ? array_merge( $item, $allowed_html_attr ) : $item;
154 },
155 $allowed_html_tags
156 );
157 }
158
159 public static function get_style( $css_properties = [] ) {
160 return implode(
161 ';',
162 array_map(
163 function ( $css_value, $css_name ) {
164 return "$css_name:$css_value";
165 },
166 $css_properties,
167 array_keys( $css_properties )
168 )
169 ) . ';';
170 }
171
172 public static function wrap_element_content( $content_html, $element, $wrapper_style = null ) {
173 $html = yaymail_get_content(
174 'templates/elements/element-wrapper.php',
175 [
176 'content_html' => $content_html,
177 'element' => $element,
178 'wrapper_style' => $wrapper_style,
179 ]
180 );
181
182 yaymail_kses_post_e( $html );
183 }
184
185 /**
186 * The function returns the value based on the provided key, default value, and placeholder
187 * flag.
188 *
189 * @param key Key parameter
190 * @param default The default value is the value that will be returned if the key is empty or if the
191 * is_placeholder parameter is false.
192 * @param is_placeholder A boolean value indicating whether the value should be treated as a
193 * placeholder or not.
194 *
195 * @return either the value of the variable or the placeholder "[[]]" depending on
196 * the values of the and variables.
197 */
198 public static function get_content_as_placeholder( $key, $default, $is_placeholder ) {
199 return $is_placeholder && ! empty( $key ) ? "[[{$key}]]" : $default;
200 }
201
202 public static function get_booking_from_order( $order ) {
203 $booking_ids = [];
204
205 if ( null !== $order ) {
206 if ( is_callable( 'WC_Booking_Data_Store::get_booking_ids_from_order_id' ) ) {
207 $booking_data = new \WC_Booking_Data_Store();
208 $booking_ids = $booking_data->get_booking_ids_from_order_id( $order->get_id() );
209 }
210
211 if ( ! empty( $booking_ids ) ) {
212 return new \WC_Booking( $booking_ids[0] );
213 }
214 }
215
216 return null;
217 }
218
219 public static function get_font_size( $size, $is_subtitle = false ) {
220 if ( 'default' === $size && $is_subtitle ) {
221 return '13px';
222 }
223 $result = isset( AttributesData::TITLE_SIZE_OPTIONS[ $size ] ) ? AttributesData::TITLE_SIZE_OPTIONS[ $size ] : 16;
224 $result .= 'px';
225 return $result;
226 }
227
228 /**
229 * Remove empty shortcodes from the content
230 *
231 * @param string $content The content to remove empty shortcodes from
232 * @return string The content with empty shortcodes removed
233 * @since 4.0.2
234 */
235 public static function remove_empty_shortcodes( $content ) {
236 $content = preg_replace( '/<p\b[^>]*>\[yaymail_[^\]]*\]<\/p>/i', '', $content );
237 $content = preg_replace( '/\[yaymail_[^\]]*\]/', '', $content );
238 return $content;
239 }
240
241 public static function convert_rgb_to_hex( $color ) {
242 if ( is_string( $color ) && strpos( $color, 'rgb' ) === 0 ) {
243 $rgb = str_replace( 'rgb(', '', $color );
244 $rgb = str_replace( ')', '', $rgb );
245 $rgb = explode( ',', $rgb );
246 $hex = '#';
247 $hex .= str_pad( dechex( $rgb[0] ), 2, '0', STR_PAD_LEFT );
248 $hex .= str_pad( dechex( $rgb[1] ), 2, '0', STR_PAD_LEFT );
249 $hex .= str_pad( dechex( $rgb[2] ), 2, '0', STR_PAD_LEFT );
250 return $hex;
251 } else {
252 return $color;
253 }
254 }
255
256 /**
257 * Find element by id in the list of elements
258 *
259 * @param string $id The id of the element to find.
260 * @param array $list_elements The list of elements to search in.
261 * @return array|null The element if found, null otherwise
262 * @since 4.1.0
263 */
264 public static function find_element_by_id( $id, $list_elements ) {
265 foreach ( $list_elements as $element ) {
266 if ( $element['id'] === $id ) {
267 return $element;
268 }
269 if ( $element['children'] && count( $element['children'] ) > 0 ) {
270 $result = self::find_element_by_id( $id, $element['children'] );
271 if ( $result ) {
272 return $result;
273 }
274 }
275 }
276 return null;
277 }
278
279 public static function find_parent_element( $id, $list_elements ) {
280
281 foreach ( $list_elements as $element ) {
282 if ( empty( $element['children'] ) ) {
283 continue;
284 }
285 if ( in_array( $id, array_column( $element['children'], 'id' ) ) ) {
286 return $element;
287 }
288 $sub_query = self::find_parent_element( $id, $element['children'] );
289 if ( $sub_query ) {
290 return $sub_query;
291 }
292 }
293
294 return null;
295 }
296
297 public static function get_current_column_index( $id, $list_elements ) {
298 $element = self::find_element_by_id( $id, $list_elements );
299 if ( empty( $element ) ) {
300 return 0;
301 }
302 $parent_element = self::find_parent_element( $element['id'], $list_elements );
303 if ( empty( $parent_element ) ) {
304 return 0;
305 }
306 $current_column_index = array_search( $element['id'], array_column( $parent_element['children'], 'id' ) );
307 return $current_column_index;
308 }
309
310 public static function get_border_css_value( $border ) {
311 if ( $border['side'] === 'none' ) {
312 return '';
313 }
314 if ( $border['side'] === 'all' ) {
315 return self::get_style(
316 [
317 'border' => self::get_border_style( $border ),
318 ]
319 );
320 }
321 if ( $border['side'] === 'top' ) {
322 return self::get_style(
323 [
324 'border-top' => self::get_border_style( $border ),
325 ]
326 );
327 }
328 if ( $border['side'] === 'bottom' ) {
329 return self::get_style(
330 [
331 'border-bottom' => self::get_border_style( $border ),
332 ]
333 );
334 }
335 if ( $border['side'] === 'right' ) {
336 return self::get_style(
337 [
338 'border-right' => self::get_border_style( $border ),
339 ]
340 );
341 }
342 if ( $border['side'] === 'left' ) {
343 return self::get_style(
344 [
345 'border-left' => self::get_border_style( $border ),
346 ]
347 );
348 }
349 if ( $border['side'] === 'custom' ) {
350 return self::get_style(
351 [
352 'border-top' => self::get_border_style(
353 [
354 'width' => $border['custom']['top'],
355 'style' => $border['style'],
356 'color' => $border['color'],
357 ]
358 ),
359 'border-right' => self::get_border_style(
360 [
361 'width' => $border['custom']['right'],
362 'style' => $border['style'],
363 'color' => $border['color'],
364 ]
365 ),
366 'border-bottom' => self::get_border_style(
367 [
368 'width' => $border['custom']['bottom'],
369 'style' => $border['style'],
370 'color' => $border['color'],
371 ]
372 ),
373 'border-left' => self::get_border_style(
374 [
375 'width' => $border['custom']['left'],
376 'style' => $border['style'],
377 'color' => $border['color'],
378 ]
379 ),
380 ]
381 );
382 }//end if
383 return '';
384 }
385
386 public static function get_border_style( $border, $unit = 'px' ) {
387 $unit = esc_attr( $unit );
388 return sprintf(
389 '%d%s %s %s',
390 $border['width'],
391 $unit,
392 $border['style'],
393 $border['color']
394 );
395 }
396
397 public static function sanitize_elements_recursive( $elements ) {
398 if ( ! is_array( $elements ) ) {
399 return [];
400 }
401
402 foreach ( $elements as &$element ) {
403 if ( isset( $element['data']['rich_text'] ) ) {
404 $element['data']['rich_text'] = yaymail_kses_post( $element['data']['rich_text'], $allowed );
405 }
406
407 if ( isset( $element['data']['title'] ) ) {
408 $element['data']['title'] = yaymail_kses_post( $element['data']['title'] );
409 }
410
411 // Recursive cho nested elements
412 if ( isset( $element['children'] ) ) {
413 $element['children'] = self::sanitize_elements_recursive( $element['children'] );
414 }
415 }
416
417 return $elements;
418 }
419
420 public static function replace_color_paths( $value ) {
421 return $value;
422 }
423
424 /**
425 * Append invisible characters so inbox clients do not pull body text into the preview line.
426 *
427 * @param string $preheader Visible preheader text.
428 * @param int $target_length Approximate preview window (Gmail ~90–140, Outlook ~130).
429 * @return string
430 */
431 public static function pad_preheader( $preheader, $target_length = 150 ) {
432 $preheader = trim( (string) $preheader );
433
434 if ( '' === $preheader ) {
435 return '';
436 }
437
438 /**
439 * Filter the target length for invisible preheader padding.
440 *
441 * @param int $target_length Default padding target length.
442 * @param string $preheader Visible preheader text.
443 */
444 $target_length = (int) apply_filters( 'yaymail_email_preheader_pad_length', $target_length, $preheader );
445
446 if ( $target_length <= 0 ) {
447 return $preheader;
448 }
449
450 $visible_length = mb_strlen( $preheader );
451
452 if ( $visible_length >= $target_length ) {
453 return $preheader;
454 }
455
456 // Litmus preview-text hack: zero-width non-joiner + non-breaking space.
457 $pad_unit = "\u{200C}\u{00A0}";
458
459 return $preheader . str_repeat( $pad_unit, $target_length - $visible_length );
460 }
461
462 /**
463 * Process preheader text (YayMail shortcodes).
464 *
465 * @param string $preheader Raw preheader from template meta.
466 * @param YayMailTemplate $template Email template.
467 * @param array $render_data Render context.
468 * @return string Plain-text preheader for inbox preview.
469 */
470 public static function process_email_preheader( $preheader, $template, $args = [] ) {
471 $preheader = trim( (string) $preheader );
472
473 if ( '' === $preheader || ! $template instanceof YayMailTemplate ) {
474 return '';
475 }
476
477 $template_name = $template->get_name();
478
479 if ( false !== strpos( $preheader, '[' ) && $template_name ) {
480
481 $shortcodes = yaymail_get_email_shortcodes( $template_name );
482 new ShortcodesExecutor( $shortcodes, $args );
483 $preheader = do_shortcode( $preheader );
484 }//end if
485
486 $preheader = self::pad_preheader( wp_strip_all_tags( $preheader ) );
487
488 return $preheader;
489 }
490
491 /**
492 * Output hidden preheader row at the top of the email body (Woo block-editor style).
493 *
494 * @param YayMailTemplate $template Email template.
495 * @param array $args Render context.
496 */
497 public static function render_email_preheader( $template, $args = [] ) {
498 if ( ! $template instanceof YayMailTemplate ) {
499 return;
500 }
501
502 $template_name = $template->get_name();
503
504 if ( str_starts_with( $template_name, 'pattern_' ) || 'yaymail_global_header_footer' === $template_name ) {
505 return;
506 }
507
508 $preheader = self::process_email_preheader( $template->get_preheader(), $template, $args );
509
510 if ( '' === $preheader ) {
511 return;
512 }
513
514 $preheader_html = yaymail_get_content(
515 'templates/emails/email-preheader.php',
516 [
517 'preheader' => $preheader,
518 ]
519 );
520
521 if ( '' !== $preheader_html ) {
522 yaymail_kses_post_e( $preheader_html );
523 }
524 }
525 }