1 <?php
  2 /**
  3  * Transactional Emails Controller
  4  *
  5  * WooCommerce Emails Class which handles the sending on transactional emails and email templates. This class loads in available emails.
  6  *
  7  * @class       WC_Emails
  8  * @version     2.0.0
  9  * @package     WooCommerce/Classes/Emails
 10  * @category    Class
 11  * @author      WooThemes
 12  */
 13 class WC_Emails {
 14 
 15     /**
 16      * @var array Array of email notification classes.
 17      * @access public
 18      */
 19     public $emails;
 20 
 21     /**
 22      * @var string Stores the emailer's address.
 23      * @access private
 24      */
 25     private $_from_address;
 26 
 27     /**
 28      * @var string Stores the emailer's name.
 29      * @access private
 30      */
 31     private $_from_name;
 32 
 33     /**
 34      * @var mixed Content type for sent emails
 35      * @access private
 36      */
 37     private $_content_type;
 38 
 39     /**
 40      * @var WooCommerce The single instance of the class
 41      * @since 2.1
 42      */
 43     protected static $_instance = null;
 44 
 45     /**
 46      * Main WooCommerce Instance
 47      *
 48      * Ensures only one instance of WooCommerce is loaded or can be loaded.
 49      *
 50      * @since 2.1
 51      * @static
 52      * @see WC()
 53      * @return Main WooCommerce instance
 54      */
 55     public static function instance() {
 56         if ( is_null( self::$_instance ) )
 57             self::$_instance = new self();
 58         return self::$_instance;
 59     }
 60 
 61     /**
 62      * Cloning is forbidden.
 63      *
 64      * @since 2.1
 65      */
 66     public function __clone() {
 67         _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'woocommerce' ), '2.1' );
 68     }
 69 
 70     /**
 71      * Unserializing instances of this class is forbidden.
 72      *
 73      * @since 2.1
 74      */
 75     public function __wakeup() {
 76         _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'woocommerce' ), '2.1' );
 77     }
 78 
 79     /**
 80      * Constructor for the email class hooks in all emails that can be sent.
 81      *
 82      * @access public
 83      * @return void
 84      */
 85     function __construct() {
 86 
 87         $this->init();
 88 
 89         // Email Header, Footer and content hooks
 90         add_action( 'woocommerce_email_header', array( $this, 'email_header' ) );
 91         add_action( 'woocommerce_email_footer', array( $this, 'email_footer' ) );
 92         add_action( 'woocommerce_email_order_meta', array( $this, 'order_meta' ), 10, 3 );
 93 
 94         // Hooks for sending emails during store events
 95         add_action( 'woocommerce_low_stock_notification', array( $this, 'low_stock' ) );
 96         add_action( 'woocommerce_no_stock_notification', array( $this, 'no_stock' ) );
 97         add_action( 'woocommerce_product_on_backorder_notification', array( $this, 'backorder' ) );
 98         add_action( 'woocommerce_created_customer_notification', array( $this, 'customer_new_account' ), 10, 3 );
 99 
100         // Let 3rd parties unhook the above via this hook
101         do_action( 'woocommerce_email', $this );
102     }
103 
104     /**
105      * Init email classes
106      */
107     function init() {
108         // Include email classes
109         include_once( 'abstracts/abstract-wc-email.php' );
110 
111         $this->emails['WC_Email_New_Order']                 = include( 'emails/class-wc-email-new-order.php' );
112         $this->emails['WC_Email_Customer_Processing_Order'] = include( 'emails/class-wc-email-customer-processing-order.php' );
113         $this->emails['WC_Email_Customer_Completed_Order']  = include( 'emails/class-wc-email-customer-completed-order.php' );
114         $this->emails['WC_Email_Customer_Invoice']          = include( 'emails/class-wc-email-customer-invoice.php' );
115         $this->emails['WC_Email_Customer_Note']             = include( 'emails/class-wc-email-customer-note.php' );
116         $this->emails['WC_Email_Customer_Reset_Password']   = include( 'emails/class-wc-email-customer-reset-password.php' );
117         $this->emails['WC_Email_Customer_New_Account']      = include( 'emails/class-wc-email-customer-new-account.php' );
118 
119         $this->emails = apply_filters( 'woocommerce_email_classes', $this->emails );
120     }
121 
122     /**
123      * Return the email classes - used in admin to load settings.
124      *
125      * @access public
126      * @return array
127      */
128     function get_emails() {
129         return $this->emails;
130     }
131 
132     /**
133      * Get from name for email.
134      *
135      * @access public
136      * @return string
137      */
138     function get_from_name() {
139         if ( ! $this->_from_name )
140             $this->_from_name = get_option( 'woocommerce_email_from_name' );
141 
142         return wp_specialchars_decode( $this->_from_name );
143     }
144 
145     /**
146      * Get from email address.
147      *
148      * @access public
149      * @return string
150      */
151     function get_from_address() {
152         if ( ! $this->_from_address )
153             $this->_from_address = get_option( 'woocommerce_email_from_address' );
154 
155         return $this->_from_address;
156     }
157 
158     /**
159      * Get the content type for the email.
160      *
161      * @access public
162      * @return string
163      */
164     function get_content_type() {
165         return $this->_content_type;
166     }
167 
168     /**
169      * Get the email header.
170      *
171      * @access public
172      * @param mixed $email_heading heading for the email
173      * @return void
174      */
175     function email_header( $email_heading ) {
176         wc_get_template( 'emails/email-header.php', array( 'email_heading' => $email_heading ) );
177     }
178 
179     /**
180      * Get the email footer.
181      *
182      * @access public
183      * @return void
184      */
185     function email_footer() {
186         wc_get_template( 'emails/email-footer.php' );
187     }
188 
189     /**
190      * Wraps a message in the woocommerce mail template.
191      *
192      * @access public
193      * @param mixed $email_heading
194      * @param mixed $message
195      * @return string
196      */
197     function wrap_message( $email_heading, $message, $plain_text = false ) {
198         // Buffer
199         ob_start();
200 
201         do_action( 'woocommerce_email_header', $email_heading );
202 
203         echo wpautop( wptexturize( $message ) );
204 
205         do_action( 'woocommerce_email_footer' );
206 
207         // Get contents
208         $message = ob_get_clean();
209 
210         return $message;
211     }
212 
213     /**
214      * Send the email.
215      *
216      * @access public
217      * @param mixed $to
218      * @param mixed $subject
219      * @param mixed $message
220      * @param string $headers (default: "Content-Type: text/html\r\n")
221      * @param string $attachments (default: "")
222      * @param string $content_type (default: "text/html")
223      * @return void
224      */
225     function send( $to, $subject, $message, $headers = "Content-Type: text/html\r\n", $attachments = "", $content_type = 'text/html' ) {
226 
227         // Set content type
228         $this->_content_type = $content_type;
229 
230         // Filters for the email
231         add_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
232         add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
233         add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );
234 
235         // Send
236         wp_mail( $to, $subject, $message, $headers, $attachments );
237 
238         // Unhook filters
239         remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
240         remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
241         remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );
242     }
243 
244     /**
245      * Prepare and send the customer invoice email on demand.
246      *
247      * @access public
248      * @param mixed $pay_for_order
249      * @return void
250      */
251     function customer_invoice( $order ) {
252         $email = $this->emails['WC_Email_Customer_Invoice'];
253         $email->trigger( $order );
254     }
255 
256     /**
257      * Customer new account welcome email.
258      *
259      * @access public
260      * @param int $customer_id
261      * @param array $new_customer_data
262      * @return void
263      */
264     function customer_new_account( $customer_id, $new_customer_data = array(), $password_generated = false ) {
265         if ( ! $customer_id )
266             return;
267 
268         $user_pass = ! empty( $new_customer_data['user_pass'] ) ? $new_customer_data['user_pass'] : '';
269 
270         $email = $this->emails['WC_Email_Customer_New_Account'];
271         $email->trigger( $customer_id, $user_pass, $password_generated );
272     }
273 
274     /**
275      * Add order meta to email templates.
276      *
277      * @access public
278      * @param mixed $order
279      * @param bool $sent_to_admin (default: false)
280      * @param bool $plain_text (default: false)
281      * @return void
282      */
283     function order_meta( $order, $sent_to_admin = false, $plain_text = false ) {
284 
285         $meta = array();
286         $show_fields = apply_filters( 'woocommerce_email_order_meta_keys', array(), $sent_to_admin );
287 
288         if ( $order->customer_note )
289             $meta[ __( 'Note', 'woocommerce' ) ] = wptexturize( $order->customer_note );
290 
291         if ( $show_fields )
292             foreach ( $show_fields as $key => $field ) {
293                 if ( is_numeric( $key ) )
294                     $key = $field;
295 
296                 $meta[ wptexturize( $key ) ] = wptexturize( get_post_meta( $order->id, $field, true ) );
297             }
298 
299         if ( sizeof( $meta ) > 0 ) {
300 
301             if ( $plain_text ) {
302 
303                 foreach ( $meta as $key => $value ) {
304                     if ( $value ) {
305                         echo $key . ': ' . $value . "\n";
306                     }
307                 }
308 
309             } else {
310 
311                 foreach ( $meta as $key => $value ) {
312                     if ( $value ) {
313                         echo '<p><strong>' . $key . ':</strong> ' . $value . '</p>';
314                     }
315                 }
316             }
317         }
318     }
319 
320     /**
321      * Low stock notification email.
322      *
323      * @access public
324      * @param mixed $product
325      * @return void
326      */
327     function low_stock( $product ) {
328 
329         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
330 
331         $subject = apply_filters( 'woocommerce_email_subject_low_stock', sprintf( '[%s] %s', $blogname, __( 'Product low in stock', 'woocommerce' ) ), $product );
332 
333         $sku = ($product->sku) ? '(' . $product->sku . ') ' : '';
334 
335         if ( ! empty( $product->variation_id ) )
336             $title = sprintf(__( 'Variation #%s of %s', 'woocommerce' ), $product->variation_id, get_the_title($product->id)) . ' ' . $sku;
337         else
338             $title = sprintf(__( 'Product #%s - %s', 'woocommerce' ), $product->id, get_the_title($product->id)) . ' ' . $sku;
339 
340         $message = $title . __( 'is low in stock.', 'woocommerce' );
341 
342         //  CC, BCC, additional headers
343         $headers = apply_filters('woocommerce_email_headers', '', 'low_stock', $product);
344 
345         // Attachments
346         $attachments = apply_filters('woocommerce_email_attachments', array(), 'low_stock', $product);
347 
348         // Send the mail
349         wp_mail( get_option('woocommerce_stock_email_recipient'), $subject, $message, $headers, $attachments );
350     }
351 
352     /**
353      * No stock notification email.
354      *
355      * @access public
356      * @param mixed $product
357      * @return void
358      */
359     function no_stock( $product ) {
360 
361         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
362 
363         $subject = apply_filters( 'woocommerce_email_subject_no_stock', sprintf( '[%s] %s', $blogname, __( 'Product out of stock', 'woocommerce' ) ), $product );
364 
365         $sku = ($product->sku) ? '(' . $product->sku . ') ' : '';
366 
367         if ( ! empty( $product->variation_id ) )
368             $title = sprintf(__( 'Variation #%s of %s', 'woocommerce' ), $product->variation_id, get_the_title($product->id)) . ' ' . $sku;
369         else
370             $title = sprintf(__( 'Product #%s - %s', 'woocommerce' ), $product->id, get_the_title($product->id)) . ' ' . $sku;
371 
372         $message = $title . __( 'is out of stock.', 'woocommerce' );
373 
374         //  CC, BCC, additional headers
375         $headers = apply_filters('woocommerce_email_headers', '', 'no_stock', $product);
376 
377         // Attachments
378         $attachments = apply_filters('woocommerce_email_attachments', array(), 'no_stock', $product);
379 
380         // Send the mail
381         wp_mail( get_option('woocommerce_stock_email_recipient'), $subject, $message, $headers, $attachments );
382     }
383 
384     /**
385      * Backorder notification email.
386      *
387      * @access public
388      * @param mixed $args
389      * @return void
390      */
391     function backorder( $args ) {
392 
393         $defaults = array(
394             'product' => '',
395             'quantity' => '',
396             'order_id' => ''
397         );
398 
399         $args = wp_parse_args( $args, $defaults );
400 
401         extract( $args );
402 
403         if (!$product || !$quantity) return;
404 
405         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
406 
407         $subject = apply_filters( 'woocommerce_email_subject_backorder', sprintf( '[%s] %s', $blogname, __( 'Product Backorder', 'woocommerce' ) ), $product );
408 
409         $sku = ($product->sku) ? ' (' . $product->sku . ')' : '';
410 
411         if ( ! empty( $product->variation_id ) )
412             $title = sprintf(__( 'Variation #%s of %s', 'woocommerce' ), $product->variation_id, get_the_title($product->id)) . $sku;
413         else
414             $title = sprintf(__( 'Product #%s - %s', 'woocommerce' ), $product->id, get_the_title($product->id)) . $sku;
415 
416         $order = new WC_Order( $order_id );
417         $message = sprintf(__( '%s units of %s have been backordered in order %s.', 'woocommerce' ), $quantity, $title, $order->get_order_number() );
418 
419         //  CC, BCC, additional headers
420         $headers = apply_filters('woocommerce_email_headers', '', 'backorder', $args);
421 
422         // Attachments
423         $attachments = apply_filters('woocommerce_email_attachments', array(), 'backorder', $args);
424 
425         // Send the mail
426         wp_mail( get_option('woocommerce_stock_email_recipient'), $subject, $message, $headers, $attachments );
427     }
428 
429 }
430 
WooCommerce API documentation generated by ApiGen 2.8.0