PluginProbe
EmailKit – Email Customizer for WooCommerce & WP / 1.6.9
EmailKit – Email Customizer for WooCommerce & WP v1.6.9
1.6.9 1.6.8 1.6.7 trunk 1.0.0 1.2.0 1.4.0 1.4.5 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6
emailkit / includes / Admin / Emails / Helpers / Utils.php

Utils.php in EmailKit – Email Customizer for WooCommerce & WP 1.6.9, at includes/Admin/Emails/Helpers/Utils.php

522 lines 22.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace EmailKit\Admin\Emails\Helpers;
4
5 defined("ABSPATH") || exit;
6
7 class Utils
8 {
9 public static function get_kses_array()
10 {
11 return array(
12 'html' => array(),
13 'head' => array(),
14 'body' => array(),
15 'hr' => array(),
16 'address' => array(),
17 'a' => array(
18 'class' => array(),
19 'href' => array(),
20 'rel' => array(),
21 'title' => array(),
22 'target' => array(),
23 'style' => array(),
24 ),
25 'abbr' => array(
26 'title' => array(),
27 'style' => array(),
28 ),
29 'b' => array(
30 'class' => array(),
31 'style' => array(),
32 ),
33 'blockquote' => array(
34 'cite' => array(),
35 'style' => array(),
36 ),
37 'cite' => array(
38 'title' => array(),
39 'style' => array(),
40 ),
41 'code' => array(
42 'style' => array(),
43 ),
44 'pre' => array(
45 'style' => array(),
46 ),
47 'del' => array(
48 'datetime' => array(),
49 'title' => array(),
50 'style' => array(),
51 ),
52 'dd' => array(
53 'style' => array(),
54 ),
55 'div' => array(
56 'class' => array(),
57 'title' => array(),
58 'style' => array(),
59 ),
60 'dl' => array(
61 'style' => array(),
62 ),
63 'dt' => array(
64 'style' => array(),
65 ),
66 'em' => array(
67 'style' => array(),
68 ),
69 'strong' => array(
70 'style' => array(),
71 ),
72 'h1' => array(
73 'class' => array(),
74 'style' => array(),
75 ),
76 'h2' => array(
77 'class' => array(),
78 'style' => array(),
79 ),
80 'h3' => array(
81 'class' => array(),
82 'style' => array(),
83 ),
84 'h4' => array(
85 'class' => array(),
86 'style' => array(),
87 ),
88 'h5' => array(
89 'class' => array(),
90 'style' => array(),
91 ),
92 'h6' => array(
93 'class' => array(),
94 'style' => array(),
95 ),
96 'i' => array(
97 'class' => array(),
98 'style' => array(),
99 ),
100 'img' => array(
101 'alt' => array(),
102 'class' => array(),
103 'height' => array(),
104 'src' => array(),
105 'width' => array(),
106 'style' => array(),
107 'title' => array(),
108 'srcset' => array(),
109 'loading' => array(),
110 'sizes' => array(),
111 'style' => array(),
112 ),
113 'figure' => array(
114 'class' => array(),
115 'style' => array(),
116 ),
117 'li' => array(
118 'class' => array(),
119 'style' => array(),
120 ),
121 'ol' => array(
122 'class' => array(),
123 'style' => array(),
124 ),
125 'p' => array(
126 'class' => array(),
127 'style' => array(),
128 ),
129 'q' => array(
130 'cite' => array(),
131 'title' => array(),
132 'style' => array(),
133 ),
134 'span' => array(
135 'class' => array(),
136 'title' => array(),
137 'style' => array(),
138 ),
139 'iframe' => array(
140 'width' => array(),
141 'height' => array(),
142 'scrolling' => array(),
143 'frameborder' => array(),
144 'allow' => array(),
145 'src' => array(),
146 'style' => array(),
147 ),
148 'strike' => array(),
149 'br' => array(),
150 'table' => array(),
151 'thead' => array(),
152 'tbody' => array(
153 'width' => array(),
154 'height' => array(),
155 'scrolling' => array(),
156 'frameborder' => array(),
157 'allow' => array(),
158 'src' => array(),
159 'style' => array()
160 ),
161 'tfoot' => array(),
162 'tr' => array(
163 'width' => array(),
164 'height' => array(),
165 'scrolling' => array(),
166 'frameborder' => array(),
167 'allow' => array(),
168 'src' => array(),
169 'style' => array()
170 ),
171 'td' => array(
172 'class' => array(),
173 ),
174 'th' => array(),
175 'colgroup' => array(),
176 'col' => array(),
177 'strong' => array(),
178 'data-wow-duration' => array(),
179 'data-wow-delay' => array(),
180 'data-wallpaper-options' => array(),
181 'data-stellar-background-ratio' => array(),
182 'ul' => array(
183 'class' => array(),
184 ),
185 'button' => array(
186 'disabled' => array(),
187 'id' => array(),
188 'class' => array(),
189 'style' => array(),
190 'target' => array(),
191 'href' => array(),
192 'data-editor-template-url' => array(),
193 'data-emailkit-email-type' => array(),
194 'data-emailkit-template-title' => array(),
195 'data-emailkit-template-type' => array(),
196 'data-emailkit-template' => array(),
197 ),
198 'svg' => array(
199 'class' => true,
200 'aria-hidden' => true,
201 'aria-labelledby' => true,
202 'role' => true,
203 'xmlns' => true,
204 'width' => true,
205 'height' => true,
206 'viewbox' => true, // <= Must be lower case!
207 'preserveaspectratio' => true,
208 ),
209 'g' => array('fill' => true),
210 'title' => array('title' => true),
211 'path' => array(
212 'd' => true,
213 'fill' => true,
214 ),
215 'input' => array(
216 'class' => array(),
217 'type' => array(),
218 'value' => array()
219 )
220 );
221 }
222
223 public static function kses($raw)
224 {
225
226 $allowed_tags = self::get_kses_array();
227
228 if (function_exists('wp_kses')) { // WP is here
229 return wp_kses($raw, $allowed_tags);
230 } else {
231 return $raw;
232 }
233 }
234
235 public static function mail_shortcode_filter(string $input) : string {
236
237 // find the shortcode
238 $pattern = '/<span data-shortcode="{{([^<>]+)}}">([\s\S]*?)<\/span>/';
239
240 // getting all shortcode matches from mail content
241 preg_match_all($pattern, $input, $matches, PREG_SET_ORDER);
242
243 // Loop through each match and replace the content inside the span tag
244 foreach ($matches as $match) {
245 $shortcode = $match[1]; // Content inside the data-shortcode attribute
246 $oldContent = $match[2]; // Content inside the span tag
247
248 // replaceing the shortcode
249 $replacement = '<span>{{' . $shortcode . '}}</span>';
250 $input = str_replace($match[0], $replacement, $input);
251 }
252
253 return $input;
254 }
255
256 /**
257 * Adjust the price structure for left or left_space currency symbol positions.
258 *
259 * @param string $message The HTML message content to process.
260 * @return string The updated message with corrected price structure.
261 */
262 public static function adjust_price_structure($message) {
263 return preg_replace_callback(
264 '/<span class="woocommerce-Price-currencySymbol">(.*?)<\/span>([\d.,]+)<\/bdi><\/span><\/span>\s*(\d{1,3}(?:,\d{3})*(?:\.\d{2})?)<\/bdi><\/span><\/span>/',
265 function ($matches) {
266 // Rebuild the correct price structure
267 return '<span class="woocommerce-Price-currencySymbol">'
268 . $matches[1] . '</span>'
269 . $matches[2] . '</bdi></span>';
270 },
271 $message
272 );
273 }
274
275 public static function adjust_left_space_price_structure($message) {
276 return preg_replace_callback(
277 '/<span><span class="woocommerce-Price-amount amount"><bdi><span class="woocommerce-Price-currencySymbol">([^<]+)<\/span>&nbsp;([\d.,]+)<\/bdi><\/span><\/span>&nbsp;[\d.,]+<\/bdi><\/span><\/span>/',
278 function ($matches) {
279 return '<span class="woocommerce-Price-amount amount"><bdi><span class="woocommerce-Price-currencySymbol">'
280 . $matches[1] . '</span>&nbsp;' . $matches[2] . '</bdi></span>';
281 },
282 $message
283 );
284 }
285
286 public static function order_items_replace(string $document, array $replacements ){
287
288 // Patterns for different classes
289 $patterns = [
290 'order_items' => '/<tr[^>]*class="order_items"[^>]*>.*?<\/tr>/s',
291 'order_item_price' => '/<tr[^>]*class="order_item_price"[^>]*>.*?<\/tr>/s',
292 'order_quantity' => '/<tr[^>]*class="order_quantity"[^>]*>.*?<\/tr>/s',
293 ];
294
295 foreach ($patterns as $key => $pattern) {
296 // Match rows with the specified class
297 preg_match_all($pattern, $document, $matches);
298
299 if (!empty($matches[0])) {
300 $rows = '';
301
302 // Iterate through each matched row
303 foreach ($matches[0] as $originalRow) {
304 // Duplicate the row for each replacement
305 foreach ($replacements as $replacement) {
306 // Replace placeholders in the duplicated row
307 $placeholders = ["{{product_name}}", "{{quantity}}", "{{total}}", "{{product_price}}", "{{product_image_url}}", "{{product_sku}}", "{{product_attributes}}", "{{purchase_note}}"];
308 $newRow = str_replace($placeholders, $replacement, $originalRow);
309
310 // If purchase note is empty, remove the purchase_note_wrapper
311 if (empty($replacement[7])) {
312 $newRow = preg_replace('/<p[^>]*class="purchase_note_wrapper"[^>]*>.*?<\/p>/s', '', $newRow);
313 $newRow = preg_replace('/<div[^>]*class="purchase_note_wrapper"[^>]*>.*?<\/div>/s', '', $newRow);
314 }
315
316 $rows .= $newRow;
317 }
318 }
319
320 // Replace the matched rows in the document
321 $document = preg_replace($pattern, $rows, $document);
322 }
323 }
324
325 return $document;
326 }
327
328 // Helper function to escape quotes
329 public static function escape_quotes($data) {
330 if (is_string($data)) {
331 return addslashes($data);
332 } elseif (is_array($data)) {
333 return array_map('escape_quotes', $data);
334 }
335 return $data;
336 }
337
338 // Function to transform keys from {{order_number}} format to [order_number] format
339 public static function transform_details_keys($details) {
340 $transformed_details = [];
341 foreach ($details as $key => $value) {
342 $new_key = str_replace(['{{', '}}'], ['[', ']'], $key);
343 $transformed_details[$new_key] = $value;
344 }
345 return $transformed_details;
346 }
347
348 public static function woocommerce_order_email_contents($order){
349
350 // Check if WooCommerce is active
351 if (!function_exists('wc_get_order')) {
352 return []; // Return empty array if WooCommerce is not active
353 }
354
355 $customer_note = $order->get_customer_note();
356 $shipping_first_name = $order->get_shipping_first_name();
357 $shipping_last_name = $order->get_shipping_last_name();
358 $shipping_full_name = $shipping_first_name . ' ' . $shipping_last_name;
359
360
361
362 $billing_country_code = $order->get_billing_country();
363 $billing_country_full_name = WC()->countries->countries[ $billing_country_code ];
364 $billing_state_code = $order->get_billing_state();
365 $billing_states = WC()->countries->get_states($billing_country_code);
366
367 $billing_state_full_name = is_array($billing_states) && isset($billing_states[$billing_state_code]) ? $billing_states[$billing_state_code] : $billing_state_code;
368
369 $shipping_country_code = $order->get_shipping_country();
370 $shipping_country_full_name = (!empty($shipping_country_code) && isset(WC()->countries->countries[$shipping_country_code]))? WC()->countries->countries[$shipping_country_code]: '';
371 $shipping_states = WC()->countries->get_states($shipping_country_code);
372 $shipping_state_code = $order->get_shipping_state();
373
374 $shipping_full_state_name = is_array($shipping_states) && isset($shipping_states[$shipping_state_code]) ? $shipping_states[$shipping_state_code] : $shipping_state_code;
375
376 $subtotal = $order->get_subtotal();
377 $total_refunded = $order->get_total_refunded();
378 $total = $order->get_total();
379
380 // Determine the formatted total using a ternary operator
381 $formatted_total = ($total_refunded == $total)
382 ? '<del aria-hidden="true">' . wc_price($total_refunded) . '</del> ' . '<ins>' . wc_price($total - $total_refunded) . '</ins>' // Fully refunded
383 : ($total_refunded > 0
384 ? '<del aria-hidden="true">' . wc_price($subtotal) . '</del> ' . '<u>' . wc_price($subtotal - $total_refunded) . '</u>' // Partially refunded
385 : wc_price($total, 2));
386
387 $total_order_quantity = 0;
388 foreach ($order->get_items() as $item) {
389 $total_order_quantity += $item->get_quantity();
390 $product_names[] = $item->get_name();
391 }
392
393 $product_names_string = implode(', ', $product_names);
394
395 $order_date = $order->get_date_created()->format('Y-m-d H:i:s');
396 // Convert the order date to the site's local timezone
397 $localized_date = get_date_from_gmt($order_date);
398 // Get the site's date and time formats
399 $date_format = get_option('date_format');
400 $time_format = get_option('time_format');
401 // Format the date and time separately
402 $formatted_date = date_i18n($date_format, strtotime($localized_date));
403 $formatted_time = date_i18n($time_format, strtotime($localized_date));
404
405 $details = [
406 "{{order_id}}" => $order->get_id(),
407 "{{order_number}}" => $order->get_order_number(),
408 "{{order_status}}" => $order->get_status(),
409 "{{customer_note}}" => $customer_note,
410 "{{shipping_total}}" => wc_price( $order->get_shipping_total() ),
411 "{{order_subtotal}}" => wc_price( $order->get_subtotal()),
412 "{{order_currency}}" => $order->get_currency(),
413 "{{order_fully_refunded}}" => '-'.wc_price($order->get_total_refunded(), 2),
414 "{{partial_refund_amount}}" => '-'. wc_price($order->get_total_refunded(), 2),
415 "{{remaining_refund_amount}}" => '-'.$order->get_remaining_refund_amount(),
416 "{{billing_phone}}" => $order->get_billing_phone(),
417 "{{shipping_tax_total}}" => wc_format_decimal($order->get_shipping_tax(), 2),
418 "{{order_date}}" => $formatted_date,
419 "{{order_time}}" => $formatted_time,
420 "{{shipping_method}}" => $order->get_shipping_method(),
421 "{{payment_method}}" => $order->get_payment_method_title(),
422 "{{total}}" => $formatted_total,
423 "{{billing_name}}" => $order->get_formatted_billing_full_name(),
424 "{{billing_first_name}}" => $order->get_billing_first_name(),
425 "{{billing_last_name}}" => $order->get_billing_last_name(),
426 "{{billing_company}}" => $order->get_billing_company(),
427 "{{billing_address_1}}" => $order->get_billing_address_1(),
428 "{{billing_address_2}}" => $order->get_billing_address_2(),
429 "{{billing_city}}" => $order->get_billing_city(),
430 "{{billing_state}}" => $billing_state_full_name,
431 "{{billing_postcode}}" => $order->get_billing_postcode(),
432 "{{billing_country}}" => $billing_country_full_name,
433 "{{billing_email}}" => $order->get_billing_email(),
434 "{{shipping_name}}" => $shipping_full_name,
435 "{{shipping_first_name}}" => $shipping_first_name,
436 "{{shipping_last_name}}" => $shipping_last_name,
437 "{{shipping_company}}" => $order->get_shipping_company(),
438 "{{shipping_address_1}}" => $order->get_shipping_address_1(),
439 "{{shipping_address_2}}" => $order->get_shipping_address_2(),
440 "{{shipping_city}}" => $order->get_shipping_city(),
441 "{{shipping_state}}" => $shipping_full_state_name,
442 "{{shipping_postcode}}" => $order->get_shipping_postcode(),
443 "{{shipping_country}}" => $shipping_country_full_name,
444 "{{shipping_phone}}" => $order->get_shipping_phone(),
445 "{{customer_note}}" => $order->get_customer_note(),
446 "{{download_permissions}}" => $order->is_download_permitted() ? $order->is_download_permitted() : 0,
447 "{{quantity}}" => $total_order_quantity,
448 "{{product_name}}" => $product_names_string,
449 "{{site_name}}" => get_bloginfo('name'),
450 "{{site_url}}" => get_bloginfo('url'),
451 ];
452
453 return $details;
454 }
455
456 public static function woocommerce_stock_email_contents($product) {
457
458 // Check if WooCommerce is active
459 if (!function_exists('wc_get_product')) {
460 return []; // Return empty array if WooCommerce is not active
461 }
462
463 $details = [
464
465 "{{stock_status}}" => $product->get_stock_status(),
466 "{{product_name}}" => $product->get_name(),
467 "{{stock_quantity}}" => $product->get_stock_quantity(),
468 "{{status}}" => $product->get_status(),
469 "{{product_id}}" => $product->get_id(),
470 "{{short_description}}" => $product->get_short_description(),
471 "{{product_price}}" => $product->get_price(),
472 "{{manage_stock}}" => $product->get_manage_stock(),
473 "{{sku}}" => $product->get_sku(),
474 "{{low_stock_amount}}" => $product->get_low_stock_amount(),
475 "{{backorders}}" => $product->get_backorders(),
476 "{{site_name}}" => get_bloginfo('name'),
477 "{{display_name}}" => wp_get_current_user()->display_name,
478
479 ];
480
481 return $details;
482 }
483
484
485 /**
486 * Convert bundled template image paths to the current site's absolute plugin URLs.
487 */
488 public static function normalize_template_asset_urls($content)
489 {
490 if (!is_string($content) || $content === '') {
491 return $content;
492 }
493
494 $site_base_url = trailingslashit(home_url());
495 $emailkit_pro_url = $site_base_url . 'wp-content/plugins/emailkit-pro/';
496
497 if (!function_exists('is_plugin_active')) {
498 require_once ABSPATH . 'wp-admin/includes/plugin.php';
499 }
500
501 $is_emailkit_pro_active = is_plugin_active('emailkit-pro/emailkit-pro.php');
502
503 if ($is_emailkit_pro_active) {
504
505 return str_replace(
506 [
507 'https://demo.wpmet.com/emailkit/wp-content/plugins/emailkit-pro/',
508 'http://demo.wpmet.com/emailkit/wp-content/plugins/emailkit-pro/',
509 '/wp-content/plugins/emailkit-pro/',
510 ],
511 [
512 $emailkit_pro_url,
513 $emailkit_pro_url,
514 $emailkit_pro_url,
515 ],
516 $content
517 );
518 }
519
520 return $content;
521 }
522 }