EmailPatterns
10 months ago
EmailTemplates
2 months ago
PersonalizationTags
3 months ago
WCTransactionalEmails
4 weeks ago
BlockEmailRenderer.php
7 months ago
EmailApiController.php
4 weeks ago
Integration.php
4 weeks ago
Logger.php
10 months ago
Package.php
1 year ago
PageRenderer.php
10 months ago
PersonalizationTagManager.php
1 year ago
TransactionalEmailPersonalizer.php
4 months ago
WooContentProcessor.php
2 months ago
Integration.php
483 lines
| 1 | <?php |
| 2 | |
| 3 | declare( strict_types=1 ); |
| 4 | |
| 5 | namespace Automattic\WooCommerce\Internal\EmailEditor; |
| 6 | |
| 7 | use Automattic\WooCommerce\EmailEditor\Email_Editor_Container; |
| 8 | use Automattic\WooCommerce\EmailEditor\Engine\Dependency_Check; |
| 9 | use Automattic\WooCommerce\Internal\Admin\EmailPreview\EmailPreview; |
| 10 | use Automattic\WooCommerce\Internal\EmailEditor\EmailPatterns\PatternsController; |
| 11 | use Automattic\WooCommerce\Internal\EmailEditor\EmailTemplates\TemplatesController; |
| 12 | use Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCEmailTemplateAutoApplier; |
| 13 | use Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCEmailTemplateDivergenceDetector; |
| 14 | use Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCEmailTemplateSyncBackfill; |
| 15 | use Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCEmailTemplateSyncTracker; |
| 16 | use Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCTransactionalEmails; |
| 17 | use Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCTransactionalEmailPostsManager; |
| 18 | use Automattic\WooCommerce\Internal\EmailEditor\EmailTemplates\TemplateApiController; |
| 19 | use Automattic\WooCommerce\EmailEditor\Engine\Logger\Email_Editor_Logger; |
| 20 | use WP_Post; |
| 21 | |
| 22 | defined( 'ABSPATH' ) || exit; |
| 23 | |
| 24 | /** |
| 25 | * Integration class for the Email Editor functionality. |
| 26 | */ |
| 27 | class Integration { |
| 28 | const EMAIL_POST_TYPE = 'woo_email'; |
| 29 | |
| 30 | /** |
| 31 | * The email editor page renderer instance. |
| 32 | * |
| 33 | * @var PageRenderer |
| 34 | */ |
| 35 | private PageRenderer $editor_page_renderer; |
| 36 | |
| 37 | /** |
| 38 | * The dependency check instance. |
| 39 | * |
| 40 | * @var Dependency_Check |
| 41 | */ |
| 42 | private Dependency_Check $dependency_check; |
| 43 | |
| 44 | /** |
| 45 | * The template API controller instance. |
| 46 | * |
| 47 | * @var TemplateApiController |
| 48 | */ |
| 49 | private TemplateApiController $template_api_controller; |
| 50 | |
| 51 | /** |
| 52 | * The email data API controller instance. |
| 53 | * |
| 54 | * @var EmailApiController |
| 55 | */ |
| 56 | private EmailApiController $email_api_controller; |
| 57 | |
| 58 | /** |
| 59 | * The WC_Email instance. |
| 60 | * |
| 61 | * @var \WC_Email |
| 62 | */ |
| 63 | private \WC_Email $wc_email_instance; |
| 64 | |
| 65 | /** |
| 66 | * Constructor. |
| 67 | */ |
| 68 | public function __construct() { |
| 69 | $editor_container = Email_Editor_Container::container(); |
| 70 | $this->dependency_check = $editor_container->get( Dependency_Check::class ); |
| 71 | } |
| 72 | |
| 73 | /** |
| 74 | * Initialize the integration. |
| 75 | * |
| 76 | * @internal |
| 77 | */ |
| 78 | final public function init(): void { |
| 79 | if ( ! $this->dependency_check->are_dependencies_met() ) { |
| 80 | // If dependencies are not met, do not initialize the email editor integration. |
| 81 | return; |
| 82 | } |
| 83 | |
| 84 | add_action( 'woocommerce_init', array( $this, 'initialize' ) ); |
| 85 | |
| 86 | // Register the post deletion cleanup hook early and unconditionally so it works in |
| 87 | // both admin and non-admin contexts (e.g. WP-CLI). This only needs $wpdb and the |
| 88 | // posts manager singleton — it must not depend on the full editor init chain. |
| 89 | add_action( 'before_delete_post', array( $this, 'delete_email_template_associated_with_email_editor_post' ), 10, 2 ); |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Initialize the integration. |
| 94 | */ |
| 95 | public function initialize() { |
| 96 | $this->init_logger(); |
| 97 | $this->init_hooks(); |
| 98 | $this->extend_post_api(); |
| 99 | $this->extend_template_post_api(); |
| 100 | $this->register_hooks(); |
| 101 | } |
| 102 | |
| 103 | /** |
| 104 | * Initialize the logger. |
| 105 | */ |
| 106 | public function init_logger() { |
| 107 | $editor_container = Email_Editor_Container::container(); |
| 108 | $logger = $editor_container->get( Email_Editor_Logger::class ); |
| 109 | |
| 110 | // Register the WooCommerce logger with the email editor package. |
| 111 | $logger->set_logger( new Logger( wc_get_logger() ) ); |
| 112 | } |
| 113 | |
| 114 | /** |
| 115 | * Initialize hooks for required classes. |
| 116 | */ |
| 117 | public function init_hooks() { |
| 118 | $container = wc_get_container(); |
| 119 | $container->get( PatternsController::class ); |
| 120 | $container->get( TemplatesController::class ); |
| 121 | $container->get( PersonalizationTagManager::class ); |
| 122 | $container->get( BlockEmailRenderer::class ); |
| 123 | $container->get( WCTransactionalEmails::class ); |
| 124 | $this->editor_page_renderer = $container->get( PageRenderer::class ); |
| 125 | $this->template_api_controller = $container->get( TemplateApiController::class ); |
| 126 | $this->email_api_controller = $container->get( EmailApiController::class ); |
| 127 | |
| 128 | // Using any email class to get the instance. |
| 129 | $registered_emails = \WC_Emails::instance()->get_emails(); |
| 130 | if ( isset( $registered_emails['WC_Email_New_Order'] ) ) { |
| 131 | $this->wc_email_instance = $registered_emails['WC_Email_New_Order']; |
| 132 | } else { |
| 133 | $first_email_key = array_key_first( $registered_emails ); |
| 134 | $this->wc_email_instance = $registered_emails[ $first_email_key ]; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | /** |
| 139 | * Register hooks for the integration. |
| 140 | */ |
| 141 | public function register_hooks() { |
| 142 | add_filter( 'woocommerce_email_editor_post_types', array( $this, 'add_email_post_type' ) ); |
| 143 | add_filter( 'woocommerce_is_email_editor_page', array( $this, 'is_editor_page' ), 10, 1 ); |
| 144 | add_filter( 'replace_editor', array( $this, 'replace_editor' ), 10, 2 ); |
| 145 | add_filter( 'woocommerce_email_editor_send_preview_email_rendered_data', array( $this, 'update_send_preview_email_rendered_data' ), 10, 2 ); |
| 146 | add_filter( 'woocommerce_email_editor_send_preview_email_personalizer_context', array( $this, 'update_send_preview_email_personalizer_context' ) ); |
| 147 | add_filter( 'woocommerce_email_editor_preview_post_template_html', array( $this, 'update_preview_post_template_html_data' ), 100, 1 ); |
| 148 | add_action( 'woocommerce_email_editor_send_preview_email_before_wp_mail', array( $this, 'send_preview_email_before_wp_mail' ), 10 ); |
| 149 | add_action( 'woocommerce_email_editor_send_preview_email_after_wp_mail', array( $this, 'send_preview_email_after_wp_mail' ), 10 ); |
| 150 | add_filter( 'woocommerce_email_editor_send_preview_email_subject', array( $this, 'update_email_subject_for_send_preview_email' ), 10, 2 ); |
| 151 | add_action( 'rest_api_init', array( $this->email_api_controller, 'register_routes' ) ); |
| 152 | // Priority 11 ensures the email editor's `init` bootstrap (default priority 10) |
| 153 | // has registered the `woo_email` post type before we register meta against it. |
| 154 | add_action( 'init', array( WCEmailTemplateDivergenceDetector::class, 'register_meta' ), 11 ); |
| 155 | add_action( 'woocommerce_updated', array( WCEmailTemplateDivergenceDetector::class, 'run_sweep' ), 20 ); |
| 156 | add_action( WCEmailTemplateSyncBackfill::BACKFILL_COMPLETE_ACTION, array( WCEmailTemplateDivergenceDetector::class, 'run_sweep' ), 10 ); |
| 157 | // Fresh installs never cross the 10.8 db-update boundary, so the RSM-149 |
| 158 | // backfill never runs and `BACKFILL_COMPLETE_OPTION` is never written. |
| 159 | // Stamp it from the `woocommerce_newly_installed` action so `run_sweep()` |
| 160 | // doesn't sit dormant forever on new sites. |
| 161 | add_action( 'woocommerce_newly_installed', array( WCEmailTemplateDivergenceDetector::class, 'mark_backfill_complete_on_fresh_install' ), 20 ); |
| 162 | add_action( WCEmailTemplateAutoApplier::AUTO_APPLY_AS_HOOK, array( WCEmailTemplateAutoApplier::class, 'run' ), 10 ); |
| 163 | add_action( 'woocommerce_email_template_divergence_sweep_complete', array( WCEmailTemplateAutoApplier::class, 'schedule' ), 10 ); |
| 164 | // RSM-145 Tracks instrumentation: fire `_backfill_completed` once when the |
| 165 | // RSM-149 sync-meta backfill finalises. The backfill class itself is in the |
| 166 | // 10.8 feature freeze, so we hook the existing action it already publishes. |
| 167 | add_action( WCEmailTemplateSyncBackfill::BACKFILL_COMPLETE_ACTION, array( WCEmailTemplateSyncTracker::class, 'on_backfill_complete' ), 20 ); |
| 168 | } |
| 169 | |
| 170 | /** |
| 171 | * Add WooCommerce email post type to the list of supported post types. |
| 172 | * |
| 173 | * @param array $post_types List of post types. |
| 174 | * @return array Modified list of post types. |
| 175 | */ |
| 176 | public function add_email_post_type( array $post_types ): array { |
| 177 | $post_types[] = array( |
| 178 | 'name' => self::EMAIL_POST_TYPE, |
| 179 | 'args' => array( |
| 180 | 'labels' => array( |
| 181 | 'name' => __( 'Emails', 'woocommerce' ), |
| 182 | 'singular_name' => __( 'Email', 'woocommerce' ), |
| 183 | 'add_new_item' => __( 'Add Email', 'woocommerce' ), |
| 184 | 'edit_item' => __( 'Edit Email', 'woocommerce' ), |
| 185 | 'new_item' => __( 'New Email', 'woocommerce' ), |
| 186 | 'view_item' => __( 'View Email', 'woocommerce' ), |
| 187 | 'search_items' => __( 'Search Emails', 'woocommerce' ), |
| 188 | ), |
| 189 | 'rewrite' => array( 'slug' => self::EMAIL_POST_TYPE ), |
| 190 | 'supports' => array( |
| 191 | 'title', |
| 192 | 'editor' => array( |
| 193 | 'default-mode' => 'template-locked', |
| 194 | ), |
| 195 | 'excerpt', |
| 196 | 'custom-fields', |
| 197 | ), |
| 198 | 'capability_type' => self::EMAIL_POST_TYPE, |
| 199 | 'capabilities' => array( |
| 200 | 'edit_post' => 'manage_woocommerce', |
| 201 | 'read_post' => 'manage_woocommerce', |
| 202 | 'delete_post' => 'manage_woocommerce', |
| 203 | 'edit_posts' => 'manage_woocommerce', |
| 204 | 'edit_others_posts' => 'manage_woocommerce', |
| 205 | 'delete_posts' => 'manage_woocommerce', |
| 206 | 'publish_posts' => 'manage_woocommerce', |
| 207 | 'read_private_posts' => 'manage_woocommerce', |
| 208 | 'create_posts' => 'manage_woocommerce', |
| 209 | ), |
| 210 | 'map_meta_cap' => false, |
| 211 | ), |
| 212 | ); |
| 213 | return $post_types; |
| 214 | } |
| 215 | |
| 216 | /** |
| 217 | * Check if current page is email editor page. |
| 218 | * |
| 219 | * @param bool $is_editor_page Current editor page status. |
| 220 | * @return bool Whether current page is email editor page. |
| 221 | */ |
| 222 | public function is_editor_page( bool $is_editor_page ): bool { |
| 223 | if ( $is_editor_page ) { |
| 224 | return $is_editor_page; |
| 225 | } |
| 226 | |
| 227 | // We need to check early if we are on the email editor page. The check runs early so we can't use current_screen() here. |
| 228 | if ( is_admin() && isset( $_GET['post'] ) && isset( $_GET['action'] ) && 'edit' === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We are not verifying the nonce here because we are not using the nonce in the function and the data is okay in this context (WP-admin errors out gracefully). |
| 229 | $post = get_post( (int) $_GET['post'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We are not verifying the nonce here because we are not using the nonce in the function and the data is okay in this context (WP-admin errors out gracefully). |
| 230 | return $post && self::EMAIL_POST_TYPE === $post->post_type; |
| 231 | } |
| 232 | |
| 233 | return false; |
| 234 | } |
| 235 | |
| 236 | /** |
| 237 | * Replace the default editor with our custom email editor. |
| 238 | * |
| 239 | * @param bool $replace Whether to replace the editor. |
| 240 | * @param WP_Post $post Post object. |
| 241 | * @return bool Whether the editor was replaced. |
| 242 | */ |
| 243 | public function replace_editor( $replace, $post ) { |
| 244 | $current_screen = get_current_screen(); |
| 245 | if ( self::EMAIL_POST_TYPE === $post->post_type && $current_screen ) { |
| 246 | $this->editor_page_renderer->render(); |
| 247 | return true; |
| 248 | } |
| 249 | return $replace; |
| 250 | } |
| 251 | |
| 252 | /** |
| 253 | * Delete the email template associated with the email editor post when the post is permanently deleted. |
| 254 | * |
| 255 | * @param int $post_id The post ID. |
| 256 | * @param WP_Post $post The post object. |
| 257 | */ |
| 258 | public function delete_email_template_associated_with_email_editor_post( $post_id, $post ) { |
| 259 | if ( self::EMAIL_POST_TYPE !== $post->post_type ) { |
| 260 | return; |
| 261 | } |
| 262 | |
| 263 | $post_manager = WCTransactionalEmailPostsManager::get_instance(); |
| 264 | |
| 265 | $email_type = $post_manager->get_email_type_from_post_id( $post_id, true ); |
| 266 | |
| 267 | if ( empty( $email_type ) ) { |
| 268 | return; |
| 269 | } |
| 270 | |
| 271 | $post_manager->delete_email_template( $email_type ); |
| 272 | } |
| 273 | |
| 274 | /** |
| 275 | * Extend the post API for the wp_template post type to add and save the woocommerce_data field. |
| 276 | */ |
| 277 | public function extend_template_post_api(): void { |
| 278 | register_rest_field( |
| 279 | 'wp_template', |
| 280 | 'woocommerce_data', |
| 281 | array( |
| 282 | 'get_callback' => array( $this->template_api_controller, 'get_template_data' ), |
| 283 | 'update_callback' => array( $this->template_api_controller, 'save_template_data' ), |
| 284 | 'schema' => $this->template_api_controller->get_template_data_schema(), |
| 285 | ) |
| 286 | ); |
| 287 | } |
| 288 | |
| 289 | /** |
| 290 | * Filter email preview data to replace placeholders with actual content. |
| 291 | * |
| 292 | * This method retrieves the appropriate email type based on the request, |
| 293 | * generates the email content using the WooContentProcessor, and replaces |
| 294 | * the placeholder in the preview HTML. |
| 295 | * |
| 296 | * @param string $data The preview data. |
| 297 | * @param string $email_type The email type identifier (e.g., 'customer_processing_order'). |
| 298 | * @param int $post_id The post ID. |
| 299 | * @return string The updated preview data with placeholders replaced. |
| 300 | */ |
| 301 | private function update_email_preview_data( $data, string $email_type, $post_id = 0 ) { |
| 302 | $type_param = EmailPreview::DEFAULT_EMAIL_TYPE; |
| 303 | |
| 304 | if ( ! empty( $post_id ) ) { |
| 305 | $type_param = WCTransactionalEmailPostsManager::get_instance()->get_email_type_class_name_from_post_id( $post_id ); |
| 306 | } elseif ( ! empty( $email_type ) ) { |
| 307 | $type_param = WCTransactionalEmailPostsManager::get_instance()->get_email_type_class_name_from_email_id( $email_type ); |
| 308 | } |
| 309 | |
| 310 | $email_preview = wc_get_container()->get( EmailPreview::class ); |
| 311 | |
| 312 | try { |
| 313 | $message = $email_preview->generate_placeholder_content( $type_param ); |
| 314 | } catch ( \InvalidArgumentException $e ) { |
| 315 | // If the provided type was invalid, fall back to the default. |
| 316 | try { |
| 317 | $message = $email_preview->generate_placeholder_content( EmailPreview::DEFAULT_EMAIL_TYPE ); |
| 318 | } catch ( \Throwable $e ) { |
| 319 | return $data; |
| 320 | } |
| 321 | } catch ( \Throwable $e ) { |
| 322 | return $data; |
| 323 | } |
| 324 | |
| 325 | return str_replace( BlockEmailRenderer::WOO_EMAIL_CONTENT_PLACEHOLDER, $message, $data ); |
| 326 | } |
| 327 | |
| 328 | /** |
| 329 | * Filter email preview data used when sending a preview email. |
| 330 | * |
| 331 | * @param string $data The preview data. |
| 332 | * @param WP_Post $post The post object. |
| 333 | * @return string The updated preview data with placeholders replaced. |
| 334 | */ |
| 335 | public function update_send_preview_email_rendered_data( $data, $post ) { |
| 336 | $email_type = ''; |
| 337 | $post_body = file_get_contents( 'php://input' ); |
| 338 | |
| 339 | if ( $post_body ) { |
| 340 | $decoded_body = json_decode( $post_body ); |
| 341 | |
| 342 | if ( json_last_error() === JSON_ERROR_NONE && isset( $decoded_body->postId ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase |
| 343 | $post_id = absint( $decoded_body->postId ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase |
| 344 | |
| 345 | $email_type = WCTransactionalEmailPostsManager::get_instance()->get_email_type_from_post_id( $post_id ); |
| 346 | if ( ! empty( $email_type ) ) { |
| 347 | return $this->update_email_preview_data( $data, $email_type ); |
| 348 | } |
| 349 | } |
| 350 | } elseif ( ! empty( $post ) && $post instanceof \WP_Post ) { |
| 351 | $email_type = WCTransactionalEmailPostsManager::get_instance()->get_email_type_from_post_id( $post->ID ); |
| 352 | if ( ! empty( $email_type ) ) { |
| 353 | return $this->update_email_preview_data( $data, $email_type, $post->ID ); |
| 354 | } |
| 355 | } |
| 356 | return $data; |
| 357 | } |
| 358 | |
| 359 | /** |
| 360 | * Update the personalizer context for the send preview email. |
| 361 | * |
| 362 | * @param array $context The personalizer context. |
| 363 | * @return array The updated personalizer context. |
| 364 | */ |
| 365 | public function update_send_preview_email_personalizer_context( $context ) { |
| 366 | $post_manager = WCTransactionalEmailPostsManager::get_instance(); |
| 367 | $email_id = $post_manager->get_email_type_from_post_id( get_the_ID() ); |
| 368 | $email_type = $email_id ? $post_manager->get_email_type_class_name_from_email_id( $email_id ) : EmailPreview::DEFAULT_EMAIL_TYPE; |
| 369 | $email_preview = wc_get_container()->get( EmailPreview::class ); |
| 370 | |
| 371 | try { |
| 372 | $email_preview->set_email_type( $email_type ); |
| 373 | } catch ( \InvalidArgumentException $e ) { |
| 374 | // If the email type is invalid, return the context data as is. |
| 375 | return $context; |
| 376 | } |
| 377 | |
| 378 | $email = $email_preview->get_email(); |
| 379 | $email->recipient = $context['recipient_email'] ?? ''; |
| 380 | $personalizer = wc_get_container()->get( TransactionalEmailPersonalizer::class ); |
| 381 | |
| 382 | return $personalizer->prepare_context_data( $context, $email ); |
| 383 | } |
| 384 | |
| 385 | /** |
| 386 | * Filter email preview data used when previewing the email in new tab. |
| 387 | * |
| 388 | * @param string $data The preview HTML string. |
| 389 | * @return string The updated preview HTML with placeholders replaced. |
| 390 | */ |
| 391 | public function update_preview_post_template_html_data( $data ) { |
| 392 | // return early if the data does not contain the placeholder meaning it's already been processed. |
| 393 | if ( ! str_contains( (string) $data, BlockEmailRenderer::WOO_EMAIL_CONTENT_PLACEHOLDER ) ) { |
| 394 | return $data; |
| 395 | } |
| 396 | |
| 397 | // phpcs:disable WordPress.Security.NonceVerification.Recommended |
| 398 | // Nonce verification is disabled here because the preview action doesn't modify data, |
| 399 | // and the check caused issues with the 'Preview in new tab' feature due to context changes. |
| 400 | $type_param = isset( $_GET['woo_email'] ) ? sanitize_text_field( wp_unslash( $_GET['woo_email'] ) ) : ''; |
| 401 | |
| 402 | // check for post id (preview id) in the request. |
| 403 | $post_id = isset( $_REQUEST['preview_id'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['preview_id'] ) ) : ''; |
| 404 | |
| 405 | // phpcs:enable |
| 406 | return $this->update_email_preview_data( $data, $type_param, $post_id ); |
| 407 | } |
| 408 | |
| 409 | /** |
| 410 | * Extend the post API for the woo_email post type to add and save the woocommerce_data field. |
| 411 | */ |
| 412 | public function extend_post_api(): void { |
| 413 | register_rest_field( |
| 414 | self::EMAIL_POST_TYPE, |
| 415 | 'woocommerce_data', |
| 416 | array( |
| 417 | 'get_callback' => array( $this->email_api_controller, 'get_email_data' ), |
| 418 | 'update_callback' => array( $this->email_api_controller, 'save_email_data' ), |
| 419 | 'schema' => $this->email_api_controller->get_email_data_schema(), |
| 420 | ) |
| 421 | ); |
| 422 | } |
| 423 | |
| 424 | /** |
| 425 | * Action hook callback before sending the preview email via wp_mail |
| 426 | * |
| 427 | * @since 10.6.0 |
| 428 | * @return void |
| 429 | */ |
| 430 | public function send_preview_email_before_wp_mail() { |
| 431 | add_filter( 'wp_mail_from', array( $this->wc_email_instance, 'get_from_address' ) ); |
| 432 | add_filter( 'wp_mail_from_name', array( $this->wc_email_instance, 'get_from_name' ) ); |
| 433 | } |
| 434 | |
| 435 | /** |
| 436 | * Action hook callback after sending the preview email via wp_mail. |
| 437 | * |
| 438 | * @since 10.6.0 |
| 439 | * @return void |
| 440 | */ |
| 441 | public function send_preview_email_after_wp_mail() { |
| 442 | remove_filter( 'wp_mail_from', array( $this->wc_email_instance, 'get_from_address' ) ); |
| 443 | remove_filter( 'wp_mail_from_name', array( $this->wc_email_instance, 'get_from_name' ) ); |
| 444 | } |
| 445 | |
| 446 | /** |
| 447 | * Update the email subject for the send preview email. |
| 448 | * |
| 449 | * @param string $subject The email subject. |
| 450 | * @param WP_Post $post The post object. |
| 451 | * @return string The updated email subject. |
| 452 | */ |
| 453 | public function update_email_subject_for_send_preview_email( $subject, $post ) { |
| 454 | if ( ! $post instanceof \WP_Post || self::EMAIL_POST_TYPE !== $post->post_type ) { |
| 455 | return $subject; |
| 456 | } |
| 457 | |
| 458 | $post_manager = WCTransactionalEmailPostsManager::get_instance(); |
| 459 | |
| 460 | $email_type_class_name = $post_manager->get_email_type_class_name_from_post_id( $post->ID ); |
| 461 | |
| 462 | if ( empty( $email_type_class_name ) ) { |
| 463 | return $subject; |
| 464 | } |
| 465 | |
| 466 | /** |
| 467 | * Validate the email type class name. |
| 468 | * |
| 469 | * @var EmailPreview $email_preview |
| 470 | */ |
| 471 | $email_preview = wc_get_container()->get( EmailPreview::class ); |
| 472 | |
| 473 | try { |
| 474 | $email_preview->set_email_type( $email_type_class_name ); |
| 475 | return $email_preview->get_subject(); |
| 476 | } catch ( \InvalidArgumentException $e ) { |
| 477 | return $subject; |
| 478 | } catch ( \Throwable $e ) { |
| 479 | return $subject; |
| 480 | } |
| 481 | } |
| 482 | } |
| 483 |