File: /home/ohirex/web/ohirex.com/public_html/wp-content/plugins/mailster/classes/placeholder.class.php
<?php
class MailsterPlaceholder {
private $content;
private $styles = array();
private $keeptag;
private $keeptags;
private $placeholder = array();
private $post_types = array();
private $rss = array();
private $rss_timestamp = null;
private $campaignID = null;
private $subscriberID = null;
private $index_offset = 0;
private $subscriberHash = null;
private $progress_conditions = false;
private $remove_modules = true;
private $replace_custom = true;
private $social_services;
private $apply_the_excerpt_filters = true;
private $last_post_args = null;
private $errors = array();
private static $global_rss_tag = null;
/**
*
*
* @param unknown $content (optional)
*/
public function __construct( $content = '', $deprecated = null ) {
$this->set_content( $content );
$this->post_types = mailster( 'helper' )->get_dynamic_post_types();
}
public function __destruct() { }
/**
*
*
* @param unknown $content (optional)
*/
public function set_content( $content = '' ) {
$this->content = $content;
}
/**
*
*
* @param unknown $id
*/
public function set_campaign( $id ) {
$this->campaignID = $id;
$autoresponder = mailster( 'campaigns' )->meta( $id, 'autoresponder' );
if ( $autoresponder && isset( $autoresponder['since'] ) ) {
$timeoffset = mailster( 'helper' )->gmt_offset( true );
$this->set_last_post_args(
array(
'date_query' => array( 'after' => date( 'Y-m-d H:i:s', $autoresponder['since'] + $timeoffset ) ),
)
);
}
}
/**
*
*
* @param unknown $id
*/
public function set_subscriber( $id ) {
$this->subscriberID = $id;
}
/**
*
*
* @param unknown $id
*/
public function set_index_offset( $offset ) {
$this->index_offset = $offset;
}
/**
*
*
* @param unknown $args
*/
public function set_last_post_args( $args ) {
$this->last_post_args = wp_parse_args( $args, $this->last_post_args );
}
public function remove_last_post_args() {
$this->last_post_args = null;
}
/**
*
*
* @param unknown $hash
*/
public function set_hash( $hash ) {
$this->subscriberHash = $hash;
}
/**
*
*
* @param unknown $bool (optional)
*/
public function replace_custom_tags( $bool = true ) {
$this->replace_custom = $bool;
}
/**
*
*
* @param unknown $removeunused (optional)
* @param unknown $placeholders (optional)
* @param unknown $relative_to_absolute (optional)
* @return unknown
*/
public function get_content( $removeunused = true, $placeholders = array(), $relative_to_absolute = false ) {
return $this->do_placeholder( $removeunused, $placeholders, $relative_to_absolute );
}
public function has_content( $check_for_modules = false ) {
$html = trim( $this->get_content( false ) );
if ( $check_for_modules ) {
return preg_match( '/<module[^>]*?data-tag="(.*?)"/', $html );
}
return ! empty( $html );
}
public function error( $error, $html_tag = true ) {
if ( ! is_wp_error( $error ) ) {
$error = new WP_Error( 'placeholder_error', (string) $error );
}
$this->errors[] = $error;
// output error only on the preview screen
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
$message = $error->get_error_message();
return $html_tag ? '<span style="background-color:#e74e2b;color:#fff;padding:2px;font-size:smaller;">' . esc_html( $message ) . '</span>' : esc_html( $message );
}
return '';
}
public function has_error() {
return ! empty( $this->errors );
}
public function get_error_messages() {
$errors = array();
foreach ( $this->errors as $error ) {
if ( is_wp_error( $error ) ) {
$errors[] = $error->get_error_message();
} else {
$errors[] = $error;
}
}
return $errors;
}
public function clear_placeholder() {
$this->placeholder = array();
}
/**
*
*
* @param unknown $do (optional)
*/
public function excerpt_filters( $do = true ) {
$this->apply_the_excerpt_filters = $do;
}
/**
*
*
* @param unknown $campaign_id (optional)
* @param unknown $args (optional)
* @return unknown
*/
public function add_defaults( $campaign_id = null, $args = array() ) {
$time = explode( '|', date( 'Y|m|d|H|i|s', current_time( 'timestamp' ) ) );
$defaults = array(
'email' => '<a href="mailto:{emailaddress}">{emailaddress}</a>',
'year' => $time[0],
'month' => $time[1],
'day' => $time[2],
'hour' => $time[3],
'minute' => $time[4],
'second' => $time[5],
'unsub' => '<a href="{unsublink}">{unsublinktext}</a>',
'profile' => '<a href="{profilelink}">{profilelinktext}</a>',
'lang' => substr( get_bloginfo( 'language' ), 0, 2 ),
'dir' => is_rtl() ? 'rtl' : 'ltr',
);
if ( $campaign_id ) {
$meta = mailster( 'campaigns' )->meta( $campaign_id );
if ( ! $meta ) {
$meta = mailster( 'campaigns' )->meta_defaults();
}
$defaults = wp_parse_args(
array(
'preheader' => $meta['preheader'],
'subject' => $meta['subject'],
'webversion' => '<a href="{webversionlink}">{webversionlinktext}</a>',
'forward' => '<a href="{forwardlink}">{forwardlinktext}</a>',
'webversionlink' => get_permalink( $campaign_id ),
'lists' => mailster( 'campaigns' )->get_formated_lists( $campaign_id ),
),
$defaults
);
if ( ! $meta['webversion'] ) {
$defaults['webversion'] = '';
$defaults['webversionlink'] = '';
}
$this->share_service( get_permalink( $campaign_id ), get_the_title( $campaign_id ) );
}
$args = wp_parse_args( $args, $defaults );
$this->add( mailster_option( 'tags' ) );
$this->add( mailster_option( 'custom_tags' ) );
$this->add( apply_filters( 'mailster_placeholder_defaults', $args, $campaign_id ) );
}
/**
*
*
* @param unknown $campaign_id (optional)
* @param unknown $args (optional)
* @return unknown
*/
public function add_custom( $campaign_id = null, $args = array() ) {
$unsubscribelink = mailster()->get_unsubscribe_link( $campaign_id, $this->subscriberHash );
$forwardlink = mailster()->get_forward_link( $campaign_id );
$profilelink = mailster()->get_profile_link( $campaign_id, $this->subscriberHash );
$defaults = array(
'webversionlinktext' => mailster_text( 'webversion' ),
'unsublinktext' => mailster_text( 'unsubscribelink' ),
'forwardlinktext' => mailster_text( 'forward' ),
'profilelinktext' => mailster_text( 'profile' ),
'unsublink' => $unsubscribelink,
'forwardlink' => $forwardlink,
'profilelink' => $profilelink,
);
$args = wp_parse_args( $args, $defaults );
$this->add( apply_filters( 'mailster_placeholder_custom', $args, $campaign_id, $this->subscriberID ) );
}
/**
*
*
* @param unknown $placeholder (optional)
* @param unknown $brackets (optional)
* @return unknown
*/
public function add( $placeholder = array(), $brackets = true ) {
if ( empty( $placeholder ) ) {
return false;
}
foreach ( $placeholder as $key => $value ) {
( $brackets )
? $this->placeholder[ '{' . $key . '}' ] = $value
: $this->placeholder[ $key ] = $value;
}
}
/**
*
*
* @param unknown $bool (optional)
*/
public function do_conditions( $bool = true ) {
$this->progress_conditions = (bool) $bool;
}
/**
*
*
* @param unknown $bool (optional)
*/
public function do_remove_modules( $bool = true ) {
$this->remove_modules = (bool) $bool;
}
/**
*
*
* @param unknown $removeunused (optional)
* @param unknown $placeholders (optional)
* @param unknown $relative_to_absolute (optional)
* @return unknown
*/
public function do_placeholder( $removeunused = true, $placeholders = array(), $relative_to_absolute = false ) {
// nothing to replace for sure
if ( empty( $this->content ) || false === strpos( $this->content, '{' ) ) {
return $this->content;
}
$this->add( $placeholders );
$this->rss();
$this->conditions();
$this->remove_modules();
// as long there are tags in the content.
while ( false !== strpos( $this->content, '{' ) ) {
$initial_content = $this->content;
// temporary remove style blocks if exists
if ( strpos( $this->content, '<style' ) !== false && preg_match_all( '#(<style(>|[^<]+?>)([^<]+)<\/style>)#', $this->content, $styles ) ) {
foreach ( $styles[0] as $style ) {
$this->content = str_replace( $style, '<!--Mailster:styleblock' . count( $this->styles ) . '-->', $this->content );
$this->styles[] = $style;
}
}
$this->rss( false ); // once more without modules
$this->replace_images( $relative_to_absolute );
$this->replace_dynamic( $relative_to_absolute );
$this->replace_static( $removeunused );
// if content hasn't changed in this loop => break;
if ( $initial_content == $this->content ) {
break;
}
}
if ( ! empty( $this->keeptag ) ) {
foreach ( $this->keeptag as $i => $keeptag ) {
$this->content = str_replace( '<!--Mailster:keeptag' . $i . '-->', $keeptag, $this->content );
}
}
if ( ! empty( $this->styles ) ) {
foreach ( $this->styles as $i => $style ) {
$this->content = str_replace( '<!--Mailster:styleblock' . $i . '-->', $style, $this->content );
}
}
/**
* Filters the replaced content
*
* @param string $content
*/
return apply_filters( 'mailster_do_placeholder', $this->content );
}
/**
*
*
* @param unknown $url
* @param unknown $title (optional)
*/
private function share_service( $url, $title = '' ) {
$placeholders = array();
$social = array( 'twitter', 'facebook', 'google', 'linkedin' );
$social = implode( '|', apply_filters( 'mailster_share_services', $social ) );
if ( $count = preg_match_all( '#\{(share:(' . $social . ') ?([^}]+)?)\}#i', $this->content, $hits ) ) {
for ( $i = 0; $i < $count; $i++ ) {
$service = $hits[2][ $i ];
$url = ! empty( $hits[3][ $i ] ) ? $hits[3][ $i ] : $url;
$placeholders[ $hits[1][ $i ] ] = $this->get_social_service( $service, $url, $title );
}
}
$this->add( $placeholders );
}
/**
*
*
* @param unknown $service
* @param unknown $url
* @param unknown $title (optional)
* @param unknown $fallback (optional)
* @return unknown
*/
private function get_social_service( $service, $url, $title = '', $fallback = '' ) {
// bit caching
if ( ! $this->social_services ) {
$this->social_services = mailster( 'helper' )->social_services();
}
if ( ! isset( $this->social_services[ $service ] ) ) {
return $fallback;
}
$_url = str_replace(
array( '%title', '%url' ),
array(
rawurlencode( $title ),
rawurlencode( $url ),
),
$this->social_services[ $service ]['url']
);
$content = '<img alt="' . esc_attr( sprintf( esc_html__( 'Share this on %s', 'mailster' ), $this->social_services[ $service ]['name'] ) ) . '" src="' . MAILSTER_URI . 'assets/img/share/share_' . $service . '.png" style="display:inline;display:inline !important;" />';
$content = apply_filters( 'mailster_share_button_' . $service, $content );
return '<a href="' . $_url . '" class="social">' . $content . '</a>' . "\n";
}
/**
*
*
* @return unknown
*/
public function rss_since( $timestamp = null ) {
if ( is_null( $timestamp ) ) {
$timestamp = time();
}
$this->rss_timestamp = $timestamp;
}
/**
*
*
* @return unknown
*/
private function rss( $do_modules = true ) {
if ( $do_modules ) {
if ( preg_match_all( '#<module[^>]*?data-rss="(.*?)".*?</module>#ms', $this->content, $modules ) ) {
foreach ( $modules[0] as $i => $html ) {
$search = $modules[0][ $i ];
$feed_url = $modules[1][ $i ];
// $last_feed_timestamp = mailster( 'helper' )->new_feed_since( $this->rss_timestamp, $feed_url );
$feeds = mailster( 'helper' )->get_feed_since( $this->rss_timestamp, $feed_url );
if ( ! empty( $feeds ) ) {
$replace = '';
$id = md5( $feed_url );
$temp_post_type = 'mailster_rss_' . $id;
if ( ! isset( $this->rss[ $id ] ) ) {
$this->rss[ 'mailster_get_last_post_' . $temp_post_type ] = $feed_url;
add_filter( 'mailster_get_last_post_' . $temp_post_type, array( &$this, 'rss_replace' ), 5, 6 );
if ( $i === 0 ) {
self::$global_rss_tag = $temp_post_type;
}
}
$this->post_types[] = $temp_post_type;
$replace = str_replace( '{rss', '{' . $temp_post_type, $search );
$replace = str_replace( 'mailster_image_placeholder&tag=rss', 'mailster_image_placeholder&tag=' . $temp_post_type, $replace );
$replace = str_replace( 'mailster_image_placeholder&tag=rss', 'mailster_image_placeholder&tag=' . $temp_post_type, $replace );
} else {
$replace = '';
}
$this->content = str_replace( $search, $replace, $this->content );
}
}
} else {
// replace all tags outside the scope
if ( self::$global_rss_tag ) {
$this->content = str_replace( '{rss', '{' . self::$global_rss_tag, $this->content );
$this->content = str_replace( 'mailster_image_placeholder&tag=rss', 'mailster_image_placeholder&tag=' . self::$global_rss_tag, $this->content );
$this->content = str_replace( 'mailster_image_placeholder&tag=rss', 'mailster_image_placeholder&tag=' . self::$global_rss_tag, $this->content );
}
}
}
/**
*
*
* @return unknown
*/
public function rss_replace( $return, $args, $offset, $term_ids, $campaign_id, $subscriber_id ) {
$current = current_filter();
if ( ! isset( $this->rss[ $current ] ) ) {
return $return;
}
$feed_url = $this->rss[ $current ];
return mailster( 'helper' )->feed( $feed_url, $offset );
}
/**
*
*
* @return unknown
*/
private function remove_modules() {
if ( ! $this->remove_modules ) {
return;
}
if ( preg_match_all( '#<module[^>]*?data-tag="{(([a-z0-9_-]+):(-|~)?([\d]+)(;([0-9;,-]+))?)\}"(.*?)".*?</module>#ms', $this->content, $modules ) ) {
foreach ( $modules[0] as $i => $html ) {
$search = $modules[0][ $i ];
$tag = $modules[1][ $i ];
$post_type = $modules[2][ $i ];
$post_or_offset = $modules[4][ $i ];
$type = $modules[3][ $i ];
if ( empty( $type ) ) {
$post = get_post( $post_or_offset );
} else {
$term_ids = ! empty( $modules[6][ $i ] ) ? explode( ';', trim( $modules[6][ $i ] ) ) : array();
if ( '~' == $type ) {
$post = mailster()->get_random_post( $post_or_offset, $post_type, $term_ids, $this->last_post_args, $this->campaignID, $this->subscriberID );
} else {
$post = mailster()->get_last_post( $post_or_offset - 1 + $this->index_offset, $post_type, $term_ids, $this->last_post_args, $this->campaignID, $this->subscriberID );
}
}
if ( ! $post || is_wp_error( $post ) ) {
$this->content = str_replace( $search, '', $this->content );
}
}
}
}
/**
*
*
* @return unknown
*/
public function conditions() {
if ( ! $this->progress_conditions ) {
return;
}
if ( preg_match_all( '#<(module|single|multi)[^>]*?condition="([a-z0-9-_]+)([=!GLTE\^$]+)(.*?)".*?</(\\1)>#ms', $this->content, $conditions ) ) {
$subscriber = $this->subscriberID ? mailster( 'subscribers' )->get( $this->subscriberID, true, true ) : false;
foreach ( $conditions[0] as $i => $html ) {
$key = $conditions[2][ $i ];
$operator = $conditions[3][ $i ];
$value = $conditions[4][ $i ];
if ( $operator == '=' && isset( $subscriber->{$key} ) && $subscriber->{$key} == $value ) {
continue;
}
if ( $operator == '!=' && ( ! isset( $subscriber->{$key} ) || $subscriber->{$key} != $value ) ) {
continue;
}
if ( $operator == '^' && isset( $subscriber->{$key} ) && false !== ( strrpos( $subscriber->{$key}, $value, -strlen( $subscriber->{$key} ) ) ) ) {
continue;
}
if ( $operator == '$' && isset( $subscriber->{$key} ) && false !== ( ( $t = strlen( $subscriber->{$key} ) - strlen( $value ) ) >= 0 && strpos( $subscriber->{$key}, $value, $t ) ) ) {
continue;
}
if ( $operator == 'GT' && isset( $subscriber->{$key} ) && $subscriber->{$key} > $value ) {
continue;
}
if ( $operator == 'GTE' && isset( $subscriber->{$key} ) && $subscriber->{$key} >= $value ) {
continue;
}
if ( $operator == 'LT' && isset( $subscriber->{$key} ) && $subscriber->{$key} < $value ) {
continue;
}
if ( $operator == 'LTE' && isset( $subscriber->{$key} ) && $subscriber->{$key} <= $value ) {
continue;
}
$this->content = str_replace( $html, '', $this->content );
}
}
if ( preg_match_all( '#<if field="([a-z0-9-_]+)" operator="([a-z_]+)+" value="(.*?)">(.*?)</if>#s', $this->content, $if_conditions ) ) {
$subscriber = $this->subscriberID ? mailster( 'subscribers' )->get( $this->subscriberID, true, true ) : false;
foreach ( $if_conditions[0] as $i => $ifhtml ) {
// if condition passed
if ( $this->check_condition( $subscriber, $if_conditions[1][ $i ], $if_conditions[2][ $i ], $if_conditions[3][ $i ] ) ) {
$html = $if_conditions[4][ $i ];
$html = preg_replace( '#<elseif(.*?)<\/elseif>#s', '', $if_conditions[4][ $i ] );
$html = preg_replace( '#<else(.*?)<\/else>#s', '', $html );
$this->content = str_replace( $ifhtml, $html, $this->content );
} else {
// elseif exists
if ( preg_match_all( '#<elseif field="([a-z0-9-_]+)" operator="([a-z_]+)+" value="(.*?)">(.*?)</elseif>#s', $ifhtml, $elseif_conditions ) ) {
foreach ( $elseif_conditions[0] as $j => $elseifhtml ) {
// elseif condition passed
if ( $this->check_condition( $subscriber, $elseif_conditions[1][ $j ], $elseif_conditions[2][ $j ], $elseif_conditions[3][ $j ] ) ) {
$this->content = str_replace( $ifhtml, $elseif_conditions[4][ $j ], $this->content );
break;
} elseif ( $j == count( $elseif_conditions[0] ) - 1 ) {
// no elseif passes
if ( preg_match( '#<else>(.*?)</else>#s', $ifhtml, $else_conditions ) ) {
$this->content = str_replace( $ifhtml, $else_conditions[1], $this->content );
break;
}
}
}
// no else if but else
} elseif ( preg_match( '#<else>(.*?)</else>#s', $ifhtml, $else_conditions ) ) {
$this->content = str_replace( $ifhtml, $else_conditions[1], $this->content );
// only if statement but didn't pass
} else {
$this->content = str_replace( $ifhtml, '', $this->content );
}
}
}
}
return $this->content;
}
/**
*
*
* @param unknown $subscriber
* @param unknown $field
* @param unknown $operator
* @param unknown $value
* @return unknown
*/
private function check_condition( $subscriber, $field, $operator, $value ) {
// return only true if operator is is_not
if ( ! isset( $subscriber->{$field} ) ) {
return $operator == 'is_not' || $operator == 'not_pattern';
}
switch ( $operator ) {
case 'is':
return $subscriber->{$field} == $value;
case 'is_not':
return $subscriber->{$field} != $value;
case 'begin_with':
return false !== ( strrpos( $subscriber->{$key}, $value, - strlen( $subscriber->{$key} ) ) );
case 'end_with':
return false !== ( ( $t = strlen( $subscriber->{$key} ) - strlen( $value ) ) >= 0 && strpos( $subscriber->{$key}, $value, $t ) );
case 'is_greater':
return $subscriber->{$key} > $value;
case 'is_greater_equal':
return $subscriber->{$key} >= $value;
case 'is_smaller':
return $subscriber->{$key} < $value;
case 'is_smaller_equal':
return $subscriber->{$key} <= $value;
case 'pattern':
return preg_match( '#' . preg_quote( $subscriber->{$key} ) . '#', $value );
case 'not_pattern':
return ! preg_match( '#' . preg_quote( $subscriber->{$key} ) . '#', $value );
}
return false;
}
/**
*
*
* @param unknown $relative_to_absolute (optional)
*/
private function replace_images( $relative_to_absolute = false ) {
// placeholder images
if ( $count = preg_match_all( '#<(img|td|th|v:fill)([^>]*)(src|background)="([^"]+)"([^>]*)>#', $this->content, $hits ) ) {
for ( $i = 0; $i < $count; $i++ ) {
$search = $hits[0][ $i ];
// check if string is still there
if ( $i && false === strrpos( $this->content, $search ) ) {
continue;
}
$imagestring = str_replace( '&', '&', $hits[4][ $i ] );
// not a placeholder image
if ( strpos( $imagestring, 'action=mailster_image_placeholder' ) === false ) {
continue;
}
$tag = $hits[1][ $i ];
$pre_stuff = str_replace( '&', '&', $hits[2][ $i ] );
$attribute = $hits[3][ $i ];
$querystring = wp_parse_url( $imagestring, PHP_URL_QUERY );
$post_stuff = str_replace( '&', '&', $hits[5][ $i ] );
$is_img_tag = 'img' == $tag;
$cache_key = md5( $search );
wp_parse_str( $querystring, $query );
if ( isset( $query['tag'] ) ) {
$replace_to = mailster_cache_get( $cache_key );
if ( false === $replace_to ) {
$parts = explode( ':', trim( $query['tag'] ) );
$factor = isset( $query['f'] ) && $is_img_tag ? (int) $query['f'] : 1;
$width = isset( $query['w'] ) ? (int) $query['w'] * $factor : null;
$height = isset( $query['h'] ) ? (int) $query['h'] * $factor : null;
$crop = isset( $query['c'] ) && $height ? (bool) ( $query['c'] ) : false;
$original = isset( $query['o'] ) ? (bool) ( $query['o'] ) : false;
$post_type = str_replace( '_image', '', $parts[0] );
$is_post = $post_type != $parts[0];
$is_random = null;
$org_src = false;
$is_author = false;
// not on RSS
if ( $relative_to_absolute && 0 === strpos( $post_type, 'mailster_rss_' ) ) {
$relative_to_absolute = false;
}
// tag is [post_type]_author_image
if ( false !== strpos( $post_type, '_author' ) ) {
$is_author = true;
$post_type = str_replace( '_author', '', $post_type );
}
if ( $is_post ) {
// cropping requires height
if ( ! $crop ) {
$height = null;
}
$extra = explode( '|', $parts[1] );
$term_ids = explode( ';', $extra[0] );
$fallback_id = isset( $extra[1] ) ? (int) $extra[1] : mailster_option( 'fallback_image' );
$post_id_or_identifier = array_shift( $term_ids );
$is_random = 0 === strpos( $post_id_or_identifier, '~' );
if ( $is_random ) {
$post = mailster()->get_random_post( substr( $post_id_or_identifier, 1 ), $post_type, $term_ids, $this->last_post_args, $this->campaignID, $this->subscriberID );
} elseif ( $post_id_or_identifier < 0 ) {
$post = mailster()->get_last_post( abs( $post_id_or_identifier ) - 1 + $this->index_offset, $post_type, $term_ids, $this->last_post_args, $this->campaignID, $this->subscriberID );
} elseif ( $post_id_or_identifier > 0 ) {
if ( $relative_to_absolute ) {
continue;
}
$post = get_post( $post_id_or_identifier );
}
} else {
$fallback_id = mailster_option( 'fallback_image' );
$post = null;
$thumb_id = null;
$src = apply_filters( 'mailster_image_placeholder', $query['tag'], $width, $height, $crop, $original, $this->campaignID, $this->subscriberID );
if ( $src && $src != $query['tag'] ) {
if ( ! is_array( $src ) ) {
$src = array( $src, $width, $height );
}
$org_src = $src;
} else {
$org_src = array( '{' . $query['tag'] . '}', $width, $height );
}
}
if ( ! $relative_to_absolute ) {
if ( ! empty( $post ) ) {
if ( is_numeric( $post->ID ) ) {
// tag is [post_type]_author_image
if ( $is_author ) {
$org_src = array( get_avatar_url( $post->post_author, array( 'width' => $width ) ), 0, 0, false );
} else {
if ( 'attachment' == $post->post_type ) {
$thumb_id = $post->ID;
} else {
$thumb_id = get_post_thumbnail_id( $post->ID );
}
$org_src = wp_get_attachment_image_src( $thumb_id, 'full' );
}
}
if ( empty( $org_src ) ) {
if ( is_numeric( $post->post_image ) ) {
$org_src = wp_get_attachment_image_src( $post->post_image, 'full' );
} elseif ( empty( $post->post_image ) ) {
// get image from sites meta tags
if ( $src = mailster( 'helper' )->get_meta_tags_from_url( $post->post_permalink, array( 'mailster:image', 'thumbnail', 'image', 'og:image', 'twitter:image' ) ) ) {
$org_src = array( $src, 0, 0, false );
}
} else {
$org_src = array( $post->post_image, 0, 0, false );
}
}
}
if ( empty( $org_src ) && $fallback_id ) {
$thumb_id = $fallback_id;
$org_src = wp_get_attachment_image_src( $thumb_id, 'full' );
}
if ( ! empty( $org_src ) ) {
if ( $org_src[1] && $org_src[2] ) {
$asp = $org_src[1] / $org_src[2];
$height = $height ? $height : round( ( $width / $asp ) / $factor );
$img = mailster( 'helper' )->create_image( $thumb_id, $org_src[0], $width, $height * $factor, $crop, $original );
} else {
$img = array( 'url' => $org_src[0] );
}
if ( $is_img_tag ) {
// set new height
$post_stuff = preg_replace( '# height="(\d+)"#i', $height ? ' height="' . $height . '"' : '', $post_stuff );
$pre_stuff = preg_replace( '# height="(\d+)"#i', $height ? ' height="' . $height . '"' : '', $pre_stuff );
$replace_to = '<img' . $pre_stuff . 'src="' . $img['url'] . '" ' . $post_stuff . '>';
} else {
$pre_stuff = str_replace( $imagestring, $img['url'], $pre_stuff );
$post_stuff = str_replace( $imagestring, $img['url'], $post_stuff );
$replace_to = '<' . $tag . $pre_stuff . 'background="' . $img['url'] . '" ' . $post_stuff . '>';
}
} elseif ( $is_img_tag ) {
$replace_to = '';
} else {
$pre_stuff = str_replace( $imagestring, '', $pre_stuff );
$post_stuff = str_replace( $imagestring, '', $post_stuff );
$replace_to = '<' . $tag . $pre_stuff . 'background="" ' . $post_stuff . '>';
}
} else {
// not if no ID is provided (custom dynamic post types)
if ( ! $post->ID ) {
continue;
}
if ( $post && ! $is_random ) {
$replace_to = str_replace( 'tag=' . $query['tag'], 'tag=' . $post_type . '_image:' . $post->ID, $search );
}
}
// cache it for faster processing
mailster_cache_set( $cache_key, $replace_to );
}
if ( false !== $replace_to ) {
$replace_to = apply_filters( 'mailster_replace_image', $replace_to, $search, $this->campaignID, $this->subscriberID );
if ( is_wp_error( $replace_to ) ) {
$this->error( $replace_to );
continue;
}
$this->content = str_replace( $search, $replace_to, $this->content );
}
}
}
}
}
/**
*
*
* @param unknown $relative_to_absolute (optional)
*/
private function replace_dynamic( $relative_to_absolute = false ) {
$pts = implode( '|', $this->post_types );
// all dynamic post type tags
if ( $count = preg_match_all( '#\{(!)?((' . $pts . ')_([^}]+):(-|~)?([\d]+)(;([0-9;,-]+))?)\}#i', $this->content, $hits ) ) {
for ( $i = 0; $i < $count; $i++ ) {
$search = $hits[0][ $i ];
$encode = ! empty( $hits[1][ $i ] );
$post_or_offset = $hits[6][ $i ];
$post_type = $hits[3][ $i ];
$type = $hits[5][ $i ];
$term_ids = ! empty( $hits[8][ $i ] ) ? explode( ';', trim( $hits[8][ $i ] ) ) : array();
$is_random = '~' == $type;
// not on RSS
if ( $relative_to_absolute && 0 === strpos( $post_type, 'mailster_rss_' ) ) {
$relative_to_absolute = false;
}
if ( empty( $type ) || $is_random ) {
$post_id = $post_or_offset;
if ( $relative_to_absolute ) {
continue;
}
if ( $is_random ) {
$post = mailster()->get_random_post( $post_or_offset, $post_type, $term_ids, $this->last_post_args, $this->campaignID, $this->subscriberID );
} else {
$post = get_post( $post_or_offset );
}
$post = apply_filters( 'mailster_get_post_' . $post_type, $post, $post_id );
if ( ! $post ) {
continue;
}
$post->post_excerpt = trim( $post->post_excerpt );
if ( empty( $post->post_excerpt ) && preg_match( '/<!--more(.*?)?-->/', $post->post_content, $matches ) ) {
$content = explode( $matches[0], $post->post_content, 2 );
$post->post_excerpt = trim( $content[0] );
$post->post_excerpt = mailster_remove_block_comments( $post->post_excerpt );
}
if ( empty( $post->post_excerpt ) ) {
$post->post_excerpt = mailster( 'helper' )->get_excerpt( $post->post_content );
}
if ( $this->apply_the_excerpt_filters ) {
if ( $length = apply_filters( 'mailster_excerpt_length', null ) ) {
$post->post_excerpt = wp_trim_words( $post->post_excerpt, $length );
}
$post->post_excerpt = apply_filters( 'the_excerpt', $post->post_excerpt );
}
} else {
$post_offset = $post_or_offset - 1;
$term_ids = ! empty( $hits[8][ $i ] ) ? explode( ';', trim( $hits[8][ $i ] ) ) : array();
$post = mailster()->get_last_post( $post_or_offset - 1 + $this->index_offset, $post_type, $term_ids, $this->last_post_args, $this->campaignID, $this->subscriberID );
}
if ( $relative_to_absolute && $post ) {
// not if no ID is provided (custom dynamic post types)
if ( ! $post->ID ) {
continue;
}
if ( $encode ) {
$replace_to = '{!' . $post_type . '_' . $hits[4][ $i ] . ':' . $post->ID . '}';
} else {
$replace_to = '{' . $post_type . '_' . $hits[4][ $i ] . ':' . $post->ID . '}';
}
} elseif ( $post ) {
$what = $hits[4][ $i ];
$replace_to = $this->get_replace( $post, $what );
if ( is_wp_error( $replace_to ) ) {
$replace_to = $this->error( $replace_to, ! $encode );
}
if ( is_null( $replace_to ) ) {
continue;
}
if ( $encode ) {
$replace_to = rawurlencode( $replace_to );
}
} else {
$replace_to = '';
}
$this->content = str_replace( $search, $replace_to, $this->content );
}
}
if ( ! $relative_to_absolute ) {
if ( $count = preg_match_all( '#\{(!)?(tweet:([^}|]+)\|?([^}]+)?)\}#i', $this->content, $hits ) ) {
for ( $i = 0; $i < $count; $i++ ) {
$search = $hits[0][ $i ];
$encode = ! empty( $hits[1][ $i ] );
$tweet = $this->get_last_tweet( $hits[3][ $i ], $hits[4][ $i ] );
if ( $encode ) {
$tweet = rawurlencode( $tweet );
}
$this->content = str_replace( $search, $tweet, $this->content );
}
}
}
}
/**
*
*
*/
private function replace_static( $removeunused = true ) {
global $mailster_tags;
if ( ! did_action( 'mailster_add_tag' ) ) {
do_action( 'mailster_add_tag' );
}
$keep = $this->get_keep_tags();
// replace static
if ( $count = preg_match_all( '#\{(!)?([a-z0-9-_]+):?([^\}|]+)?\|?([^\}]+)?\}#i', $this->content, $hits_fallback ) ) {
for ( $i = 0; $i < $count; $i++ ) {
$search = $hits_fallback[0][ $i ];
$encode = ! empty( $hits_fallback[1][ $i ] );
// check if string is still there
if ( $i && false === strrpos( $this->content, $search ) ) {
continue;
}
$tag = $hits_fallback[2][ $i ];
$option = $hits_fallback[3][ $i ];
$fallback = $hits_fallback[4][ $i ];
$replace = '';
// tag is in placeholders
if ( isset( $this->placeholder[ $search ] ) ) {
$replace = $this->placeholder[ $search ];
if ( $replace && '{preheader}' === $search ) {
/**
* Adds invisible characters after the preheader text also known as "preview text hack"
* Read more here: https://www.litmus.com/blog?p=4367
* Updated in Sept. 2023 to use the new invisible characters
*
* defaults:
* `true`
*
* @param boolean $default default values
*/
$preview_text_fix = apply_filters( 'mailster_preview_text_fix', true );
if ( $preview_text_fix ) {
$preview_text_count = 200 - strlen( $replace );
// PHP throws an error if $count = 0, preventing the campaign from being sent. This check patch this.
if ( $preview_text_count > 0 ) {
$replace .= str_repeat( ' ͏ ‌   ­', $preview_text_count );
}
}
}
// tag is a custom tag
} elseif ( isset( $this->placeholder[ '{' . $tag . '}' ] ) ) {
$replace = $this->placeholder[ '{' . $tag . '}' ];
// tag is a custom tag
} elseif ( isset( $mailster_tags[ $tag ] ) && $this->replace_custom ) {
$replace = call_user_func_array( $mailster_tags[ $tag ], array( $option, $fallback, $this->campaignID, $this->subscriberID ) );
// prevent infinity loops if replace contains it's own tag
if ( false !== strpos( $replace, '{' . $tag ) ) {
$replace = str_replace( array( '{', '}' ), array( '!', '!' ), $replace );
}
// tag should be kept
} elseif ( in_array( $tag, $keep ) ) {
if ( $fallback ) {
$replace = $fallback;
} else {
$this->keeptag[ $i ] = $search;
$replace = '<!--Mailster:keeptag' . $i . '-->';
}
// keep unused
} elseif ( ! $removeunused ) {
continue;
}
// add fallback if set
if ( '' == $replace && $fallback ) {
$replace = $fallback;
}
$replace_to = apply_filters( 'mailster_replace_' . $tag, $replace, $option, $fallback, $this->campaignID, $this->subscriberID );
if ( is_wp_error( $replace_to ) ) {
$replace_to = $this->error( $replace_to, ! $encode );
}
if ( $encode ) {
$replace_to = rawurlencode( $replace_to );
}
$this->content = str_replace( $search, $replace_to, $this->content );
}
}
}
public function get_replace( $post, $what ) {
if ( is_wp_error( $post ) ) {
return $post;
}
$extra = null;
$replace_to = null;
$author = null;
$post_type = $post->post_type;
$post_content = $post->post_content;
// author related tags
if ( 0 === strpos( $what, 'author' ) ) {
$author = get_user_by( 'id', $post->post_author );
$extra = $author;
// post meta related tags (e.g meta[meta_key])
} elseif ( 0 === strpos( $what, 'meta[' ) ) {
preg_match( '#meta\[(.*)\]#i', $what, $metakey );
if ( ! isset( $metakey[1] ) ) {
return null;
}
$metakey = trim( $metakey[1] );
$metavalue = get_post_meta( $post->ID, $metakey, true );
if ( is_null( $metavalue ) ) {
return null;
}
$what = 'meta';
$extra = $metakey;
// categories related tags (e.g categories[taxonomy])
} elseif ( 0 === strpos( $what, 'categories' ) || 0 === strpos( $what, 'category' ) ) {
// if set in the post object use this
if ( is_string( $post->post_category ) ) {
$extra = is_string( $post->post_category ) ? array( $post->post_category ) : $post->post_category;
} else {
preg_match( '#(category|categories)(_strip)?\[(.*)\]#i', $what, $matches );
// check taxonomy type
if ( isset( $matches[2] ) ) {
$taxonomy = trim( $matches[3] );
$what = $matches[1] . $matches[2];
} else {
$taxonomy = 'category';
}
// get all terms of the taxonomy
$terms = get_the_term_list( $post->ID, $taxonomy, '', ', ' );
// no terms or error
if ( ! $terms || is_wp_error( $terms ) ) {
return null;
}
// convert to array
$extra = explode( ', ', $terms );
// only first
if ( 0 === strpos( $what, 'category' ) ) {
// get all terms of the taxonomy
$extra = array( $extra[0] );
}
}
// convert to string
$terms = implode( ', ', $extra );
// with format (e.g date[format])
} elseif ( false !== strpos( $what, '[' ) ) {
preg_match( '#(.*)\[(.*)\]#i', $what, $withformat );
if ( ! isset( $withformat[1] ) ) {
return null;
}
$what = trim( $withformat[1] );
$extra = trim( $withformat[2] );
}
switch ( $what ) {
case 'id':
$replace_to = $post->ID;
break;
case 'title':
$replace_to = str_replace( array( '"', "'" ), array( '"', ''' ), $post->post_title );
break;
case 'button':
$replace_to = esc_html__( 'Read More', 'mailster' );
break;
case 'link':
if ( isset( $post->post_link ) ) {
$replace_to = $post->post_link;
}
case 'permalink':
if ( ! $replace_to && $post->ID ) {
$replace_to = get_permalink( $post->ID );
}
if ( ! $replace_to ) {
$replace_to = $post->post_link;
}
if ( ! $replace_to ) {
$replace_to = $post->post_permalink;
}
break;
case 'shortlink':
if ( $post->ID ) {
$replace_to = wp_get_shortlink( $post->ID );
} else {
$replace_to = $post->post_permalink;
}
break;
case 'author':
case 'author_strip':
if ( ! $author ) {
$replace_to = $post->post_author;
break;
}
if ( $author->data->user_url && $what != 'author_strip' ) {
$replace_to = '<a href="' . $author->data->user_url . '">' . $author->data->display_name . '</a>';
} else {
$replace_to = $author->data->display_name;
}
break;
case 'author_name':
$replace_to = $author ? $author->data->display_name : $post->post_author;
break;
case 'author_nicename':
$replace_to = $author ? $author->data->user_nicename : $post->post_author;
break;
case 'author_email':
$replace_to = $author ? $author->data->user_email : '';
break;
case 'author_url':
$replace_to = $author ? $author->data->user_url : '';
break;
case 'author_info':
$replace_to = $author ? get_the_author_meta( 'description', $author->ID ) : '';
break;
case 'author_image':
$replace_to = $author ? get_avatar_url( $author->ID ) : '';
break;
case 'date':
case 'date_gmt':
case 'modified':
case 'modified_gmt':
$replace_to = date_i18n( $extra ? $extra : mailster( 'helper' )->dateformat(), strtotime( $post->{'post_' . $what} ) );
break;
case 'time':
$what = 'date';
case 'time_gmt':
$what = isset( $what ) ? $what : 'date_gmt';
case 'modified_time':
$what = isset( $what ) ? $what : 'modified';
case 'modified_time_gmt':
$what = isset( $what ) ? $what : 'modified_gmt';
$replace_to = date_i18n( $extra ? $extra : mailster( 'helper' )->timeformat(), strtotime( $post->{'post_' . $what} ) );
break;
case 'excerpt':
if ( ! empty( $post->{'post_excerpt'} ) ) {
$replace_to = wpautop( $post->{'post_excerpt'} );
} else {
$replace_to = mailster( 'helper' )->get_excerpt( $post_content );
}
break;
case 'content':
$replace_to = $post_content;
if ( function_exists( 'do_blocks' ) && has_blocks( $replace_to ) ) {
$replace_to = do_blocks( $replace_to );
}
$replace_to = wpautop( $replace_to );
break;
case 'meta':
$replace_to = maybe_unserialize( $metavalue );
break;
case 'category':
case 'categories':
$replace_to = $terms;
break;
case 'category_strip':
case 'categories_strip':
$replace_to = strip_tags( $terms );
break;
case 'twitter':
case 'facebook':
case 'google':
case 'linkedin':
$replace_to = $this->get_social_service( $what, get_permalink( $post->ID ), get_the_title( $post->ID ) );
break;
case 'image':
$replace_to = '[' . ( sprintf( esc_html__( 'use the tag %s as url in the editbar', 'mailster' ), '"' . $hits[1][ $i ] . '"' ) ) . ']';
break;
default:
if ( isset( $post->{'post_' . $what} ) && $post->{'post_' . $what} ) {
$replace_to = $post->{'post_' . $what};
} elseif ( isset( $post->{$what} ) && $post->{$what} ) {
$replace_to = $post->{$what};
} else {
$replace_to = '';
}
}
return apply_filters( 'mailster_replace_' . $post_type . '_' . $what, $replace_to, $post, $extra, $this->campaignID, $this->subscriberID );
}
/**
*
*
* @param unknown $username
* @param unknown $fallback (optional)
* @return unknown
*/
private function get_last_tweet( $username, $fallback = '' ) {
if ( false === ( $tweet = get_transient( 'mailster_tweet_' . $username ) ) ) {
$token = mailster_option( 'twitter_token' );
$token_secret = mailster_option( 'twitter_token_secret' );
$consumer_key = mailster_option( 'twitter_consumer_key' );
$consumer_secret = mailster_option( 'twitter_consumer_secret' );
if ( ! $token || ! $token_secret || ! $consumer_key || ! $consumer_secret ) {
return esc_html__( 'Please enter your Twitter application credentials on the settings page', 'mailster' );
}
require_once MAILSTER_DIR . 'classes/libs/twitter.class.php';
$twitter = new TwitterApiClass( $token, $token_secret, $consumer_key, $consumer_secret );
if ( is_numeric( $username ) ) {
$method = 'statuses/show/' . $username;
$args = array();
} else {
$method = 'statuses/user_timeline';
$args = array(
'screen_name' => $username,
'count' => 1,
'include_rts' => false,
'exclude_replies' => true,
'include_entities' => true,
);
}
$response = $twitter->query( $method, $args );
if ( is_wp_error( $response ) ) {
return $fallback;
}
$data = $response;
if ( isset( $data->errors ) ) {
return $fallback;
}
if ( isset( $data->error ) ) {
return $fallback;
}
$tweet = ( is_array( $data ) ) ? $data[0] : $data;
if ( ! isset( $tweet->text ) ) {
return $fallback;
}
if ( $tweet->entities->hashtags ) {
foreach ( $tweet->entities->hashtags as $hashtag ) {
$tweet->text = str_replace( '#' . $hashtag->text, '#<a href="https://twitter.com/search/%23' . $hashtag->text . '">' . $hashtag->text . '</a>', $tweet->text );
}
}
if ( $tweet->entities->urls ) {
foreach ( $tweet->entities->urls as $url ) {
$tweet->text = str_replace( $url->url, '<a href="' . $url->url . '">' . $url->display_url . '</a>', $tweet->text );
}
}
$tweet->text = preg_replace( '/(^|\s)@(\w+)/', '\1@<a href="https://twitter.com/\2">\2</a>', $tweet->text );
set_transient( 'mailster_tweet_' . $username, $tweet, 60 * mailster_option( 'tweet_cache_time' ) );
}
return $tweet->text;
}
private function get_keep_tags() {
if ( is_null( $this->keeptags ) ) {
$this->keeptags = array_unique( (array) apply_filters( 'mailster_keep_tags', array() ) );
}
return $this->keeptags;
}
}