Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails
WCTransactionalEmailPostsGenerator{} │ WC 1.0
Class WCTransactionalEmailPostsGenerator
Handles the generation of WooCommerce transactional email templates. This class is responsible for initializing and managing default email templates, as well as generating new templates when required.
Hooks from the class
Usage
$WCTransactionalEmailPostsGenerator = new WCTransactionalEmailPostsGenerator(); // use class methods
Methods
- public __construct()
- public generate_email_template_if_not_exists( $email_type )
- public generate_email_templates( $templates_to_generate )
- public generate_initial_email_templates()
- public get_email_template( $email )
- public init_default_transactional_emails()
- public initialize()
- private generate_single_template( $email_type, $email_data )
Notes
- Package: Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails
WCTransactionalEmailPostsGenerator{} WCTransactionalEmailPostsGenerator{} code WC 10.7.0
class WCTransactionalEmailPostsGenerator {
/**
* WooCommerce Email Template Manager instance.
*
* @var WCTransactionalEmailPostsManager
*/
private $template_manager;
/**
* Default templates.
*
* @var array<string, \WC_Email>
*/
private $default_templates = array();
/**
* Transient name.
*
* @var string
*/
private $transient_name = 'wc_email_editor_initial_templates_generated';
/**
* Constructor.
*
* Initializes the WCTransactionalEmailPostsGenerator by setting up the template manager.
*/
public function __construct() {
$this->template_manager = WCTransactionalEmailPostsManager::get_instance();
}
/**
* Initialize the email template generator.
*
* This function initializes the email template generator by loading the default templates
* and generating initial email templates if needed.
*
* @internal
*/
public function initialize() {
if ( Constants::get_constant( 'WC_VERSION' ) === get_transient( $this->transient_name ) ) {
// if templates are already generated, we don't need to run this function again.
return true;
}
$this->init_default_transactional_emails();
$this->generate_initial_email_templates();
}
/**
* Initialize the default WooCommerce Transactional Emails.
*
* This function initializes the default templates for the core transactional emails.
* It fetches all the emails from WooCommerce and filters them to include only the core transactional emails.
*/
public function init_default_transactional_emails() {
if ( ! empty( $this->default_templates ) ) {
// If the default templates are already initialized, we don't need to run this function again.
return;
}
$core_transactional_emails = WCTransactionalEmails::get_transactional_emails();
$wc_emails = \WC_Emails::instance();
/**
* WooCommerce Transactional Emails instance.
*
* @var \WC_Email[]
*/
$email_types = $wc_emails->get_emails();
// Filter the emails to include only the core transactional emails.
$email_types = array_filter(
$email_types,
function ( $email ) use ( $core_transactional_emails ) {
return in_array( $email->id, $core_transactional_emails, true );
}
);
$this->default_templates = array_reduce(
$email_types,
function ( $acc, $email ) {
$acc[ $email->id ] = $email;
return $acc;
},
array()
);
}
/**
* Get the email template for the given email.
*
* Looks for the initial email block content in plugins/woocommerce/templates/emails/block.
*
* @param \WC_Email $email The email object.
* @return string The email template.
*/
public function get_email_template( $email ) {
$template_name = ! empty( $email->template_block ) ? $email->template_block : str_replace( 'plain', 'block', $email->template_plain );
try {
$template_html = wc_get_template_html(
$template_name,
array(),
'',
$email->template_base ?? ''
);
} catch ( \Exception $e ) {
// wc_get_template_html() uses ob_start(), so we need to clean the output buffer if an exception is thrown.
if ( ob_get_level() > 0 ) {
ob_end_clean();
}
$template_html = '';
}
// wc_get_template_html does not throw an error when the template is not found.
// We need to check if the template is not found by checking the template_html content.
$has_template_error =
StringUtil::contains( $template_html, 'No such file or directory', false ) ||
StringUtil::contains( $template_html, 'Failed to open stream', false ) ||
StringUtil::contains( $template_html, 'Warning: include', false );
if ( is_wp_error( $template_html ) || empty( $template_html ) || $has_template_error ) {
$default_template_name = 'emails/block/default-block-content.php';
$template_html = wc_get_template_html(
$default_template_name,
array()
);
}
/**
* Filter the email template HTML.
*
* @param string $template_html The email template HTML.
* @param \WC_Email $email The email object.
* @since 10.7.0
*/
$template_html = apply_filters( 'woocommerce_email_block_template_html', $template_html, $email );
return $template_html;
}
/**
* Generate initial email templates.
*
* This function generates the initial email templates for the core transactional emails.
* It checks if the templates are already generated and if not, it generates them.
*
* @return bool True if the templates are generated, false otherwise.
*/
public function generate_initial_email_templates() {
$core_transactional_emails = WCTransactionalEmails::get_transactional_emails();
$templates_to_generate = array();
foreach ( $core_transactional_emails as $email_type ) {
if ( empty( $this->template_manager->get_email_template_post_id( $email_type ) ) ) {
$templates_to_generate[] = $email_type;
}
}
if ( empty( $templates_to_generate ) ) {
return;
}
$result = $this->generate_email_templates( $templates_to_generate );
if ( is_wp_error( $result ) ) {
return false;
}
set_transient( $this->transient_name, Constants::get_constant( 'WC_VERSION' ), WEEK_IN_SECONDS );
// Flush rewrite rules to ensure the new templates are loaded.
flush_rewrite_rules();
return true;
}
/**
* Generate email template if it doesn't exist.
*
* This function generates an email template if it doesn't exist.
*
* @param string $email_type The email type.
* @return int The post ID of the generated template.
* @throws \Exception When post creation fails.
*/
public function generate_email_template_if_not_exists( $email_type ) {
$email_data = $this->default_templates[ $email_type ];
if ( $this->template_manager->get_email_template_post_id( $email_type ) || empty( $email_data ) ) {
return $this->template_manager->get_email_template_post_id( $email_type );
}
return $this->generate_single_template( $email_type, $email_data );
}
/**
* Generate email templates.
*
* This function generates the email templates for the given email types.
*
* @param array $templates_to_generate The email types to generate.
*/
public function generate_email_templates( $templates_to_generate ) {
global $wpdb;
$core_emails = array_filter(
$this->default_templates,
function ( $email_id ) use ( $templates_to_generate ) {
return in_array( $email_id, $templates_to_generate, true );
},
ARRAY_FILTER_USE_KEY
);
if ( empty( $core_emails ) ) {
return false;
}
// Start transaction.
$wpdb->query( 'START TRANSACTION' );
try {
foreach ( $core_emails as $email_type => $email_data ) {
$this->generate_single_template( $email_type, $email_data );
}
$wpdb->query( 'COMMIT' );
return true;
} catch ( \Exception $e ) {
$wpdb->query( 'ROLLBACK' );
return new \WP_Error( 'email_generation_failed', $e->getMessage() );
}
}
/**
* Generate a single email template.
*
* This function generates a single email template post and sets its postmeta association.
*
* @param string $email_type The email type.
* @param \WC_Email $email_data The transactional email data.
* @return int The post ID of the generated template.
* @throws \Exception When post creation fails.
*/
private function generate_single_template( $email_type, $email_data ) {
$post_data = array(
'post_type' => Integration::EMAIL_POST_TYPE,
'post_status' => 'publish',
'post_name' => $email_type,
'post_title' => $email_data->get_title(),
'post_excerpt' => $email_data->get_description(),
'post_content' => $this->get_email_template( $email_data ),
'meta_input' => array(
'_wp_page_template' => ( new WooEmailTemplate() )->get_slug(),
),
);
/**
* Filter the email content post data before creating the post.
*
* Allows third-party integrators to modify the post data (title, content, meta, etc.)
* before the email content post is created.
*
* @since 10.5.0
* @param array $post_data The post data array to be used for wp_insert_post().
* @param string $email_type The email type identifier (e.g., 'customer_processing_order').
* @param \WC_Email $email_data The WooCommerce email object.
*/
$post_data = apply_filters( 'woocommerce_email_content_post_data', $post_data, $email_type, $email_data );
$post_id = wp_insert_post( $post_data, true );
if ( is_wp_error( $post_id ) ) {
throw new \Exception( esc_html( $post_id->get_error_message() ) );
}
$this->template_manager->save_email_template_post_id( $email_type, $post_id );
return $post_id;
}
}