WooCommerce trigger custom email via AJAX

hi and thanks for stopping by.
i am currently writing a plugin for wordpress. i need a button inside a certain page, that triggers an email-notification. i figured it would be good to use the woocommerce email functionality, since it is a customer email and i’d like to use the woocommerce-email-templates, too.

in my plugin i include my class extension via

Read More
function add_wc_custom_email( $email_classes ) {
    require( 'includes/class-wc-custom-email.php' );
    $email_classes['WC_Custom_Email'] = new WC_Custom_Email();

    return $email_classes;
}
add_filter( 'woocommerce_email_classes', 'add_wc_custom_email' );
//if i write a print_r(something) inside this function, just to alert if this filters hits, i don't see a result, so i think the error is here.. the filter gets hit under woocommerce->settings->emails but not, if you simply load a page in the backend 

in the file class-wc-custom-email.php i have my class extension

class WC_Custom_Email extends WC_Email {
    public function __construct() {
        …
    }
    public function mail( $var1, $var2, $var3 ) {
        …
    }
}

my ajax looks like this

( function( $ ) {
    $('#button1').on( "click", function() {
        $.post(
            ajaxurl,
            {
                'action' : 'jnz_email_custom',
                'page_id': '<?php the_ID(); ?>',
            },
            function ( response ) {
                console.log( "triggered", response )
            }
        );
    });
})(jQuery);

the ajax handler looks like this

add_action('wp_ajax_jnz_email_custom', 'jnz_email_custom');
function jnz_email_custom() {
    $message = email_custom( $_POST['page_id'] );
    $response = array(
        'what'   => 'email_custom_triggered',
        'action' => 'email custom triggered',
        'id'     => $_POST['page_id'],
        'data'   => $message,
    );
    $xmlResponse = new WP_Ajax_Response( $response );
    $xmlResponse->send();
}

the function that i trigger with ajax

function email_custom( $page_id = 2728 ) {
    $field = get_field( 'something', $page_id )[0];
    //get_field() is a function by plugin 'Advanced Custom Fields' and works fine

    function somethingSomething( $field ) {
        …
        return $results;
    }

    foreach ( $results as $result ) :
        $email = new WC_Custom_Email();
        $email->mail( $result['details']['name'], $result['details']['email'], $result['something'] );
    endforeach;

    return json_encode( $results, JSON_UNESCAPED_UNICODE );
    //this is the $xmlResponse i get from the ajax call and looks fine (but only works, if i uncomment the 'new WC_Custom_Email()' stuff. otherwise i see the "Fatal Error" thingy)
}

the response is: Fatal error: Class 'WC_Custom_Email' not found in …

all the functions work fine, if i return the $results i see all i want and get no errors.

same is, when i change it to new WC_Email(). so my guess is, that the woocommerce functionality isn’t loaded into my admin->edit_page_xy screen. so the big question is: how would i load the woocommerce functionality (or only the email-functionality) into my plugin..??

hope this is somewhat clear and makes any sense. i only know little php and am completely new to oop.

Related posts

2 comments

  1. Ok, so this was a bit of a beast.

    I’ve written a demo plugin with the following structure:

    kia-ajax-email.php
    - includes
      -- class-wc-test-ajax-email.php
    -- js
       -- script.js
    -- templates
       -- emails
          -- test.php
          -- plain
             -- test.php
    

    ##The main plugin file kia-ajax-email.php

    This file is responsible for enqueuing the script, adding your custom email class, creating a button on the single product page, and registering an action as one that triggers a WooCommerce email:

    <?php
    /**
     * Plugin Name: Test Ajax Email
     * Plugin URI: http://stackoverflow.com/q/35018177/383847
     * Description: Demo plugin for sending email via ajax
     * Author: helgatheviking
     * Author URI: http://www.kathyisawesome.com
     * Version: 0.1
     *
     * License: GNU General Public License v3.0
     * License URI: http://www.gnu.org/licenses/gpl-3.0.html
     *
     */
    
    if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
    
    
    /**
     *  get plugin path
     *
     * @since 0.1
     */
    function kia_ajax_email_plugin_path(){
        return untrailingslashit( plugin_dir_path( __FILE__ ) ); 
    }
    
    /**
     *  Add a custom email to the list of emails WooCommerce should load
     *
     * @since 0.1
     * @param array $email_classes available email classes
     * @return array filtered available email classes
     */
    function kia_add_custom_email( $email_classes ) {
    
        // include our custom email class
        require_once( 'includes/class-wc-test-ajax-email.php' );
    
        // add the email class to the list of email classes that WooCommerce loads
        $email_classes['WC_Test_Ajax_Email'] = new WC_Test_Ajax_Email();
    
        return $email_classes;
    
    }
    add_filter( 'woocommerce_email_classes', 'kia_add_custom_email' );
    
    
    /**
     *  Enqueue the scripts with apprpriate vars
     *
     * @since 0.1
     */
    function kia_ajax_email_js(){
        wp_enqueue_script( 'kia_ajax_email', plugins_url( 'js/script.js', __FILE__ ), array('jquery'), '1.0.0', true );
        wp_localize_script( 'kia_ajax_email', 'kia_ajax_email', array( 
                    'ajax_url'                  => WC()->ajax_url(),
                    'wc_ajax_url'               => WC_AJAX::get_endpoint( "test_email" ) ) );
    }
    add_action( 'wp_enqueue_scripts', 'kia_ajax_email_js', 20 );
    
    
    /**
     *  AJAX callback
     *
     * @since 0.1
     */
    function kia_ajax_email_callback() {
        $mailer = WC()->mailer();
    
        do_action( 'kia_trigger_ajax_email' );
    
        die('ajax finished'); // this is required to terminate immediately and return a proper response
    }
    add_action( 'wc_ajax_test_email', 'kia_ajax_email_callback' );
    
    
    /**
     *  Register action as one that sends emails
     *
     * @since 0.1
     */
    function kia_ajax_email_action( $actions ){
        $actions[] = 'kia_trigger_ajax_email';
        return $actions;
    }
    add_filter( 'woocommerce_email_actions', 'kia_ajax_email_action' );
    
    
    /**
     *  Add a dummy button to product page
     *
     * @since 0.1
     */
    function kia_ajax_email_button(){
        echo '<button class="email-trigger">' . __( 'Email Trigger', 'kia-ajax-email' ). '</button>';
    }
    add_action('woocommerce_before_single_product_summary', 'kia_ajax_email_button');
    

    ##The email class includes/class-wc-test-ajax-email.php

    <?php
    
    if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
    
    /**
     * A custom Expedited Order WooCommerce Email class
     *
     * @since 0.1
     * @extends WC_Email
     */
    class WC_Test_Ajax_Email extends WC_Email {
    
    
        /**
         * Set email defaults
         *
         * @since 0.1
         */
        public function __construct() {
    
            // set ID, this simply needs to be a unique name
            $this->id = 'wc_text_ajax_email';
    
            // this is the title in WooCommerce Email settings
            $this->title = 'Test Ajax';
    
            // this is the description in WooCommerce email settings
            $this->description = 'Text emails are sent when ajax button is clicked';
    
            // these are the default heading and subject lines that can be overridden using the settings
            $this->heading = 'Test Ajax';
            $this->subject = 'Test Ajax';
    
            // these define the locations of the templates that this email should use, we'll just use the new order template since this email is similar
            $this->template_html  = 'emails/test.php';
            $this->template_plain = 'emails/plain/test.php';
    
            // Trigger on new paid orders
            add_action( 'kia_trigger_ajax_email', array( $this, 'trigger' ) );
    
            // Call parent constructor to load any other defaults not explicity defined here
            parent::__construct();
    
            // this sets the recipient to the settings defined below in init_form_fields()
            $this->recipient = $this->get_option( 'recipient' );
    
            // if none was entered, just use the WP admin email as a fallback
            if ( ! $this->recipient )
                $this->recipient = get_option( 'admin_email' );
        }
    
    
        /**
         * Determine if the email should actually be sent and setup email merge variables
         *
         * @since 0.1
         * @param int $order_id
         */
        public function trigger() {
    
            if ( ! $this->is_enabled() || ! $this->get_recipient() )
                return;
    
            // woohoo, send the email!
            $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
        }
    
    
        /**
         * get_content_html function.
         *
         * @since 0.1
         * @return string
         */
        public function get_content_html() {
            return wc_get_template_html( $this->template_html, array(
                'email_heading' => $this->get_heading(),
                'sent_to_admin' => false,
                'plain_text'    => false,
                'email'         => $this
            ),
            '',
            kia_ajax_email_plugin_path() . "/templates/" );
        }
    
    
        /**
         * get_content_plain function.
         *
         * @since 0.1
         * @return string
         */
        public function get_content_plain() {
            return wc_get_template_html( $this->template_plain, array(
                'email_heading' => $this->get_heading(),
                'sent_to_admin' => false,
                'plain_text'    => false,
                'email'         => $this
            ),
            '',
            kia_ajax_email_plugin_path() . "/templates/" );
        }
    
    
        /**
         * Initialize Settings Form Fields
         *
         * @since 2.0
         */
        public function init_form_fields() {
    
            $this->form_fields = array(
                'enabled'    => array(
                    'title'   => 'Enable/Disable',
                    'type'    => 'checkbox',
                    'label'   => 'Enable this email notification',
                    'default' => 'yes'
                ),
                'recipient'  => array(
                    'title'       => 'Recipient(s)',
                    'type'        => 'text',
                    'description' => sprintf( 'Enter recipients (comma separated) for this email. Defaults to <code>%s</code>.', esc_attr( get_option( 'admin_email' ) ) ),
                    'placeholder' => '',
                    'default'     => ''
                ),
                'subject'    => array(
                    'title'       => 'Subject',
                    'type'        => 'text',
                    'description' => sprintf( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', $this->subject ),
                    'placeholder' => '',
                    'default'     => ''
                ),
                'heading'    => array(
                    'title'       => 'Email Heading',
                    'type'        => 'text',
                    'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.' ), $this->heading ),
                    'placeholder' => '',
                    'default'     => ''
                ),
                'email_type' => array(
                    'title'       => 'Email type',
                    'type'        => 'select',
                    'description' => 'Choose which format of email to send.',
                    'default'     => 'html',
                    'class'       => 'email_type',
                    'options'     => array(
                        'plain'     => __( 'Plain text', 'woocommerce' ),
                        'html'      => __( 'HTML', 'woocommerce' ),
                        'multipart' => __( 'Multipart', 'woocommerce' ),
                    )
                )
            );
        }
    
    
    } // end WC_Test_Ajax_Email class
    

    the script js/script.js

    jQuery(document).ready(function($) {
    
      $(".email-trigger").on("click", function(e) {
    
        e.preventDefault();
    
        $.ajax({
            url: kia_ajax_email.wc_ajax_url.toString(),
            type: 'POST',
            data: {
              'whatever': 1234
            },
          })
          .done(function(data) {
            if (console && console.log) {
              console.log(data);
            }
          });
      });
    
    });
    

    The email templates. first templates/emails/test.php and templates/emails/plain/test.php

    <?php
    /**
     * Test email
     *
     * This template can be overridden by copying it to yourtheme/woocommerce/emails/test.php.
     *
     * HOWEVER, on occasion WooCommerce will need to update template files and you (the theme developer).
     * will need to copy the new files to your theme to maintain compatibility. We try to do this.
     * as little as possible, but it does happen. When this occurs the version of the template file will.
     * be bumped and the readme will list any important changes.
     *
     * @see         http://docs.woothemes.com/document/template-structure/
     * @author      WooThemes
     * @package     WooCommerce/Templates/Emails
     * @version     2.5.0
     */
    
    if ( ! defined( 'ABSPATH' ) ) {
        exit;
    }
    
    /**
     * @hooked WC_Emails::email_header() Output the email header
     */
    do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
    
    <p><?php _e( 'A test email is being sent', 'kia-ajax-email' ); ?></p>
    
    
    <?php
    /**
     * @hooked WC_Emails::email_footer() Output the email footer
     */
    do_action( 'woocommerce_email_footer', $email );
    

    and templates/emails/plain/test.php

    <?php
    /**
     * Test email
     *
     * This template can be overridden by copying it to yourtheme/woocommerce/emails/plain/test.php.
     *
     * HOWEVER, on occasion WooCommerce will need to update template files and you (the theme developer).
     * will need to copy the new files to your theme to maintain compatibility. We try to do this.
     * as little as possible, but it does happen. When this occurs the version of the template file will.
     * be bumped and the readme will list any important changes.
     *
     * @see         http://docs.woothemes.com/document/template-structure/
     * @author      WooThemes
     * @package     WooCommerce/Templates/Emails
     * @version     2.5.0
     */
    
    if ( ! defined( 'ABSPATH' ) ) {
        exit;
    }
    
    
    echo "= " . $email_heading . " =nn";
    
    echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=nn";
    
    
    _e( 'A test email is being sent', 'kia-ajax-email' );
    
    echo "n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=nn";
    
    echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) );
    

    Going forward

    This sends an email when a button is clicked. You will need to modify where that button goes, and because it is kind of slow (or seems so on my local setup) I would definitely recommend some kind of spinner/notification that the action is happening. You’ll also need to customize what data is sent via ajax and how that ends up in the templates. This is just a proof of concept.

  2. <?php
    // custom-email.php
    
    /**
     * Plugin Name: Custom Email
     * Description: Demo plugin for sending email via ajax
     * Author: um
     * Author URI: 
     * Version: 0.1
     *
     * License: GNU General Public License v3.0
     * License URI: http://www.gnu.org/licenses/gpl-3.0.html
     *
     */
    
    if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
    
    
    /**
     *  get plugin path
     *
     * @since 0.1
     */
    function um_ajax_email_plugin_path(){
        return untrailingslashit( plugin_dir_path( __FILE__ ) ); 
    }
    
    /**
     *  Add a custom email to the list of emails WooCommerce should load
     *
     * @since 0.1
     * @param array $email_classes available email classes
     * @return array filtered available email classes
     */
    function um_add_custom_email( $email_classes ) {
    
        // include our custom email class
        require_once( 'includes/class-wc-test-ajax-email.php' );
    
        // add the email class to the list of email classes that WooCommerce loads
        $email_classes['WC_Test_Ajax_Email'] = new WC_Test_Ajax_Email();
    
        return $email_classes;
    }
    add_filter( 'woocommerce_email_classes', 'um_add_custom_email' );
    
    
    /**
     *  Enqueue the scripts with apprpriate vars
     *
     * @since 0.1
     */
    function um_ajax_email_js(){
        wp_enqueue_script( 'um_ajax_email', plugins_url( 'js/script.js', __FILE__ ), array('jquery'), '1.0.0', true );
        wp_localize_script( 'um_ajax_email', 'um_ajax_email', array( 
                    'ajax_url'                  => WC()->ajax_url(),
                    'wc_ajax_url'               => WC_AJAX::get_endpoint( "test_email" ) ) );
    }
    add_action( 'wp_enqueue_scripts', 'um_ajax_email_js', 20 );
    
    
    /**
     *  AJAX callback
     *
     * @since 0.1
     */
    function um_ajax_email_callback() {
        $mailer = WC()->mailer();
    
        do_action( 'um_trigger_ajax_email' );
    
        //echo '<pre>'; var_dump(do_action( 'um_trigger_ajax_email' )); echo '</pre>'; 
    
        die('ajax finished'); // this is required to terminate immediately and return a proper response
    }
    add_action( 'wc_ajax_test_email', 'um_ajax_email_callback' );
    
    
    /**
     *  Register action as one that sends emails
     *
     * @since 0.1
     */
    function um_ajax_email_action( $actions ){
        $actions[] = 'um_trigger_ajax_email';
        return $actions;
        
    }
    add_action( 'woocommerce_email_actions', 'um_ajax_email_action' );
    
    
    /**
     *  Add a dummy button to product page
     *
     * @since 0.1
     */
    function um_ajax_email_button(){
        echo '<button class="email-trigger">' . __( 'Email Trigger', 'kia-ajax-email' ). '</button>';
    }
    add_action('woocommerce_before_single_product_summary', 'um_ajax_email_button');
    

Comments are closed.