PluginProbe
YayMail – WooCommerce Email Customizer / 4.4.4
YayMail – WooCommerce Email Customizer v4.4.4
4.4.6 4.4.5 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 All 57 releases
yaymail / src / Ajax.php

Ajax.php in YayMail – WooCommerce Email Customizer 4.4.4, at src/Ajax.php

940 lines 41.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace YayMail;
4
5 use YayMail\Utils\SingletonTrait;
6 use YayMail\Models\SettingModel;
7 use YayMail\Models\TemplateModel;
8 use YayMail\Models\RevisionModel;
9 use YayMail\Migrations\MainMigration;
10 use YayMail\Utils\Helpers;
11
12 /**
13 * I18n Logic
14 *
15 * @method static Ajax get_instance()
16 */
17 class Ajax {
18 use SingletonTrait;
19
20 protected function __construct() {
21 $this->init_hooks();
22 }
23
24 protected function init_hooks() {
25 add_action( 'wp_ajax_yaymail_preview_mail', [ $this, 'preview_mail' ] );
26 add_action( 'wp_ajax_yaymail_preview_mail_for_woo', [ $this, 'preview_mail_for_woo' ] );
27 add_action( 'wp_ajax_yaymail_send_test_mail', [ $this, 'send_test_mail' ] );
28 add_action( 'wp_ajax_yaymail_install_yaysmtp', [ $this, 'install_yaysmtp' ] );
29 add_action( 'wp_ajax_yaymail_get_custom_hook_html', [ $this, 'get_custom_hook_html' ] );
30 add_action( 'wp_ajax_yaymail_get_template_data_onload', [ $this, 'get_template_data_onload' ] );
31 add_action( 'wp_ajax_yaymail_export_templates', [ $this, 'export_templates' ] );
32 add_action( 'wp_ajax_yaymail_import_templates', [ $this, 'import_templates' ] );
33 add_action( 'wp_ajax_yaymail_review', [ $this, 'yaymail_review' ] );
34 add_action( 'wp_ajax_yaymail_change_ghf_tour', [ $this, 'change_ghf_tour' ] );
35 add_action( 'wp_ajax_yaymail_dismiss_multi_select_notice', [ $this, 'dismiss_multi_select_notice' ] );
36 add_action( 'wp_ajax_yaymail_export_state', [ $this, 'export_state' ] );
37 add_action( 'wp_ajax_yaymail_import_state', [ $this, 'import_state' ] );
38 add_action( 'wp_ajax_yaymail_dismiss_new_element_notification', [ $this, 'dismiss_new_element_notification' ] );
39 }
40
41 public function import_state() {
42 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
43 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
44 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
45 }
46 try {
47 $import_file = isset( $_FILES['import_file'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_FILES['import_file'] ) ) : null;
48 if ( ! $import_file ) {
49 return wp_send_json_error( [ 'mess' => __( 'Can\'t find import file', 'yaymail' ) ] );
50 }
51
52 if ( $import_file['type'] !== 'application/zip' ) {
53 return wp_send_json_error( [ 'mess' => __( 'Invalid file type. Please upload a ZIP file.', 'yaymail' ) ] );
54 }
55
56 $zip = new \ZipArchive();
57 if ( $zip->open( $import_file['tmp_name'] ) !== true ) {
58 return wp_send_json_error( [ 'mess' => __( 'Cannot open ZIP file.', 'yaymail' ) ] );
59 }
60
61 $state_data = null;
62 for ( $i = 0; $i < $zip->numFiles; $i++ ) {
63 $filename = $zip->getNameIndex( $i );
64 // Matches both "yaymail_backup.json" (YayMail) and "email_builder_backup.json"
65 // (Email Builder) -- the zip always holds exactly this one entry, named per
66 // getBrandName() in backup/index.tsx.
67 if ( 1 === preg_match( '/_backup\.json$/', (string) $filename ) ) {
68 $state_data = $zip->getFromIndex( $i );
69 break;
70 }
71 }
72
73 $zip->close();
74
75 if ( ! $state_data ) {
76 return wp_send_json_error( [ 'mess' => __( 'Cannot find the backup JSON file in the ZIP file.', 'yaymail' ) ] );
77 }
78
79 $imported_data = json_decode( $state_data );
80 if ( json_last_error() !== JSON_ERROR_NONE ) {
81 return wp_send_json_error( [ 'mess' => __( 'Invalid JSON data in the state file.', 'yaymail' ) ] );
82 }
83
84 if ( empty( $imported_data->posts ) || empty( $imported_data->postmeta ) || empty( $imported_data->options ) ) {
85 return wp_send_json_error( [ 'mess' => __( 'Invalid state file structure.', 'yaymail' ) ] );
86 }
87
88 $migration_model = \YayMail\Models\MigrationModel::get_instance();
89
90 $source_version = $imported_data->version;
91
92 $imported_posts = array_values(
93 array_filter(
94 $imported_data->posts,
95 function( $post ) {
96 return isset( $post->post_type ) && 'yaymail_template' === $post->post_type;
97 }
98 )
99 );
100
101 $imported_postmeta = array_values(
102 array_filter(
103 $imported_data->postmeta,
104 function( $postmeta ) use ( $imported_posts ) {
105 if ( empty( $imported_posts ) ) {
106 return false;
107 }
108 if ( ! isset( $postmeta->post_id ) || ! isset( $postmeta->meta_key ) ) {
109 return false;
110 }
111 if ( strpos( (string) $postmeta->meta_key, 'yaymail' ) === false ) {
112 return false;
113 }
114 foreach ( $imported_posts as $post ) {
115 if ( isset( $post->ID ) && (int) $post->ID === (int) $postmeta->post_id ) {
116 return true;
117 }
118 }
119 return false;
120 }
121 )
122 );
123
124 $imported_options = array_values(
125 array_filter(
126 $imported_data->options,
127 function( $option ) {
128 return isset( $option->option_name ) && strpos( (string) $option->option_name, 'yaymail' ) !== false;
129 }
130 )
131 );
132
133 $backup_data = [
134 'posts' => $imported_posts,
135 'postmeta' => $imported_postmeta,
136 'options' => $imported_options,
137 'created_date' => $imported_data->created_date ?? current_datetime()->format( 'Y-m-d H:i:s' ),
138 'name' => '_yaymail_import_backup_' . $source_version,
139 'version' => $source_version,
140 ];
141
142 $migration_model->reset( $backup_data );
143
144 wp_send_json_success(
145 [
146 'message' => __( 'Import state successfully', 'yaymail' ),
147 ]
148 );
149 } catch ( \Error $error ) {
150 yaymail_get_logger( $error );
151 wp_send_json_error( [ 'mess' => __( 'Import failed: ', 'yaymail' ) . $error->getMessage() ] );
152 } catch ( \Exception $exception ) {
153 yaymail_get_logger( $exception );
154 wp_send_json_error( [ 'mess' => __( 'Import failed: ', 'yaymail' ) . $exception->getMessage() ] );
155 }//end try
156 }
157
158 public function export_state() {
159 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
160 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
161 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
162 }
163
164 try {
165 global $wpdb;
166
167 /**
168 * Backup posts and postmeta
169 */
170 $query_posts = "
171 SELECT *
172 FROM {$wpdb->posts}
173 WHERE post_type = 'yaymail_template'
174 ";
175 $yaymail_template_posts = $wpdb->get_results( $query_posts );// phpcs:ignore
176
177 $query_postmeta = "
178 SELECT *
179 FROM {$wpdb->postmeta}
180 WHERE meta_key LIKE '%yaymail%'
181 ";
182 $yaymail_template_postmeta = $wpdb->get_results( $query_postmeta );// phpcs:ignore
183
184 $backup_data = [
185 'posts' => $yaymail_template_posts,
186 'postmeta' => $yaymail_template_postmeta,
187 ];
188 /** ****************************** */
189
190 /**
191 * Backup options
192 */
193 $query_options = "
194 SELECT *
195 FROM {$wpdb->options}
196 WHERE option_name LIKE '%yaymail%'
197 ";
198 $yaymail_options = $wpdb->get_results( $query_options ); // phpcs:ignore
199 $backup_data['options'] = $yaymail_options;
200
201 $backup_data['created_date'] = current_datetime()->format( 'Y-m-d H:i:s' );
202
203 // Fall back through running version / YAYWP_VERSION / '1.0' when the
204 // backup option hasn't been set yet (e.g. init_modules() hasn't
205 // recorded it), otherwise a falsy 'version' gets baked into the
206 // exported ZIP and MigrationModel::reset() rejects it on import with
207 // "Back up does not exist".
208 $version_backup = get_option( 'yaymail_version_backup' );
209 if ( ! empty( $version_backup ) ) {
210 $backup_data['version'] = $version_backup;
211 } elseif ( ! empty( yaymail_version() ) ) {
212 $backup_data['version'] = yaymail_version();
213 } else {
214 $backup_data['version'] = defined( 'YAYWP_VERSION' ) ? YAYWP_VERSION : '1.0';
215 }
216
217 $backup_data = apply_filters( 'yaymail_backup_state_data', $backup_data );
218
219 wp_send_json_success(
220 [
221 'message' => 'success',
222 'data' => $backup_data,
223 'file_name' => $this->export_file_name_prefix() . '_export_backup_' . gmdate( 'm-d-Y' ),
224 ]
225 );
226
227 } catch ( \Error $error ) {
228 yaymail_get_logger( $error );
229 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
230 } catch ( \Exception $exception ) {
231 yaymail_get_logger( $exception );
232 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
233 }//end try
234 }
235
236 public function sanitize( $array ) {
237
238 return wp_kses_post_deep( $array );
239 }
240
241 /**
242 * File name prefix for exported/backup downloads, matching the frontend's
243 * brand name per platform (constants/theme.ts WP_COLORS vs the free "yaymail"
244 * default). Reads the "platform" the frontend sends alongside these AJAX
245 * requests (see common/ajax's getPlatform() calls) since these admin-ajax.php
246 * requests don't reliably expose the calling screen via get_current_screen().
247 */
248 private function export_file_name_prefix() {
249 $platform = isset( $_POST['platform'] ) ? sanitize_text_field( wp_unslash( $_POST['platform'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing
250 return 'email-builder' === $platform ? 'email_builder' : 'yaymail';
251 }
252
253 public function process_plugin_installer( $slug ) {
254 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
255 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
256 require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';
257 require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
258
259 $api = plugins_api(
260 'plugin_information',
261 [
262 'slug' => $slug,
263 'fields' => [
264 'short_description' => false,
265 'sections' => false,
266 'requires' => false,
267 'rating' => false,
268 'ratings' => false,
269 'downloaded' => false,
270 'last_updated' => false,
271 'added' => false,
272 'tags' => false,
273 'compatibility' => false,
274 'homepage' => false,
275 'donate_link' => false,
276 ],
277 ]
278 );
279
280 $skin = new \WP_Ajax_Upgrader_Skin();
281
282 $plugin_upgrader = new \Plugin_Upgrader( $skin );
283
284 try {
285 $result = $plugin_upgrader->install( $api->download_link );
286
287 if ( is_wp_error( $result ) ) {
288 yaymail_get_logger( $result );
289 }
290
291 return true;
292 } catch ( \Exception $exception ) {
293 yaymail_get_logger( $exception );
294 }
295
296 return false;
297 }
298
299 public function install_yaysmtp() {
300 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
301 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
302 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
303 }
304
305 if ( ! current_user_can( 'install_plugins' ) && ! current_user_can( 'activate_plugins' ) ) {
306 return wp_send_json_error( [ 'mess' => __( 'You do not have permission to install plugins', 'yaymail' ) ] );
307 }
308
309 try {
310 $is_installed = $this->process_plugin_installer( 'yaysmtp' );
311
312 if ( false === $is_installed ) {
313 wp_send_json_error( [ 'message' => $is_installed ] );
314 }
315
316 $result = activate_plugin( 'yaysmtp/yay-smtp.php' );
317
318 if ( is_wp_error( $result ) ) {
319 return wp_send_json_error( [ 'mess' => esc_html( $result->get_error_message() ) ] );
320 }
321
322 wp_send_json_success(
323 [
324 'installed' => null === $result,
325 ]
326 );
327
328 } catch ( \Error $error ) {
329 yaymail_get_logger( $error );
330 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
331 } catch ( \Exception $exception ) {
332 yaymail_get_logger( $exception );
333 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
334 }//end try
335 }
336
337 public function send_test_mail() {
338 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
339 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
340 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
341 }
342 try {
343 $template_name = isset( $_POST['template_name'] ) ? sanitize_text_field( wp_unslash( $_POST['template_name'] ) ) : '';
344 $order_id = isset( $_POST['order_id'] ) ? sanitize_text_field( wp_unslash( $_POST['order_id'] ) ) : 'sample_order';
345 $email = isset( $_POST['email'] ) ? sanitize_text_field( $_POST['email'] ) : '';
346 $is_wc_email = strpos( $template_name, 'wp-core-' ) !== 0;
347
348 if ( empty( $template_name ) ) {
349 return wp_send_json_error( [ 'mess' => __( 'Can\'t find template', 'yaymail' ) ] );
350 }
351
352 if ( empty( $order_id ) && $is_wc_email ) {
353 return wp_send_json_error( [ 'mess' => __( 'Can\'t find order', 'yaymail' ) ] );
354 }
355
356 if ( empty( $email ) ) {
357 return wp_send_json_error( [ 'mess' => __( 'Can\'t find email', 'yaymail' ) ] );
358 }
359
360 $template = new YayMailTemplate( $template_name );
361
362 $render_data = [];
363
364 if ( empty( $order_id ) || ( 'sample_order' === $order_id ) ) {
365 $render_data['is_sample'] = true;
366 } else {
367 $render_data['order'] = wc_get_order( $order_id );
368 }
369
370 $render_data['is_customized_preview'] = true;
371 // check if email template on preview and send test mail
372
373 update_option( 'yaymail_default_email_test', $email );
374
375 $html = $template->get_content( $render_data );
376
377 $headers = "Content-Type: text/html\r\n";
378 $subject = __( 'Email Test', 'yaymail' );
379
380 if ( $is_wc_email ) {
381 $class_wc_email = \WC_Emails::instance();
382 $send_mail = $class_wc_email->send( $email, $subject, $html, $headers, [] );
383 } else {
384 // $html is already the fully-rendered wp-core-mail template output.
385 // Without this marker, WpMail::custom_wp_mail_body() (hooked on the
386 // 'wp_mail' filter, meant to wrap *raw* WP core messages like a
387 // password-reset email) can't tell it apart from unrendered content
388 // and wraps it in the template a second time -- the same marker
389 // AddonWpMailController::woocommerce_mail_content() uses for real
390 // WooCommerce sends.
391 $html = '<!-- yaymail:wp-has-template-email-content -->' . $html;
392 $send_mail = wp_mail( $email, $subject, $html, $headers, [] );
393 }
394 if ( ! $send_mail ) {
395 return wp_send_json_error( [ 'mess' => __( 'Can\'t send email', 'yaymail' ) ] );
396 }
397
398 wp_send_json_success(
399 [
400 'email' => $email,
401 'send_mail_success' => $send_mail,
402 ]
403 );
404 } catch ( \Error $error ) {
405 yaymail_get_logger( $error );
406 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
407 } catch ( \Exception $exception ) {
408 yaymail_get_logger( $exception );
409 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
410 }//end try
411 }
412
413 public function preview_mail() {
414 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
415 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
416 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
417 }
418 try {
419 $order_id = ! empty( $_POST['order_id'] ) ? sanitize_text_field( wp_unslash( $_POST['order_id'] ) ) : 'sample_order';
420 $template_data = isset( $_POST['template_data'] ) ? $this->sanitize( json_decode( wp_unslash( $_POST['template_data'] ), true ) ) : []; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
421 $unsaved_settings = isset( $_POST['unsaved_settings'] ) ? $this->sanitize( wp_unslash( $_POST['unsaved_settings'] ) ) : []; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
422
423 if ( empty( $template_data ) ) {
424 return wp_send_json_error( [ 'mess' => __( 'Can\'t find template', 'yaymail' ) ] );
425 }
426
427 if ( empty( $order_id ) ) {
428 return wp_send_json_error( [ 'mess' => __( 'Can\'t find order', 'yaymail' ) ] );
429 }
430
431 $template = new YayMailTemplate( $template_data['name'] );
432
433 if ( ! empty( $unsaved_settings ) ) {
434 global $yaymail_unsaved_settings;
435 $yaymail_unsaved_settings = $unsaved_settings;
436 }
437
438 $template->set_background_color( $template_data['background_color'] );
439 $template->set_text_link_color( $template_data['text_link_color'] );
440 $template->set_global_header_settings( $template_data['global_header_settings'] );
441 $template->set_global_footer_settings( $template_data['global_footer_settings'] );
442 $template->set_elements( $template_data['elements'] );
443
444 $render_data = [];
445
446 if ( empty( $order_id ) || ( 'sample_order' === $order_id ) ) {
447 $render_data['is_sample'] = true;
448 } else {
449 $render_data['order'] = wc_get_order( $order_id );
450 }
451
452 $render_data['is_customized_preview'] = true;
453 // check if email template on preview and send test mail
454
455 $html = $template->get_content( $render_data );
456
457 if ( strpos( $template->get_name(), 'wp-core-' ) !== 0 ) {
458 // TODO: render with passing settings
459 $current_email = null;
460 $subject = 'Sample Subject';
461 $emails = wc()->mailer()->emails;
462 foreach ( $emails as $email ) {
463 if ( $email->id === $template_data['name'] ) {
464 $current_email = $email;
465 if ( method_exists( $current_email, 'set_object' ) ) {
466 if ( ! empty( $render_data['order'] ) && is_a( $render_data['order'], '\WC_Order' ) ) {
467 $current_email->set_object( $render_data['order'] );
468 } else {
469 $current_email->set_object( Helpers::get_dummy_order() );
470 }
471 }
472 break;
473 }
474 }
475 }
476
477 if ( ! empty( $current_email ) ) {
478 $subject = $current_email->get_subject();
479 }
480 $email_address = wp_get_current_user()->user_email ?? '[email protected]';
481
482 wp_send_json_success(
483 [
484 'html' => $html,
485 'subject' => $subject,
486 'email_address' => $email_address,
487 ]
488 );
489 } catch ( \Error $error ) {
490 yaymail_get_logger( $error );
491 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
492 } catch ( \Exception $exception ) {
493 yaymail_get_logger( $exception );
494 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
495 }//end try
496 }
497
498 public function preview_mail_for_woo() {
499 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
500 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
501 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
502 }
503 try {
504 $template_name = isset( $_POST['template_name'] ) ? sanitize_text_field( wp_unslash( $_POST['template_name'] ) ) : '';
505 $search_order_id = isset( $_POST['search_order_id'] ) ? sanitize_text_field( wp_unslash( $_POST['search_order_id'] ) ) : null;
506 $email_address = isset( $_POST['email_address'] ) ? sanitize_text_field( wp_unslash( $_POST['email_address'] ) ) : '';
507
508 $email_preview_output = PreviewEmail\PreviewEmailWoo::email_preview_output( $search_order_id, $template_name, $email_address );
509
510 $email_preview_output = apply_filters( 'yaymail_preview_email', $email_preview_output, $search_order_id, $template_name, $email_address );
511
512 $send_mail = false;
513
514 if ( ! empty( $email_address ) && ! empty( $email_preview_output['html'] ) ) {
515 $headers = "Content-Type: text/html\r\n";
516 $class_wc_email = \WC_Emails::instance();
517 $subject = __( 'Email Preview', 'yaymail' );
518 $send_mail = $class_wc_email->send( $email_address, $subject, $email_preview_output['html'], $headers, [] );
519 if ( ! $send_mail ) {
520 return wp_send_json_error( [ 'mess' => __( 'Can\'t send email', 'yaymail' ) ] );
521 }
522 }
523
524 wp_send_json_success(
525 [
526 'html' => ! empty( $email_preview_output['html'] ) ? $email_preview_output['html'] : __( 'No email content found', 'yaymail' ),
527 'subject' => ! empty( $email_preview_output['subject'] ) ? $email_preview_output['subject'] : __( 'No subject found', 'yaymail' ),
528 'is_disabled_send_mail' => ! empty( $email_preview_output['is_disabled_send_mail'] ) ? $email_preview_output['is_disabled_send_mail'] : false,
529 'send_mail_success' => $send_mail,
530 ]
531 );
532 } catch ( \Error $error ) {
533 yaymail_get_logger( $error );
534 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
535 } catch ( \Exception $exception ) {
536 yaymail_get_logger( $exception );
537 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
538 }//end try
539 }
540
541 public function export_templates() {
542 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
543 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
544 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
545 }
546 try {
547 $templates = isset( $_POST['templates'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['templates'] ) ) : [];
548 // TODO: sanitize
549 $default = [
550 'post_type' => 'yaymail_template',
551 'post_status' => [ 'publish', 'pending', 'future' ],
552 'posts_per_page' => '-1',
553 'meta_query' => [
554 [
555 'key' => YayMailTemplate::META_KEYS['name'],
556 'value' => $templates,
557 'compare' => 'IN',
558 ],
559 ],
560 ];
561 $export_data = [];
562 $query = new \WP_Query( $default );
563 if ( $query->have_posts() ) {
564 $posts = $query->get_posts();
565 foreach ( $posts as $post ) {
566 $template_name = get_post_meta( $post->ID, YayMailTemplate::META_KEYS['name'], true );
567 $elements = get_post_meta( $post->ID, YayMailTemplate::META_KEYS['elements'], true );
568 $language = get_post_meta( $post->ID, YayMailTemplate::META_KEYS['language'], true );
569 $text_link_color = get_post_meta( $post->ID, YayMailTemplate::META_KEYS['text_link_color'], true );
570 $background_color = get_post_meta( $post->ID, YayMailTemplate::META_KEYS['background_color'], true );
571 $content_background_color = get_post_meta( $post->ID, YayMailTemplate::META_KEYS['content_background_color'], true );
572 $content_text_color = get_post_meta( $post->ID, YayMailTemplate::META_KEYS['content_text_color'], true );
573 $title_color = get_post_meta( $post->ID, YayMailTemplate::META_KEYS['title_color'], true );
574 $file_name = "{$template_name}.json";
575 // Every WP-core template (e.g. wp-core-mail) is saved with a
576 // non-empty language meta (the site locale), unlike WooCommerce
577 // templates -- gating on "no language" here used to silently
578 // drop every WP-core template from the export with no error.
579 // find_by_name() below only ever looks templates up by name, so
580 // there's no separate per-language row to disambiguate against.
581 $export_data[] = [
582 'file_name' => $file_name,
583 'templates_data' => [
584 'template' => $template_name,
585 'elements' => $elements,
586 'language' => $language,
587 'text_link_color' => $text_link_color,
588 'background_color' => $background_color,
589 'content_background_color' => $content_background_color,
590 'content_text_color' => $content_text_color,
591 'title_color' => $title_color,
592 ],
593 ];
594 }//end foreach
595 }//end if
596 wp_reset_postdata();
597 wp_send_json_success(
598 [
599 'message' => __( 'Export successfully', 'yaymail' ),
600 'data' => $export_data,
601 'file_name' => $this->export_file_name_prefix() . '_customizer_templates_' . gmdate( 'm-d-Y' ),
602 ]
603 );
604 } catch ( \Error $error ) {
605 yaymail_get_logger( $error );
606 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
607 } catch ( \Exception $exception ) {
608 yaymail_get_logger( $exception );
609 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
610 }//end try
611 }
612
613 public function import_templates() {
614 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
615 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
616 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
617 }
618 try {
619 if ( ! empty( $_FILES ) ) {
620 $result = $this->process_import( $_FILES );
621 wp_send_json_success(
622 [
623 'imported_data' => $result,
624 ]
625 );
626 } else {
627 wp_send_json_error( [ 'message' => __( 'Can\'t find import files.', 'yaymail' ) ] );
628 }
629 } catch ( \Error $error ) {
630 yaymail_get_logger( $error );
631 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
632 } catch ( \Exception $exception ) {
633 yaymail_get_logger( $exception );
634 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
635 }
636 }
637
638 public function process_import( $files ) {
639 global $wp_filesystem;
640 if ( empty( $wp_filesystem ) ) {
641 require_once ABSPATH . '/wp-admin/includes/file.php';
642 WP_Filesystem();
643 }
644 $imported_templates = [];
645 $is_legacy = false;
646 foreach ( $files as $file ) {
647 if ( isset( $file['type'] ) ) {
648 if ( 'application/json' === $file['type'] ) {
649 if ( ! empty( $file['tmp_name'] ) ) {
650 $file_tmp_name = sanitize_text_field( $file['tmp_name'] );
651 $file_content = $wp_filesystem->get_contents( $file_tmp_name );
652 $file_content = json_decode( $file_content, true );
653 if ( ! isset( $file_content['template'] ) ) {
654 if ( isset( $file_content['yaymailTemplateExport'] ) ) {
655 $is_legacy = true;
656 $imported_templates = array_merge( $imported_templates, $this->process_import_legacy( $file_content ) );
657 } else {
658 continue;
659 }
660 } else {
661 $update_result = $this->processing_import_update_data( $file_content );
662 if ( ! empty( $update_result ) ) {
663 $imported_templates[] = $update_result;
664 }
665 }
666 }//end if
667 }//end if
668 }//end if
669 }//end foreach
670 if ( $is_legacy ) {
671 MainMigration::get_instance()->migrate( true );
672 }
673 return $imported_templates;
674 }
675
676 public function process_import_legacy( $file_content ) {
677 $updated_templates = [];
678 // Import templates
679 foreach ( $file_content['yaymailTemplateExport'] as $template ) {
680 $updated_result = $this->processing_import_update_data( $template, true );
681 if ( ! empty( $updated_result ) ) {
682 $updated_templates[] = $updated_result;
683 }
684 }//end foreach
685 // Import settings
686 $import_settings = isset( $file_content['yaymail_settings'] ) ? $file_content['yaymail_settings'] : [];
687 if ( ! empty( $import_settings ) ) {
688 update_option( 'yaymail_settings', $import_settings );
689 }
690 return $updated_templates;
691 }
692
693 public function processing_import_update_data( $data, $is_legacy = false ) {
694 $template_name = $data['template'] ?? null;
695 $elements = $data['elements'] ?? null;
696 $text_link_color = $data['text_link_color'] ?? null;
697 $background_color = $data['background_color'] ?? null;
698 $title_color = $data['title_color'] ?? null;
699 $content_background_color = $data['content_background_color'] ?? null;
700 $content_text_color = $data['content_text_color'] ?? null;
701
702 if ( empty( $template_name ) ) {
703 return null;
704 }
705
706 $template = new YayMailTemplate( $template_name );
707 if ( ! $template->is_exists() ) {
708 return null;
709 }
710
711 $template->set_elements( $elements );
712 $template->set_text_link_color( $text_link_color );
713 $template->set_background_color( $background_color );
714 $template->set_title_color( $title_color );
715 $template->set_content_background_color( $content_background_color );
716 $template->set_content_text_color( $content_text_color );
717 if ( $is_legacy ) {
718 $template->set_status( 'inactive' );
719 }
720
721 $template->save();
722
723 wp_reset_postdata();
724
725 return [
726 'template_name' => $template_name,
727 ];
728 }
729
730 /**
731 * Process a custom hook request and generate HTML content.
732 *
733 * This function handles a custom hook request, generates HTML content based on the provided data and attributes.
734 * It is designed to be used as an AJAX callback.
735 *
736 * @example $_POST['data'] =
737 * [
738 * 'template_data' => YayMail\YayMailTemplate,
739 * 'order_id' => 'sample_order',
740 * 'attributes' => [
741 * [
742 * 'name' => 'hook',
743 * 'value' => 'your_hook'
744 * ],
745 * [
746 * 'name' => 'background_color',
747 * 'value' => '#ffffff'
748 * ]
749 * ]
750 * ]
751 *
752 * @return void This function sends a JSON response with HTML content or error messages.
753 */
754 public function get_custom_hook_html() {
755 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
756 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
757 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
758 }
759 try {
760 $attributes = isset( $_POST['data']['attributes'] ) ? $_POST['data']['attributes'] : []; // phpcs:ignore
761 if ( empty( $attributes ) ) {
762 return wp_send_json_error( [ 'mess' => __( 'Attributes empty', 'yaymail' ) ] );
763 }
764
765 /**
766 * Build data for shortcode
767 */
768 $template_model = \YayMail\Models\TemplateModel::get_instance();
769 $data = [];
770 if ( ! empty( $_POST['data']['template_data'] ) ) {
771 $data = \YayMail\Models\TemplateModel::get_shortcode_executor_data( sanitize_text_field( wp_unslash( $_POST['data']['template_data'] ) ), sanitize_text_field( wp_unslash( $_POST['data']['order_id'] ) ) );
772
773 $data['template']->set_props( sanitize_text_field( wp_unslash( $_POST['data']['template_data'] ) ) );
774 }
775
776 $hook_shortcodes = \YayMail\Shortcodes\HookShortcodes::get_instance();
777 $html = $hook_shortcodes->yaymail_handle_custom_hook_shortcode( $data, $attributes );
778 wp_send_json_success(
779 [
780 'html' => $html,
781 ]
782 );
783 } catch ( \Error $error ) {
784 yaymail_get_logger( $error );
785 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
786 } catch ( \Exception $exception ) {
787 yaymail_get_logger( $exception );
788 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
789 }//end try
790 }
791
792 /**
793 * Get all needed data when load YayMail template to customizer.
794 */
795 public function get_template_data_onload() {
796 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
797 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
798 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
799 }
800 try {
801 $setting_model = SettingModel::get_instance();
802 $settings_data = $setting_model->find_all();
803
804 $template_name = isset( $_POST['data']['template_name'] ) ? sanitize_text_field( wp_unslash( $_POST['data']['template_name'] ) ) : 'new_order';
805 $order_id = isset( $_POST['data']['order_id'] ) ? sanitize_text_field( wp_unslash( $_POST['data']['order_id'] ) ) : 'sample_order';
806
807 $template_model = TemplateModel::get_instance();
808
809 $shortcodes_data = $template_model->get_shortcodes_by_template_name_and_order_id( $template_name, $order_id );
810
811 $templates_data = apply_filters( 'yaymail_get_all_templates', $template_model->find_all() );
812
813 $selected_template_data = $template_model->find_by_name( $template_name );
814
815 $elements_data = TemplateModel::get_elements_for_template( $template_name );
816
817 $revision_model = RevisionModel::get_instance();
818 $revisions_data = $revision_model->get_by_template( $template_name );
819
820 wp_send_json_success(
821 [
822 'settings_data' => $settings_data,
823 'templates_data' => $templates_data,
824 'selected_template_data' => $selected_template_data,
825 'elements_data' => $elements_data,
826 'revisions_data' => $revisions_data,
827 'shortcodes_data' => $shortcodes_data,
828 ]
829 );
830 } catch ( \Error $error ) {
831 yaymail_get_logger( $error );
832 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
833 } catch ( \Exception $exception ) {
834 yaymail_get_logger( $exception );
835 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
836 } catch ( \Throwable $throwable ) {
837 yaymail_get_logger( $throwable );
838 wp_send_json_error( [ 'mess' => $throwable->getMessage() ] );
839 }//end try
840 }
841
842 public function yaymail_review() {
843 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
844 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
845 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
846 }
847 try {
848
849 $yaymail_review = update_option( 'yaymail_review', true );
850
851 wp_send_json_success(
852 [
853 'reviewed' => $yaymail_review,
854 ]
855 );
856
857 } catch ( \Error $error ) {
858 yaymail_get_logger( $error );
859 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
860 } catch ( \Exception $exception ) {
861 yaymail_get_logger( $exception );
862 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
863 }
864 }
865
866 public function change_ghf_tour() {
867 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
868 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
869 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
870 }
871
872 try {
873 $next_move = isset( $_POST['next_move'] ) ? sanitize_text_field( wp_unslash( $_POST['next_move'] ) ) : 'initial';
874 $ghf_tour = update_option( 'yaymail_ghf_tour', $next_move );
875
876 wp_send_json_success(
877 [
878 'ghf_tour' => $ghf_tour,
879 ]
880 );
881 } catch ( \Error $error ) {
882 yaymail_get_logger( $error );
883 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
884 } catch ( \Exception $exception ) {
885 yaymail_get_logger( $exception );
886 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
887 }
888 }
889
890 public function dismiss_multi_select_notice() {
891 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
892 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
893 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
894 }
895
896 try {
897 update_option( 'yaymail_show_multi_select_notice', 'no' );
898
899 wp_send_json_success(
900 [
901 'show_multi_select_notice' => 'no',
902 ]
903 );
904 } catch ( \Error $error ) {
905 yaymail_get_logger( $error );
906 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
907 } catch ( \Exception $exception ) {
908 yaymail_get_logger( $exception );
909 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
910 }
911 }
912
913 public function dismiss_new_element_notification() {
914 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
915 if ( ! wp_verify_nonce( $nonce, 'yaymail_frontend_nonce' ) ) {
916 return wp_send_json_error( [ 'mess' => __( 'Verify nonce failed', 'yaymail' ) ] );
917 }
918
919 $elements = isset( $_POST['elements'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['elements'] ) ) : [];
920
921 $viewed_new_elements = get_option( 'yaymail_viewed_new_elements', [] );
922 $viewed_new_elements = array_unique( array_merge( $viewed_new_elements, $elements ) );
923
924 try {
925 update_option( 'yaymail_viewed_new_elements', $viewed_new_elements );
926
927 wp_send_json_success(
928 [
929 'viewed_new_elements' => $viewed_new_elements,
930 ]
931 );
932 } catch ( \Error $error ) {
933 wp_send_json_error( [ 'mess' => $error->getMessage() ] );
934 } catch ( \Exception $exception ) {
935 yaymail_get_logger( $exception );
936 wp_send_json_error( [ 'mess' => $exception->getMessage() ] );
937 }
938 }
939 }
940