gocodebox/lifterlms

View on GitHub
includes/emails/class.llms.email.php

Summary

Maintainability
B
4 hrs
Test Coverage
B
80%
<?php
/**
 * Email Base
 *
 * @package LifterLMS/Emails/Classes
 *
 * @since 1.0.0
 * @version 5.0.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Email Base Class
 *
 * @since 1.0.0
 * @since 3.30.3 Explicitly define class properties.
 * @since 4.0.0 Always supply a from address even if the option is empty.
 */
class LLMS_Email {

    /**
     * @var array
     * @since 3.15.0
     */
    private $attachments = array();

    /**
     * @var string
     * @since 3.8.0
     */
    protected $body = '';

    /**
     * @var string
     * @since 3.8.0
     */
    protected $content_type = 'text/html';

    /**
     * @var WP_Post
     * @since 3.26.1
     */
    public $email_post;

    /**
     * @var array
     * @since 1.0.0
     */
    private $find = array();

    /**
     * @var array
     * @since 3.8.0
     */
    private $headers = array();

    /**
     * @var string
     * @since 1.0.0
     */
    protected $heading = '';

    /**
     * @var string
     * @since 1.0.0
     */
    protected $id = 'generic';

    /**
     * @var array
     * @since 1.0.0
     */
    private $recipient = array();

    /**
     * @var array
     * @since 1.0.0
     */
    private $replace = array();

    /**
     * @var string
     * @since 1.0.0
     */
    protected $subject = '';

    /**
     * @var string
     * @since 3.8.0
     */
    protected $template_html = 'emails/template.php';

    /**
     * Initializer
     * Children can configure the email in this function called by the __construct() function
     *
     * @param    array $args  optional arguments passed in from the constructor
     * @return   void
     * @since    3.8.0
     * @version  3.8.0
     */
    protected function init( $args ) {}

    /**
     * Constructor
     * Sets up data needed to generate email content
     *
     * @since    1.0.0
     * @version  3.8.0
     */
    public function __construct( $args = array() ) {

        $this->add_header( 'Content-Type', $this->get_content_type() );

        $this->add_merge_data(
            array(
                '{blogname}'     => get_bloginfo( 'name', 'display' ),
                '{site_title}'   => get_bloginfo( 'name', 'display' ),
                '{divider}'      => llms()->mailer()->get_divider_html(),
                '{button_style}' => llms()->mailer()->get_button_style(),
            )
        );

        $this->init( $args );

    }

    /**
     * Add an attachment to the email
     *
     * @param    string $attachment  full system path to a file to attach
     * @return   void
     * @since    3.15.0
     * @version  3.15.0
     */
    public function add_attachment( $attachment ) {

        array_push( $this->attachments, $attachment );

    }

    /**
     * Add a single header to the email headers array
     *
     * @param    string $key   header key eg: 'Cc'
     * @param    string $val   header value eg: 'noreply@website.tld'
     * @since    3.8.0
     * @version  3.8.0
     */
    public function add_header( $key, $val ) {

        array_push( $this->headers, sprintf( '%1$s: %2$s', $key, $val ) );

    }

    /**
     * Add merge data that will be used in the email
     *
     * @param    array $data    associative array where
     *                             $key = merge field
     *                             $val = merge value
     * @since    3.8.0
     * @version  3.8.0
     */
    public function add_merge_data( $data = array() ) {

        foreach ( $data as $find => $replace ) {

            array_push( $this->find, $find );
            array_push( $this->replace, $replace );

        }

    }

    /**
     * Add a single recipient for sending to, cc, or bcc
     *
     * @param    int|string $address  if string, must be a valid email address
     *                                if int, must be the WP User ID of a user
     * @param    string     $type     recipient type [to,cc,bcc]
     * @param    string     $name     recipient name (optional)
     * @return   boolean
     * @since    3.8.0
     * @version  3.10.1
     */
    public function add_recipient( $address, $type = 'to', $name = '' ) {

        // If an ID was supplied, get the information from the student object.
        if ( is_numeric( $address ) ) {
            $student = llms_get_student( $address );
            if ( ! $student ) {
                return false;
            }
            $address = $student->get( 'user_email' );
            $name    = $student->get_name();
        }

        // Ensure address is a valid email.
        if ( ! filter_var( $address, FILTER_VALIDATE_EMAIL ) ) {
            return false;
        }

        // If a name is supplied format the name & address.
        if ( $name ) {
            $address = sprintf( '%1$s <%2$s>', $name, $address );
        }

        if ( 'to' === $type ) {

            array_push( $this->recipient, $address );
            return true;

        } elseif ( 'cc' === $type || 'bcc' === $type ) {

            $this->add_header( ucfirst( $type ), $address );
            return true;

        }

        return false;

    }

    /**
     * Add multiple recipients
     *
     * @param    array $recipients  array of recipient information
     * @return   void
     * @since    3.8.0
     * @version  3.8.0
     */
    public function add_recipients( $recipients = array() ) {

        foreach ( $recipients as $data ) {

            $data = wp_parse_args(
                $data,
                array(
                    'address' => '',
                    'type'    => 'to',
                    'name'    => '',
                )
            );

            if ( $data['address'] ) {
                $this->add_recipient( $data['address'], $data['type'], $data['name'] );
            }
        }

    }

    /**
     *  Format string method
     *
     *  Finds and replaces merge fields with appropriate data.
     *
     * @since 1.0.0
     * @since 5.0.0 Process shortocdes when formatting a string.
     *
     * @param string $string String to be formatted.
     * @return string
     */
    public function format_string( $string ) {
        return do_shortcode( str_replace( $this->find, $this->replace, $string ) );
    }

    /**
     * Get attachments
     *
     * @return   array
     * @since    3.15.0
     * @version  3.15.0
     */
    public function get_attachments() {
        return apply_filters( 'llms_email_get_attachments', $this->attachments, $this );
    }

    /**
     * Get the body content of the email
     *
     * @return   string
     * @since    3.8.0
     * @version  3.8.0
     */
    public function get_body() {
        return apply_filters( 'llms_email_body', $this->format_string( $this->body ), $this );
    }

    /**
     * Get email content
     *
     * @return string
     * @since    1.0.0
     * @version  3.8.0
     */
    public function get_content() {

        $content = apply_filters( 'llms_email_content_get_content', $this->get_content_html(), $this );
        return wordwrap( $content, 70 );

    }

    /**
     * Get the HTML email content
     *
     * @return   string
     * @since    3.8.0
     * @version  3.26.1
     */
    public function get_content_html() {

        global $post;
        $temp = null;

        // Override the $post global with the email post content (if it exists).
        // This fixes Elementor / WC conflict outlined at https://github.com/gocodebox/lifterlms/issues/730.
        if ( isset( $this->email_post ) ) {
            $temp = $post;
            $post = $this->email_post;
        }

        ob_start();
        llms_get_template(
            $this->template_html,
            array(
                'email_heading' => $this->get_heading(),
                'email_message' => $this->get_body(),
            )
        );

        $html = apply_filters( 'llms_email_content_get_content_html', ob_get_clean(), $this );

        // Restore the default $post global.
        if ( $temp ) {
            $post = $temp;
        }

        return $html;

    }

    /**
     * Get the content type
     *
     * @return string
     * @since    1.0.0
     * @version  3.8.0
     */
    public function get_content_type() {
        return apply_filters( 'llms_email_content_type', $this->content_type, $this );
    }

    /**
     * Get from email option data
     *
     * @since 1.0.0
     * @since 4.0.0 Use the address provided by `wp_mail_from` as the default if no option is stored.
     *
     * @return string
     */
    public function get_from_address( $from_address ) {
        return sanitize_email( get_option( 'lifterlms_email_from_address', $from_address ) );
    }

    /**
     * Get from name option data
     *
     * @return   string
     * @since    1.0.0
     * @version  1.0.0
     */
    public function get_from_name() {
        return wp_specialchars_decode( esc_html( get_option( 'lifterlms_email_from_name' ) ), ENT_QUOTES );
    }

    /**
     * Get email headers
     *
     * @return   string|array
     * @since    1.0.0
     * @version  3.8.0
     */
    public function get_headers() {
        return apply_filters( 'lifterlms_email_headers', $this->headers, $this->id );
    }

    /**
     * Get the text of the email "heading"
     *
     * @return string
     * @since    1.0.0
     * @version  3.8.0
     */
    public function get_heading() {
        return apply_filters( 'lifterlms_email_heading', $this->format_string( $this->heading ), $this );
    }

    /**
     * Get recipient email address
     *
     * @return   string|array
     * @since    1.0.0
     * @version  3.8.0
     */
    public function get_recipient() {
        return apply_filters( 'lifterlms_email_recipient', $this->recipient, $this );
    }

    /**
     * Get email subject
     *
     * @return   string
     * @since    1.0.0
     * @version  3.8.0
     */
    public function get_subject() {
        return apply_filters( 'lifterlms_email_subject', $this->format_string( $this->subject ), $this );
    }

    /**
     * Set the body for the email
     *
     * @param    string $body   text or html body content for the email
     * @return   $this
     * @since    3.8.0
     * @version  3.8.0
     */
    public function set_body( $body = '' ) {
        $this->body = $body;
        return $this;
    }

    /**
     * set the content_type for the email
     *
     * @param    string $content_type   content type (for the header)
     * @return   $this
     * @since    3.8.0
     * @version  3.8.0
     */
    public function set_content_type( $content_type = 'text/html' ) {
        $this->content_type = $content_type;
        return $this;
    }

    /**
     * set the heading for the email
     *
     * @param    string $heading    text string to use for the email heading
     * @return   $this
     * @since    3.8.0
     * @version  3.8.0
     */
    public function set_heading( $heading = '' ) {
        $this->heading = $heading;
        return $this;
    }

    /**
     * Set the ID of the email
     *
     * @param    string $id   id string
     * @return   $this
     * @since    3.8.0
     * @version  3.8.0
     */
    public function set_id( $id = '' ) {
        $this->id = $id;
        return $this;
    }

    /**
     * set the subject for the email
     *
     * @param    string $subject Text string to use for the email subject.
     * @return   $this
     * @since    3.8.0
     * @version  3.24.0
     */
    public function set_subject( $subject = '' ) {
        $this->subject = html_entity_decode( $subject, ENT_QUOTES );
        return $this;
    }

    /**
     * Send email
     *
     * @return bool
     * @since    1.0.0
     * @version  3.15.0
     */
    public function send() {

        do_action( 'lifterlms_email_' . $this->id . '_before_send', $this );

        add_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
        add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
        add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );

        $return = wp_mail( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );

        remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
        remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
        remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );

        do_action( 'lifterlms_email_' . $this->id . '_after_send', $this, $return );

        return $return;

    }

}