declare( strict_types=1 );
namespace Automattic\WooCommerce\Internal\Admin\Emails;
use Automattic\WooCommerce\Internal\RestApiControllerBase;
use Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCTransactionalEmails;
use Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCTransactionalEmailPostsGenerator;
* Controller for the REST endpoint for the new email listing page.
class EmailListingRestController extends RestApiControllerBase {
const NONCE_KEY = 'email-listing-nonce';
* The root namespace for the JSON REST API endpoints.
protected string $route_namespace = 'wc-admin-email';
protected string $rest_base = 'settings/email/listing';
* Email template generator instance.
* @var WCTransactionalEmailPostsGenerator
private $email_template_generator;
* Get the WooCommerce REST API namespace for the class.
protected function get_rest_api_namespace(): string {
return 'wc-admin-email-listing';
public function __construct() {
$this->email_template_generator = new WCTransactionalEmailPostsGenerator();
* Perform the initialization.
public function initialize_template_generator() {
$this->email_template_generator->init_default_transactional_emails();
* Register the REST API endpoints handled by this controller.
public function register_routes() {
$this->initialize_template_generator();
'/' . $this->rest_base . '/recreate-email-post',
'methods' => \WP_REST_Server::CREATABLE,
'callback' => fn( $request ) => $this->recreate_email_post( $request ),
'permission_callback' => fn( $request ) => $this->check_permissions( $request ),
'args' => $this->get_args_for_recreate_email_post(),
'schema' => $this->get_schema_with_message(),
* Get the accepted arguments for the POST recreate-email-post request.
private function get_args_for_recreate_email_post() {
'description' => __( 'The email ID to recreate the post for.', 'woocommerce' ),
'validate_callback' => fn( $email_id ) => $this->validate_email_id( $email_id ),
'sanitize_callback' => 'sanitize_text_field',
* Get the schema for the POST recreate-email-post and save-transient requests.
private function get_schema_with_message() {
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'email-listing-with-message',
'description' => __( 'A message indicating that the action completed successfully.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'The post ID of the generated email post.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
* @param string $email_id The email ID to validate.
* @return bool|WP_Error True if the email ID is valid, otherwise a WP_Error object.
private function validate_email_id( string $email_id ) {
if ( ! in_array( $email_id, WCTransactionalEmails::get_transactional_emails(), true ) ) {
'woocommerce_rest_not_allowed_email_id',
sprintf( 'The provided email ID "%s" is not allowed.', $email_id ),
array( 'status' => 400 ),
* Permission check for REST API endpoint.
* @param WP_REST_Request $request The request for which the permission is checked.
* @return bool|WP_Error True if the current user has the capability, otherwise a WP_Error object.
private function check_permissions( WP_REST_Request $request ) {
$nonce = $request->get_param( 'nonce' );
if ( ! wp_verify_nonce( $nonce, self::NONCE_KEY ) ) {
__( 'Invalid nonce.', 'woocommerce' ),
array( 'status' => 403 ),
return $this->check_permission( $request, 'manage_woocommerce' );
* Handle the POST /settings/email/listing/recreate-email-post.
* @param WP_REST_Request $request The received request.
* @return array|WP_Error Request response or an error.
public function recreate_email_post( WP_REST_Request $request ) {
$email_id = $request->get_param( 'email_id' );
$generated_post_id = $this->email_template_generator->generate_email_template_if_not_exists( $email_id );
} catch ( \Exception $e ) {
'woocommerce_rest_email_post_generation_failed',
// translators: %s: Error message.
sprintf( __( 'Error generating email post. Error: %s.', 'woocommerce' ), $e->getMessage() ),
if ( $generated_post_id ) {
// translators: %s: WooCommerce transactional email ID.
'message' => sprintf( __( 'Email post generated for %s.', 'woocommerce' ), $email_id ),
'post_id' => (string) $generated_post_id,
'woocommerce_rest_email_post_generation_error',
__( 'Error unable to generate email post.', 'woocommerce' ),