first commit

This commit is contained in:
2026-03-05 13:07:40 +01:00
commit 64ba0721ee
25709 changed files with 4691006 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
<?php
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'ES_Logs' ) ) {
/**
* Class to handle es logs
*
* @since 5.6.6
* @version 1.0
* @package Email Subscribers
*/
class ES_Logs {
/**
* Method to show es logs
*
* @since 5.6.6
*
* @modify 5.6.7
*/
public static function show_es_logs() {
$log_files = IG_Log_Handler_File::get_log_files();
$log_nonce = ig_es_get_request_data( 'ig-es-log-nonce' );
$log_files = IG_Log_Handler_File::sort_log_files_by_created_time( $log_files );
$reverse_log_files = array_reverse( $log_files );
$log_file_name = $reverse_log_files[0];
if ( isset( $_POST['submit'] ) ) {
if ( wp_verify_nonce( $log_nonce, 'ig-es-log' ) ) {
if ( isset( $_POST['log_file'] ) ) {
$log_file_name = sanitize_text_field( $_POST['log_file'] );
}
} else {
$message = __( 'Sorry, you are not allowed to view logs.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
exit();
}
}
?>
<style>
.select2-container{
width: 100%!important;
}
.select2-search__field {
width: 100%!important;
}
</style>
<h2 class="wp-heading-inline text-3xl font-bold text-gray-700 sm:leading-9 sm:truncate pr-4 mt-6">
<?php
echo esc_html__( 'Logs', 'email-subscribers' );
?>
</h2>
<div class="flex flex-col space-y-4 pr-4">
<div class="mt-8">
<div class="font-bold text-xl float-left ig-es-log-file-name"><?php echo esc_html( $log_file_name ); ?></div>
<div class="float-right">
<form action="#" method="POST" id="ig-es-log-files-container">
<?php
// logs nonce.
wp_nonce_field( 'ig-es-log', 'ig-es-log-nonce', false );
?>
<span class="inline-block mr-1 ig-es-log-files-dropdown">
<select name="log_file" id="ig-es-log-files">
<?php
$i = 0;
foreach ( $reverse_log_files as $key => $file_name ) {
$files[$i] = $file_name;
?>
<option value="<?php echo esc_attr( $files[$i] ); ?>" <?php selected( $log_file_name, $file_name ); ?>><?php echo esc_html( $files[$i] ); ?></option>
<?php
$i++;
}
?>
</select>
</span>
<button type="submit" name="submit" class="inline-flex justify-center py-1.5 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-indigo-500 rounded-md cursor-pointer select-none focus:outline-none focus:shadow-outline-indigo focus:shadow-lg hover:bg-indigo-500 hover:text-white hover:shadow-md md:px-2 lg:px-3 xl:px-4 ml-2">
<?php echo esc_html__( 'View', 'email-subscribers' ); ?>
</button>
</form>
</div>
</div>
<div class="w-full bg-white rounded shadow">
<div class="px-6 py-4">
<p class="text-gray-700 text-base">
<?php
if ( in_array( $log_file_name, $log_files, true ) ) {
?>
<pre id="ig_es_log_content"><?php echo esc_html__( file_get_contents( IG_LOG_DIR . $log_file_name ) ); ?></pre>
<?php
} else {
$message = __( 'Sorry, you are not allowed to view logs.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
exit();
}
?>
</p>
</div>
</div>
</div>
<?php
}
}
new ES_Logs();
}

View File

@@ -0,0 +1,821 @@
<?php
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Email_Subscribers_Pricing {
public static function sm_show_pricing() {
$utm_medium = apply_filters( 'ig_es_pricing_page_utm_medium', 'in_app_pricing' );
$allowedtags = ig_es_allowed_html_tags_in_esc();
?>
<style type="text/css">
.update-nag {
display: none;
}
.wrap.about-wrap.ig_es {
margin: 0 auto;
max-width: 100%;
}
body{
background-color: white;
}
.ig_es_main_heading {
font-size: 2em;
background-color: #252f3f !important;
color: #ffffff;
text-align: center;
font-weight: 500;
margin: auto;
padding-top: 0.75em;
padding-bottom: 0.5em;
/* max-width: 1375px; */
}
.ig_es_discount_code {
/* color: #6875F5; */
font-weight: 600;
font-size: 2.5rem;
}
.ig_es_sub_headline {
font-size: 1.6em;
font-weight: 400;
color: #00848D !important;
text-align: center;
line-height: 1.5em;
margin: 0 auto 1em;
}
.ig_es_row {
/* padding: 1em !important;
margin: 1.5em !important; */
clear: both;
position: relative;
}
#ig_es_price_column_container {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
max-width: 1190px;
margin-right: auto;
margin-left: auto;
margin-top: 4em;
padding-bottom: 1.2em;
}
.ig_es_column {
padding: 2em;
margin: 0 1em;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
text-align: center;
color: rgba(0, 0, 0, 0.75);
}
.column_one_fourth {
width: 30%;
border-radius: 3px;
margin-right: 4%;
}
.ig_es_last {
margin-right: 0;
}
.ig_es_price {
margin: 1.5em 0;
color: #1e73be;
}
.ig_es_button {
color: #FFFFFF !important;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
font-weight: 500;
margin: 2em 2px 1em 2px;
cursor: pointer;
}
.ig_es_button.green {
background: #23B191;
border-color: #23B191;
}
.ig_es_button.green:hover {
background: #66C78E;
border-color: #66C78E;
}
.ig_es_button.small {
text-transform: uppercase !important;
box-shadow: none;
padding: 0.8em;
font-size: 1rem;
border-radius: 0.25rem;
margin-top: 1em;
font-weight: 600;
}
.ig_es_discount_amount {
font-size: 1.3em !important;
}
.dashicons.dashicons-yes {
color: green;
font-size: 2em;
}
.dashicons.dashicons-no-alt {
color: #ed4337;
font-size: 2em;
}
.dashicons.dashicons-yes.yellow {
color: #BDB76B;
line-height: unset;
}
.dashicons.dashicons-awards,
.dashicons.dashicons-testimonial {
margin-right: 0.25em !important;
color: #15576F;
font-size: 1.25em;
}
.ig_es_license_name {
font-size: 1.1em !important;
color: #1a72bf !important;
font-weight: 500 !important;
}
.ig_es_old_price {
font-size: 1.3em;
color: #ed4337;
vertical-align: top;
}
.ig_es_new_price {
font-size: 1.6em;
padding-left: 0.2em;
font-weight: 400;
}
.ig_es_most_popular {
position: absolute;
right: 0px;
top: -39px;
background-color: #41495b;
background-color: #596174;
text-align: center;
color: white;
padding: 10px;
font-size: 18px;
border-top-right-radius: 4px;
border-top-left-radius: 4px;
font-weight: 500;
width: 275px;
}
#ig-es-testimonial {
text-align: center;
}
.ig-es-testimonial-content {
width: 50%;
margin: 0 auto;
margin-bottom: 1em;
background-color: #FCFEE9;
}
.ig-es-testimonial-content img {
width: 12% !important;
border-radius: 9999px;
margin: 0 auto;
}
#ig_es_testimonial-others .ig-es-testimonial-content img.star-ratings {
width: 18% !important;
}
.ig_es_testimonial_headline {
margin: 0.6em 0 0 !important;
font-weight: 500 !important;
font-size: 1.5em !important;
}
.ig_es_testimonial_text {
text-align: left;
font-size: 1.2em;
line-height: 1.6;
padding: 1em 1em 0;
}
.pricing {
border-radius: 5px;
position: relative;
padding: 0.25em;
margin: 2em auto;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
text-align: center;
color: rgba(0, 0, 0, 0.75);
}
.pricing h4 {
margin-top: 1em;
margin-bottom: 1em;
}
.pricing del {
font-size: 1.3em;
color: grey;
}
.pricing h2 {
margin-top: 0!important;
margin-bottom: 0.5em;
text-align: center;
font-weight: 600;
line-height: 1.218;
color: #515151;
font-size: 2.5em;
}
.pricing p {
text-align: center;
margin: 0em;
}
.pricing:hover{
border-color: #15576F;
}
.pricing.scaleup{
transform: scale(1.2);
}
.fidget.spin{
animation: spin 1.2s 0s linear both infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
table.ig_es_feature_table {
width: 90%;
margin-left: 5%;
margin-right: 5%;
}
table.ig_es_feature_table th,
table.ig_es_feature_table tr,
table.ig_es_feature_table td,
table.ig_es_feature_table td span {
padding: 0.5em;
text-align: center !important;
background-color: transparent !important;
vertical-align: middle !important;
}
table.ig_es_feature_table,
table.ig_es_feature_table th,
table.ig_es_feature_table tr,
table.ig_es_feature_table td {
border: 1px solid #eaeaea;
}
table.ig_es_feature_table.widefat th,
table.ig_es_feature_table.widefat td {
color: #515151;
}
table.ig_es_feature_table th {
font-weight: bolder !important;
font-size: 1.3em;
}
table.ig_es_feature_table tr td {
font-size: 15px;
}
table.ig_es_feature_table th.ig_es_features {
background-color: #F4F4F4 !important;
color: #A1A1A1 !important;
width:16em;
}
table.ig_es_feature_table th.ig_es_free_features {
background-color: #F7E9C8 !important;
color: #D39E22 !important;
}
table.ig_es_feature_table th.ig_es_pro_features{
background-color: #CCFCBF !important;
color: #14C38E !important;
width:16em;
}
table.ig_es_feature_table th.ig_es_starter_features {
background-color: #DCDDFC !important;
color: #6875F5 !important;
}
table.ig_es_feature_table td{
padding: 0.5em;
}
table.ig_es_feature_table td.ig_es_feature_name {
text-transform: capitalize;
padding:1em 2em;
}
table.ig_es_feature_table td.ig_es_free_feature_name {
background-color: #FCF7EC !important;
padding:1em 2em;
}
table.ig_es_feature_table td.ig_es_starter_feature_name {
background-color: #F4F5FD !important;
padding:1em 3em;
}
table.ig_es_feature_table td.ig_es_pro_feature_name {
background-color: #E3FCBF !important;
padding:1em 2em;
}
#ig_es_product_page_link {
text-align: center;
font-size: 1.1em;
margin-top: 2em;
line-height: 2em;
}
.clr-a {
color: #00848D !important;
}
.update-nag , .error, .updated{
display:none;
}
table .dashicons {
padding-top: 0 !important;
}
#wpcontent {
padding-left: 0!important;
}
#ig_es_testimonial-others, #ig_es_activity{
margin-top: 4em;
}
#ig_es_comparison_table{
margin-top: 4em;
}
.ig-es-testimonial-content .ig_es_testimonial_user_name{
font-size: 1em;
margin-top: 0.5em;
}
.ig_es_renew_headline{
font-size: 1em;
font-weight: 400;
color: #00848D !important;
text-align: center;
line-height: 1.5em;
margin: 0 auto 1em;
padding-bottom: 3em;
}
</style>
<div class="wrap about-wrap ig_es">
<div class="ig_es_row" id="ig-es-pricing">
<div class="ig_es_main_heading">
<div style="display: inline-flex;">
<div style="padding-right: 0.5rem;">🎉</div>
<div style="line-height: 2.5rem;">
<?php
/* translators: %s: Offer text */
echo sprintf( esc_html__( 'Congratulations! You unlocked %s on Icegram Express Premium plans!', 'email-subscribers' ), '<span class="ig_es_discount_code">' . esc_html__( '25% off', 'email-subscribers' ) . '</span>' );
?>
</div>
<div style="padding-left: 0.5rem;">🎉</div>
</div>
<div style="padding-top: 1em;font-size: 0.5em;"><?php echo esc_html__( '⏰ Limited time offer', 'email-subscribers' ); ?></div>
</div>
<div id="ig_es_price_column_container">
<div class="ig_es_column column_one_fourth pricing ig_es_lifetime_price">
<span class="ig_es_plan"><h4 class="clr-a center"><?php echo esc_html__( 'Pro', 'email-subscribers' ); ?></h4></span>
<span class="ig_es_plan"><h4 class="clr-a center"><?php echo esc_html__( '1 site (Annual)', 'email-subscribers' ); ?></h4></span>
<span class="ig_es_price">
<p><del class="center"><?php echo esc_html__( '$129', 'email-subscribers' ); ?></del></p>
<h2><?php echo esc_html__( '$97', 'email-subscribers' ); ?></h2>
</span>
<div class="center">
<a class="ig_es_button small green center" href="https://www.icegram.com/?buy-now=39043&qty=1&coupon=es-upgrade-25&page=6&with-cart=1&utm_source=ig_es&utm_medium=<?php echo esc_attr( $utm_medium ); ?>&utm_campaign=pro" target="_blank" rel="noopener"><?php esc_html_e( 'Buy Now', 'email-subscribers' ); ?></a>
</div>
</div>
<div class="ig_es_column column_one_fourth pricing scaleup" style="border-color: #15576F;padding: 0;border-width: 0.2em;">
<div style="text-align: center;background-color: #15576F;color: #FFF;padding: 1em;font-weight: 900;text-transform: uppercase;"> <?php echo esc_html__( 'Best Seller', 'email-subscribers' ); ?> </div>
<span class="ig_es_plan"><h4 class="clr-a center"><?php echo esc_html__( 'Max', 'email-subscribers' ); ?></h4></span>
<span class="ig_es_plan"><h4 class="clr-a center"><?php echo esc_html__( '3 sites (Annual)', 'email-subscribers' ); ?></h4></span>
<span class="ig_es_price">
<p><del class="center"><?php echo esc_html__( '$229', 'email-subscribers' ); ?></del></p>
<h2><?php echo esc_html__( '$172', 'email-subscribers' ); ?></h2>
</span>
<div class="center">
<a class="ig_es_button small green center" href="https://www.icegram.com/?buy-now=404335&qty=1&coupon=es-upgrade-25&page=6&with-cart=1&utm_source=ig_es&utm_medium=<?php echo esc_attr( $utm_medium ); ?>&utm_campaign=max" target="_blank" rel="noopener"><?php esc_html_e( 'Buy Now', 'email-subscribers' ); ?><span style="width: 1em; height: 1em; background-image: url('https://www.storeapps.org/wp-content/themes/storeapps/assets/images/fidget.svg'); display: inline-block; margin-left: 0.5em" class="fidget spin"></span></a>
</div>
</div>
</div>
<div class="ig_es_renew_headline"><?php echo esc_html__( ' * Renew at same discounted price', 'email-subscribers' ); ?></div>
</div>
<div class="ig_es_row" id="ig-es-testimonial">
<div class="ig_es_column ig-es-testimonial-content">
<img src="https://secure.gravatar.com/avatar/bd09132e1396bf948a5710bcdec25126?s=150&d=retro&r=g" alt="laurendevine" />
<h3 class="ig_es_testimonial_headline">
<?php echo esc_html__( 'Worked where other subscriber plugins failed…', 'email-subscribers' ); ?>
</h3>
<img src="<?php echo esc_url( ES_IMG_URL . '/five-stars.png' ); ?>" class="star-ratings" alt="Star ratings">
<div class="ig_es_testimonial_text">
<?php
echo esc_html__( 'This plugin was quick and easy to set up and implement…and, more important than anything…IT WORKS. Other big-name plugins didnt work when re: sending out notifications to users re: new blog entries and THIS ONE DOES. Use with their free RAINMAKER plugin to format the look and feel of your form a bit more, and its even better!', 'email-subscribers' );
?>
<p class="ig_es_testimonial_user_name">
- Lauren Devine
</p>
</div>
</div>
</div>
<div class="ig_es_row" id="ig_es_comparison_table">
<div class="ig_es_sub_headline"><span class="dashicons dashicons-awards"></span><?php echo esc_html__( ' More powerful features with Icegram Express Premium!', 'email-subscribers' ); ?></div>
<table class="ig_es_feature_table wp-list-table widefat">
<thead>
<tr>
<th class="ig_es_features">
<?php echo esc_html__( 'Features', 'email-subscribers' ); ?>
</th>
<th class="ig_es_free_features">
<?php echo esc_html__( 'Free', 'email-subscribers' ); ?>
</th>
<th class="ig_es_starter_features">
<?php echo esc_html__( 'Pro', 'email-subscribers' ); ?>
</th>
<th class="ig_es_pro_features">
<?php echo esc_html__( 'Max', 'email-subscribers' ); ?>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="ig_es_feature_name">
<strong><?php echo esc_html__( 'Plan Highlights', 'email-subscribers' ); ?></strong>
</td>
<td class="ig_es_free_feature_name">
<?php echo esc_html__( 'Unlimited contacts, emails, forms & lists. Automatic welcome emails and new post notifications.', 'email-subscribers' ); ?>
</td>
<td class="ig_es_starter_feature_name">
<?php echo esc_html__( 'Everything in Free + Automatic batch sending, Captcha, Advanced blocks.', 'email-subscribers' ); ?>
</td>
<td class="ig_es_pro_feature_name">
<?php
/* translators: %s. Line break */
echo sprintf( esc_html__( 'Everything in Pro +%s Integrations, List cleanup, Cart recovery emails, Autoresponders', 'email-subscribers' ), '<br/>' );
?>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( '3rd Party SMTP Configuration', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Connect with SMTP services to reliable send transactional emails. Also supports automatic bounce handling.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
<?php echo esc_html__( 'Pepipost', 'email-subscribers' ); ?>
</td>
<td class="ig_es_starter_feature_name">
<?php echo esc_html__( 'Default SMTP', 'email-subscribers' ); ?>
</td>
<td class="ig_es_pro_feature_name">
<?php echo esc_html__( 'Amazon SES, Mailgun, SendGrid, SparkPost, Postmark, Sendinblue, Mailjet & Mailersend.', 'email-subscribers' ); ?>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Detailed Reports/analytics', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Get a detailed email campaign report such as open rate, avg. click rate, user device, browser, country info, IP and more. Also, use built-in UTM to track metrics.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
<?php echo esc_html__( 'Overall Summary', 'email-subscribers' ); ?>
</td>
<td class="ig_es_starter_feature_name">
<?php echo esc_html__( 'Overall Summary', 'email-subscribers' ); ?>
</td>
<td class="ig_es_pro_feature_name">
<?php echo esc_html__( 'Detailed Report', 'email-subscribers' ); ?>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Weekly Summary Email', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Receive a weekly summary of your all email campaigns & growth of your email list.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
<?php echo esc_html__( 'Basic Summary', 'email-subscribers' ); ?>
</td>
<td class="ig_es_starter_feature_name">
<?php echo esc_html__( 'Basic Summary', 'email-subscribers' ); ?>
</td>
<td class="ig_es_pro_feature_name">
<?php echo esc_html__( 'Advanced Summary', 'email-subscribers' ); ?>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Drag and Drop Campaign Editor', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Build email campaigns faster and better with an intuitive drag and drop interface.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
<?php echo esc_html__( 'Basic Blocks', 'email-subscribers' ); ?>
</td>
<td class="ig_es_starter_feature_name">
<?php echo esc_html__( 'Advanced Blocks', 'email-subscribers' ); ?>
</td>
<td class="ig_es_pro_feature_name">
<?php echo esc_html__( 'Advanced Blocks', 'email-subscribers' ); ?>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Automatic Batch Sending', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Send reliable emails via our cron that automates triggering pending queues every 5 minutes. Also, schedule your campaign at a specific time.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Captcha & Security', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Combat spams with the robust Captcha system built-in. Add extra security to your email list by blacklisting domains suggested by our experts.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'List Unsubscribe', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Allow subscribers to select the specific email list to opt out.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Comment Optin', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Whenever a reader leaves a blog comment, add him/her to a specific email list.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Gmail API', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Send reliable transactional emails using your Gmail API safely.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Automatic List Cleanup', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Automatically clean up bad/spam/bounced emails & maintain a healthy email list.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Custom Contact Fields', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Create custom contact fields in your forms and receive responses.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Autoresponder & Workflows', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Setup autoresponder email series based on event triggers.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Send WooCommerce Coupons', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Automatically send unique WooCommerce coupons when someone subscribes, places an order, left a product review and more.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Abandoned Cart Recovery Email', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Send automatic abandoned cart recovery emails when the visitor abandons his/her shopping cart.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Post Digest Notifications', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Send automatic blog post notification when a new blog post gets published. Also, send post digest email on a specific day.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Email Newsletter Archive', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Display a list of all existing email campaign newsletters on your website using a shortcode.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Resend Confirmation Email', 'email-subscribers' ); ?>
<?php echo wp_kses( ES_Common::get_tooltip_html('Resend confirmation emails to those who abandon it when you\'re using the double opt-in feature.'), $allowedtags ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<span class='dashicons dashicons-yes'></span>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Membership Plugin Integration', 'email-subscribers' ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<?php echo esc_html__( 'Integrate with WooCommerce Memberships, MemberPress, Paid Memberships Pro, Ultimate Members.', 'email-subscribers' ); ?>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Popular Integrations', 'email-subscribers' ); ?>
</td>
<td class="ig_es_free_feature_name">
-
</td>
<td class="ig_es_starter_feature_name">
-
</td>
<td class="ig_es_pro_feature_name">
<?php echo esc_html__( 'Integrate with WooCommerce Abandoned Cart, Easy Digital Downloads, GiveWP Donation, Yith Wishlist Item On Sale, LearnDash, Contact Form 7, Ninja Forms, Forminator, Gravity Forms & WP Forms', 'email-subscribers' ); ?>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Support', 'email-subscribers' ); ?>
</td>
<td class="ig_es_free_feature_name">
<?php echo esc_html__( 'WordPress Forum Support', 'email-subscribers' ); ?>
</td>
<td class="ig_es_starter_feature_name">
<?php echo esc_html__( 'Premium Support (Email)', 'email-subscribers' ); ?>
</td>
<td class="ig_es_pro_feature_name">
<?php echo esc_html__( 'VIP Support (Email + Facebook)', 'email-subscribers' ); ?>
</td>
</tr>
<tr>
<td class="ig_es_feature_name">
<?php echo esc_html__( 'Pricing', 'email-subscribers' ); ?>
</td>
<td class="ig_es_free_feature_name">
<span><?php echo esc_html__( 'Free', 'email-subscribers' ); ?></span>
</td>
<td class="ig_es_starter_feature_name">
<div class="center">
<a class="ig_es_button small green center" href="https://www.icegram.com/?buy-now=39043&qty=1&coupon=es-upgrade-25&page=6&with-cart=1&utm_source=ig_es&utm_medium=<?php echo esc_attr( $utm_medium ); ?>&utm_campaign=pro" target="_blank" style="text-transform: none;"><?php esc_html_e( 'Buy Pro', 'email-subscribers' ); ?></a>
</div>
</td>
<td class="ig_es_pro_feature_name">
<div class="center">
<a class="ig_es_button small green center" href="https://www.icegram.com/?buy-now=404335&qty=1&coupon=es-upgrade-25&page=6&with-cart=1&utm_source=ig_es&utm_medium=<?php echo esc_attr( $utm_medium ); ?>&utm_campaign=max" target="_blank" style="text-transform: none;"><?php esc_html_e( 'Buy Max', 'email-subscribers' ); ?></a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="ig_es_row" id="ig_es_testimonial-others">
<div style="width: 70%; margin: 0 auto; display: flex; gap: 2em;">
<div class="ig_es_column ig-es-testimonial-content">
<img src="https://secure.gravatar.com/avatar/df87927c83228d3ab0c85a7167a708b4?s=150&d=retro&r=g" alt="Resolve">
<h3 class="ig_es_testimonial_headline">
<?php echo esc_html__( 'Perfect plugin for blog promotion', 'email-subscribers' ); ?>
</h3>
<img src="<?php echo esc_url( ES_IMG_URL . '/five-stars.png' ); ?>" class="star-ratings" alt="Star ratings">
<div class="ig_es_testimonial_text">
<?php
echo esc_html__( 'This plugin works great in WordPress. Simple, yet effective. When a new blog is released, it sends a customized email along with a link to the blog title. Great to stimulate web traffic, yet sends a simple email. Have been using for over 6 months.', 'email-subscribers' );
?>
<p class="ig_es_testimonial_user_name">
- Resolve
</p>
</div>
</div>
<div class="ig_es_column ig-es-testimonial-content">
<img src="https://secure.gravatar.com/avatar/5f23eacce811025ec51f7bc95f9bd6c7?s=150&d=retro&r=g" alt="Rick Vidallon">
<h3 class="ig_es_testimonial_headline">
<?php echo esc_html__( 'Great for Professional Bloggers', 'email-subscribers' ); ?>
</h3>
<img src="<?php echo esc_url( ES_IMG_URL . '/five-stars.png' ); ?>" class="star-ratings" alt="Star ratings">
<div class="ig_es_testimonial_text">
<?php
echo esc_html__( 'Great for Professional Bloggers and great support! Icegram was very responsive to our questions. I highly recommend this WordPress plugin and the PAID version is worth the cost. The paid version shows intuitive stats and drill-down information.', 'email-subscribers' );
?>
<p class="ig_es_testimonial_user_name">
- Rick Vidallon
</p>
</div>
</div>
</div>
</div>
<div class="ig_es_row" id="ig_es_activity" style="width: 70%; margin: 0 auto; margin-top: 4em;">
<div class="ig_es_sub_headline"> <?php echo esc_html__( 'Few hours left to grab this deal!', 'email-subscribers' ); ?> </div>
<p>
<?php
/* translators: %s: HTML tag */
echo sprintf( esc_html__( '%1$sEmbrace the power of choice%2$s: Choose between the traditional approach of manually sending email marketing campaigns or embrace the revolutionary power of Icegram Express, enabling the seamless automation of reliable emails that effortlessly land in subscribers\' inboxes, untainted by the clutches of spam folders.
', 'email-subscribers' ), '<strong>', '</strong>' );
?>
</p>
<div style="text-align: center;"><a class="ig_es_button small green center" href="#ig_es_price_column_container" style="text-transform: none; margin-top: 1.5em;"><?php echo esc_html__( 'Select a plan now', 'email-subscribers' ); ?></a></div>
</div>
</div>
<?php
}
}
new Email_Subscribers_Pricing();

View File

@@ -0,0 +1,401 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_Actions' ) ) {
/**
* Class ES_Actions
*
* Track all actions
*
* IG_CONTACT_SUBSCRIBE => 1,
* IG_MESSAGE_SENT => 2,
* IG_MESSAGE_OPEN => 3,
* IG_LINK_CLICK => 4,
* IG_CONTACT_UNSUBSCRIBE => 5,
* IG_MESSAGE_SOFT_BOUNCE => 6,
* IG_MESSAGE_HARD_BOUNCE => 7,
* IG_MESSAGE_ERROR => 8
*
* @since 4.2.0
*/
class ES_Actions {
/**
* ES_DB_Actions object
*
* @since 4.2.1
* @var $db
*/
protected $db;
/**
* ES_Actions constructor.
*
* @since 4.2.0
*/
public function __construct() {
$this->db = new ES_DB_Actions();
add_action( 'init', array( &$this, 'init' ), 1 );
}
/**
* Init Actions
*
* @since 4.2.0
*/
public function init() {
add_action( 'ig_es_contact_subscribe', array( &$this, 'subscribe' ), 10, 2 );
add_action( 'ig_es_message_sent', array( &$this, 'sent' ), 10, 3 );
add_action( 'ig_es_message_open', array( &$this, 'open' ), 10, 3 );
add_action( 'ig_es_message_click', array( &$this, 'click' ), 10, 5 );
add_action( 'ig_es_contact_unsubscribe', array( &$this, 'unsubscribe' ), 10, 4 );
}
/**
* Get action data
*
* @since 4.2.0
*/
public function get_fields( $fields = null, $where = null ) {
global $wpdb, $wpbd;
$fields = esc_sql( is_null( $fields ) ? '*' : ( is_array( $fields ) ? implode( ', ', $fields ) : $fields ) );
$sql = "SELECT $fields FROM {$wpdb->prefix}ig_actions WHERE 1=1";
if ( is_array( $where ) ) {
foreach ( $where as $key => $value ) {
$sql .= ', ' . esc_sql( $key ) . " = '" . esc_sql( $value ) . "'";
}
}
return $wpbd->get_results( $sql, ARRAY_A );
}
/**
* Add action
*
* @param $args
* @param bool $explicit
*
* @return bool
*
* @since 4.2.0
*/
private function add( $args, $explicit = true ) {
$args = wp_parse_args(
$args,
array(
'created_at' => ig_es_get_current_gmt_timestamp(),
'updated_at' => ig_es_get_current_gmt_timestamp(),
'count' => 1,
'ip' => '',
'country' => '',
'browser' => '',
'device' => '',
'os' => '',
'email_client' => '',
)
);
return $this->db->add( $args, $explicit );
}
/**
* Track Contact Action
*
* @param $args
* @param bool $explicit
*
* @since 4.2.4
*/
private function add_contact_action( $args, $explicit = true ) {
return $this->add( $args, $explicit );
}
/**
* Add action
*
* @param $args
* @param bool $explicit
*
* @return bool
*
* @since 4.2.0
*/
private function add_action( $args, $explicit = true ) {
return $this->add( $args, $explicit );
}
/**
* Track Subscribe Action
*
* @param $contact_id
* @param array $list_ids
*
* @since 4.2.0
*/
public function subscribe( $contact_id, $list_ids = array() ) {
if ( is_array( $list_ids ) && count( $list_ids ) > 0 ) {
foreach ( $list_ids as $list_id ) {
$this->add_action(
array(
'contact_id' => $contact_id,
'list_id' => $list_id,
'type' => IG_CONTACT_SUBSCRIBE,
)
);
}
}
}
/**
* Track Send Action
*
* @param $contact_id
* @param $message_id
* @param $campaign_id
*
* @return bool
*
* @since 4.2.0
*/
public function sent( $contact_id, $campaign_id = 0, $message_id = 0 ) {
return $this->add_action(
array(
'contact_id' => $contact_id,
'campaign_id' => $campaign_id,
'message_id' => $message_id,
'type' => IG_MESSAGE_SENT,
)
);
}
/**
* Track Message Open Action
*
* @param $contact_id
* @param $message_id
* @param $campaign_id
*
* @return bool
*
* @since 4.2.0
*/
public function open( $contact_id, $message_id, $campaign_id, $explicit = true ) {
// Track only if campaign sent.
if ( $this->is_campaign_sent( $contact_id, $message_id, $campaign_id ) ) {
$action_data = array(
'contact_id' => $contact_id,
'message_id' => $message_id,
'campaign_id' => $campaign_id,
'type' => IG_MESSAGE_OPEN,
);
$device_info = $this->get_user_device_info();
$action_data = array_merge( $action_data, $device_info );
return $this->add_action( $action_data, $explicit );
}
}
/**
* Track Link Click Action
*
* @param $contact_id
* @param $message_id
* @param $campaign_id
* @param $link_id
*
* @return bool
*
* @since 4.2.0
*/
public function click( $link_id, $contact_id, $message_id, $campaign_id, $explicit = true ) {
// When someone click on link which means they have opened that email
// Track Email Open
$this->open( $contact_id, $message_id, $campaign_id, false );
$action_data = array(
'contact_id' => $contact_id,
'campaign_id' => $campaign_id,
'message_id' => $message_id,
'link_id' => $link_id,
'type' => IG_LINK_CLICK,
);
$device_info = $this->get_user_device_info();
$action_data = array_merge( $action_data, $device_info );
return $this->add_contact_action( $action_data, $explicit );
}
/**
* Track Contact Unsubscribe Action
*
* @param $contact_id
* @param $message_id
* @param $campaign_id
* @param array $list_ids
*
* @since 4.2.0
*/
public function unsubscribe( $contact_id, $message_id, $campaign_id, $list_ids = array() ) {
if ( is_array( $list_ids ) && count( $list_ids ) > 0 ) {
foreach ( $list_ids as $list_id ) {
$this->add_action(
array(
'contact_id' => $contact_id,
'message_id' => $message_id,
'campaign_id' => $campaign_id,
'list_id' => $list_id,
'type' => IG_CONTACT_UNSUBSCRIBE,
)
);
}
}
}
/**
* Track Message Bounce Action
*
* @param $contact_id
* @param $message_id
* @param $campaign_id
* @param bool $hard
*
* @since 4.2.0
*/
public function bounce( $contact_id, $campaign_id, $hard = false ) {
$this->add_action(
array(
'contact_id' => $contact_id,
'campaign_id' => $campaign_id,
'type' => $hard ? IG_MESSAGE_HARD_BOUNCE : IG_MESSAGE_SOFT_BOUNCE,
)
);
}
/**
* Check whether campaign is sent to specific contact
*
* @param $contact_id
* @param $message_id
* @param $campaign_id
*
* @return string|null
*
* @since 4.2.3
*/
public function is_campaign_sent( $contact_id, $message_id, $campaign_id ) {
global $wpdb;
$sql = $wpdb->get_var( $wpdb->prepare( "SELECT count(*) FROM {$wpdb->prefix}ig_actions WHERE contact_id = %d AND message_id = %d AND campaign_id = %d AND type = %d ", $contact_id, $message_id, $campaign_id, IG_MESSAGE_SENT ) );
return $sql;
}
/**
* Method to update campaign viewed/opened_at status
*
* @param int $conact_id
* @param int $campaign_id
* @param int $message_id
*
* @return bool|false|int|void
*
* @since 4.4.7
*/
public function update_viewed_status( $conact_id = 0, $campaign_id = 0, $message_id = 0 ) {
global $wpdb;
if ( empty( $conact_id ) || empty( $campaign_id ) ) {
return;
}
$current_date = ig_get_current_date_time();
$sql = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}ig_sending_queue SET opened_at = %s, opened = %d WHERE contact_id = %d AND campaign_id = %d AND mailing_queue_id = %d", $current_date, 1, $conact_id, $campaign_id, $message_id ) );
return $sql;
}
/**
* Method to get current device information
*
* @since 4.5.0
*/
public function get_user_device_info() {
$browser = new ES_Browser();
$device_info = array();
if ( $browser->isMobile() ) {
$device_info['device'] = 'mobile';
} elseif ( $browser->isTablet() ) {
$device_info['device'] = 'tablet';
} else {
$device_info['device'] = 'desktop';
}
$device_ip_address = ig_es_get_ip();
if ( ! empty( $device_ip_address ) && 'UNKNOWN' !== $device_ip_address ) {
$device_location_data = ES_Geolocation::geolocate_ip( $device_ip_address );
$device_country_code = ! empty( $device_location_data['country_code'] ) ? $device_location_data['country_code'] : '';
$device_info['country'] = $device_country_code;
} else {
$device_ip_address = '';
$device_info['country'] = '';
}
$device_info['ip'] = $device_ip_address;
$device_info['browser'] = $browser->getBrowser();
$device_info['os'] = $browser->getPlatform();
$device_info['email_client'] = $browser->get_email_client();
return $device_info;
}
public function get_action_verb( $action_type ) {
$action_verb = '';
switch ( $action_type ) {
case IG_CONTACT_SUBSCRIBE:
$action_verb = __( 'subscribed to', 'email-subscribers' );
break;
case IG_MESSAGE_SENT:
$action_verb = __( 'received', 'email-subscribers' );
break;
case IG_MESSAGE_OPEN:
$action_verb = __( 'opened', 'email-subscribers' );
break;
case IG_LINK_CLICK:
$action_verb = __( 'clicked on', 'email-subscribers' );
break;
case IG_CONTACT_UNSUBSCRIBE:
$action_verb = __( 'unsubscribed from', 'email-subscribers' );
break;
case IG_MESSAGE_SOFT_BOUNCE:
$action_verb = __( 'marked as soft bounced', 'email-subscribers' );
break;
case IG_MESSAGE_HARD_BOUNCE:
$action_verb = __( 'marked as hard bounced', 'email-subscribers' );
break;
}
return $action_verb;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,186 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Cache implementation of the plugin
*
* @credit - Inspired by the WooCommerce Cache implementation.
*/
if ( ! class_exists( 'ES_Cache' ) ) {
/**
* Class ES_Cache
*
* @since 4.4.0
*/
class ES_Cache {
/**
* Cache enabled/disabled
*
* @var bool
*/
public static $enabled = true;
/**
* Get default transient expiration
*
* @return mixed|void
*/
public static function get_default_transient_expiration() {
return apply_filters( 'ig_es_cache_default_expiration', 10 );
}
/**
* Set the transient
*
* @param $key
* @param $value
* @param bool $expiration
*
* @return bool
*/
public static function set_transient( $key, $value, $expiration = false ) {
if ( ! self::$enabled ) {
return false;
}
if ( ! $expiration ) {
$expiration = self::get_default_transient_expiration();
}
return set_transient( 'ig_es_cache_' . $key, $value, $expiration * HOUR_IN_SECONDS );
}
/**
* Get the transient
*
* @param string $key
*
* @return bool|mixed
*
* @since 4.4.0
*/
public static function get_transient( $key ) {
if ( ! self::$enabled ) {
return false;
}
return get_transient( 'ig_es_cache_' . $key );
}
/**
* Transient delete
*
* @param $key
*
* @since 4.4.0
*/
public static function delete_transient( $key ) {
delete_transient( 'ig_es_cache_' . $key );
}
/**
* Only sets if key is not falsy
*
* @param string $key
* @param mixed $value
* @param string $group
*
* @since 4.4.0
*/
public static function set( $key, $value, $group ) {
if ( ! $key ) {
return;
}
wp_cache_set( (string) $key, $value, "ig_es_$group" );
}
/**
* Get the data
*
* @param $key
* @param $group
* @param false $force
* @param null $found
*
* @return false|mixed
*/
public static function get( $key, $group, $force = false, &$found = null ) {
if ( ! $key ) {
return false;
}
return wp_cache_get( (string) $key, "ig_es_$group", $force, $found );
}
/**
* Checks if key is found in the cache or not
*
* @param string $key
* @param string $group
*
* @return bool
*
* @since 4.4.0
*/
public static function is_exists( $key, $group ) {
if ( ! $key ) {
return false;
}
$found = false;
wp_cache_get( (string) $key, "ig_es_$group", false, $found );
return $found;
}
/**
* Only deletes if key is not falsy
*
* @param string $key
* @param string $group
*
* @since 4.4.0
*/
public static function delete( $key, $group ) {
if ( ! $key ) {
return;
}
wp_cache_delete( (string) $key, "ig_es_$group" );
}
/**
* Generate cache key
*
* @param string $string
*
* @return boolean $exists_in_cache
*
* @since 4.7.2
*/
public static function generate_key( $string = '' ) {
$cache_key = '';
if ( ! empty( $string ) ) {
$cache_key = md5( $string ); // Convert to md5 hash string
}
return $cache_key;
}
/**
* Flush cache
*
* @since 4.7.2
*/
public static function flush() {
wp_cache_flush();
}
}
}

View File

@@ -0,0 +1,890 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Campaign_Report extends ES_List_Table {
public static $instance;
public function __construct() {
parent::__construct(
array(
'singular' => __( 'Report', 'email-subscribers' ), // singular name of the listed records
'plural' => __( 'Reports', 'email-subscribers' ), // plural name of the listed records
'ajax' => true, // does this table support ajax?,
'screen' => 'es_reports',
)
);
add_action( 'ig_es_view_report_data_lite', array( $this, 'view_report_data_lite' ) );
add_action( 'ig_es_view_report_description_lite', array( $this, 'view_report_description_lite' ), 10, 2 );
add_action( 'ig_es_view_activity_table_html', array( $this, 'view_activity_report_table' ), 10, 3 );
add_action( 'admin_footer', array( $this, 'es_view_activity_report_sort_and_filter' ) );
}
/**
* Get individual reports data
*
* @version 5.4.2
*/
public static function view_report_data_lite( $id ) {
global $wpdb;
$notification = ES_DB_Mailing_Queue::get_notification_by_hash( $id );
$report_id = $notification['id'];
$notification_campaign_id = $notification['campaign_id'];
$total_email_sent = ES()->actions_db->get_count_based_on_id_type( $notification_campaign_id, $report_id, IG_MESSAGE_SENT );
$email_viewed_count = ES()->actions_db->get_count_based_on_id_type( $notification_campaign_id, $report_id, IG_MESSAGE_OPEN );
//--->
$email_unsubscribed_count = ES()->actions_db->get_count_based_on_id_type( $notification_campaign_id, $report_id, IG_CONTACT_UNSUBSCRIBE );
$avg_unsubscribed_rate = !empty($total_email_sent) ? number_format_i18n(( ( $email_unsubscribed_count/$total_email_sent ) * 100 ), 2) : 0;
//--->
$avg_open_rate = ! empty( $total_email_sent) ? number_format_i18n( ( ( $email_viewed_count * 100 ) / $total_email_sent ), 2 ) : 0;
$email_click_count = ! empty( $notification_campaign_id ) ? ES()->actions_db->get_count_based_on_id_type( $notification_campaign_id, $report_id, IG_LINK_CLICK ) : 0;
$avg_click_rate = ! empty( $total_email_sent ) ? number_format_i18n( ( ( $email_click_count * 100 ) / $total_email_sent ), 2 ) : 0;
if ( empty( $notification['campaign_id'] ) ) {
$notification_type = __( 'Post Notification', 'email-subscribers' );
} else {
$notification_type = ES()->campaigns_db->get_campaign_type_by_id( $notification['campaign_id'] );
$notification_type = strtolower( $notification_type );
$notification_type = ( 'newsletter' === $notification_type ) ? __( 'Broadcast', 'email-subscribers' ) : $notification_type;
}
$report_kpi_statistics = array(
'total_email_sent' => number_format_i18n( $total_email_sent ),
'email_viewed_count' => number_format_i18n( $email_viewed_count ),
'email_unsubscribed_count' => number_format_i18n( $email_unsubscribed_count ),
'email_click_count' => number_format_i18n( $email_click_count ),
'avg_open_rate' => $avg_open_rate,
'avg_click_rate' => $avg_click_rate,
'avg_unsubscribed_rate' => $avg_unsubscribed_rate,
);
$notification['type'] = ucwords( str_replace( '_', ' ', $notification_type ) );
$notification_subject = $notification['subject'];
$notification_campaign = ES()->campaigns_db->get_campaign_by_id( $notification_campaign_id, - 1 );
$notification['from_email'] = ! empty( $notification_campaign['from_email'] ) ? $notification_campaign['from_email'] : '';
$notification_lists_ids = ! empty( $notification_campaign['list_ids'] ) ? explode( ',', $notification_campaign['list_ids'] ) : array();
$notification['list_name'] = ES_Common::prepare_list_name_by_ids( $notification_lists_ids );
$total_contacts = $notification['count'];
$notification_status = $notification['status'];
$campaign_meta = ! empty( $notification_campaign['meta'] ) ? unserialize( $notification_campaign['meta']) : '';
$notification['list_conditions'] = ! empty( $campaign_meta['list_conditions'] ) ? $campaign_meta['list_conditions'] : '';
$where = $wpdb->prepare( 'message_id = %d ORDER BY updated_at DESC', $report_id );
$notification_actions = ES()->actions_db->get_by_conditions( $where );
$links_where = $wpdb->prepare( 'message_id = %d', $report_id );
$notification_links = ES()->links_db->get_by_conditions( $links_where );
$activity_data = array();
$time_offset = get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
$date_format = get_option( 'date_format' );
if ( ! empty( $notification_actions ) ) {
foreach ( $notification_actions as $notification_action ) {
$action_type = (int) $notification_action['type'];
if ( in_array( $action_type, array( IG_MESSAGE_OPEN, IG_LINK_CLICK ), true ) ) {
$created_timestamp = $notification_action['created_at'];
//$created_date = date_i18n( $date_format, $created_timestamp + $time_offset );
$created_date = gmdate( 'Y-m-d', $created_timestamp + $time_offset );
if ( ! isset( $activity_data[ $created_date ] ) ) {
$activity_data[ $created_date ] = array(
'opened' => 0,
'clicked' => 0,
);
}
if ( IG_MESSAGE_OPEN === $action_type ) {
$activity_data[ $created_date ]['opened'] ++;
} elseif ( IG_LINK_CLICK === $action_type ) {
$activity_data[ $created_date ]['clicked'] ++;
}
}
}
}
if ( ! empty( $activity_data ) ) {
ksort( $activity_data );
}
// To display report header information and KPI values
do_action( 'ig_es_view_report_description_lite', $notification, $report_kpi_statistics );
}
/**
* Display Report header information and KPI values
*
* @version 5.4.2
*/
public function view_report_description_lite( $notification, $report_kpi_statistics ) {
?>
<div class="wrap max-w-7xl w-full">
<div class="wp-heading-inline flex items-center justify-between">
<div class="flex-shrink-0 break-words">
<h2 class="text-2xl font-medium leading-7 tracking-wide text-gray-900 pt-1">
<?php echo esc_html__( 'Report', 'email-subscribers' ); ?>
</h2>
</div>
</div>
<div class="mt-3 pb-2 w-full bg-white rounded-md shadow flex">
<div class="w-3/4">
<div class="flex pl-6 pt-4">
<div class="w-auto inline-block text-xl text-gray-600 font-medium leading-7 truncate">
<?php echo esc_html( $notification['subject'] ); ?>
</div>
<div class="inline-block ml-2 font-semibold leading-5 tracking-wide text-xs">
<?php
switch ( $notification['status'] ) {
case 'Sent':
?>
<svg class="inline-block mt-1.5 ml-1 h-5 w-5 text-green-400" fill="currentColor" viewBox="0 0 20 20">
<title><?php echo esc_attr__( 'Sent', 'email-subscribers' ); ?></title>
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
</svg>
<?php
break;
case 'In Queue':
?>
<svg class="inline-block mt-1.5 ml-1 h-5 w-5 text-orange-400" fill="currentColor" viewBox="0 0 20 20">
<title><?php echo esc_attr__( 'In Queue', 'email-subscribers' ); ?></title>
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/>
</svg>
<?php
break;
case 'Sending':
?>
<svg class="inline-block mt-1.5 ml-1 h-5 w-5 text-yellow-400" fill="currentColor" viewBox="0 0 20 20">
<title><?php echo esc_attr__( 'Sending', 'email-subscribers' ); ?></title>
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-8.707l-3-3a1 1 0 00-1.414 1.414L10.586 9H7a1 1 0 100 2h3.586l-1.293 1.293a1 1 0 101.414 1.414l3-3a1 1 0 000-1.414z" clip-rule="evenodd"/>
</svg>
<?php
break;
case '1':
?>
<span class="inline-flex px-2 text-green-800 bg-green-100 rounded-full"><?php echo esc_html__('Active', 'email-subscribers'); ?></span>
<?php
break;
case '':
?>
<span class="inline-flex px-2 text-red-800 bg-red-100 rounded-full"><?php echo esc_html__('Inactive', 'email-subscribers'); ?></span>
<?php } ?>
</div>
</div>
<div class="w-full text-gray-600 italic font-medium pt-4 text-sm leading-5 overflow-hidden">
<p class="pl-6 truncate"><?php echo esc_html__( 'Type: ', 'email-subscribers' ); ?>
<span class="pl-1 font-normal not-italic text-gray-900"><?php echo esc_html( $notification['type'] ); ?></span>
</p>
<p class="pl-6 pt-2 truncate"><?php echo esc_html__( 'From: ', 'email-subscribers' ); ?>
<span class="pl-1 font-normal not-italic text-gray-900"><?php echo esc_html( $notification['from_email'] ); ?></span>
</p>
<div class="pl-6 pt-2 inline-block truncate relative w-full">
<span class="recipient-text"><?php echo esc_html__( 'Recipient(s): ', 'email-subscribers' ); ?></span>
<div class="pl-1 font-normal not-italic text-gray-900 inline-block truncate w-11/12" style="padding-left: 80px;">
<?php
if ( ! empty( $notification['list_name'] ) ) {
echo esc_html( $notification['list_name'] );
} else {
if ( ! empty( $notification['list_conditions'] ) ) {
do_action( 'ig_es_campaign_show_conditions', $notification['list_conditions'] );
}
}
?>
</div>
</div>
<?php if ( ! in_array( $notification['type'], array( 'Sequence Message', 'Workflow Email' ), true ) ) { ?>
<p class="pl-6 pt-2 text-gray-600 "><?php echo esc_html__( 'Date: ', 'email-subscribers' ); ?>
<span class="pl-1 font-normal not-italic text-gray-900"><?php echo wp_kses_post( ig_es_format_date_time( $notification['start_at'] ) ); ?></span>
</p>
<?php } ?>
</div>
</div>
<div class="w-1/2">
<div class="flex-1 min-w-0">
<p class="pt-4 pl-8 text-lg font-medium leading-6 text-gray-400">
<?php echo esc_html__( 'Statistics', 'email-subscribers' ); ?>
</p>
<div class="sm:grid sm:grid-cols-2 ml-6 mr-8">
<div class="p-2">
<span class = "text-2xl font-bold leading-none text-indigo-600">
<?php echo esc_html( $report_kpi_statistics['email_viewed_count']); ?>
</span>
<span class = "text-xl font-bold leading-none text-indigo-600">
<?php echo esc_html( ' (' . $report_kpi_statistics['avg_open_rate'] . '%)'); ?>
</span>
<p class="mt-1 font-medium leading-6 text-gray-500">
<?php echo esc_html__( 'Opened', 'email-subscribers' ); ?>
</p>
</div>
<div class="p-2">
<span class = "text-2xl font-bold leading-none text-indigo-600">
<?php echo esc_html( '0' ); ?>
</span>
<span class = "text-xl font-bold leading-none text-indigo-600">
<?php echo esc_html( '(0.00%)'); ?>
</span>
<?php
$utm_args = array(
'utm_medium' => 'campaign-report-analytics',
'url' => 'https://www.icegram.com/documentation/what-analytics-does-email-subscribers-track/'
);
$pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
?>
<p class="mt-1 font-medium leading-6 text-gray-500">
<?php echo esc_html__( 'Clicked', 'email-subscribers' ); ?>
<a target="_blank" href="<?php echo esc_url( $pricing_url ); ?>">
<span class="premium-icon max ml-2 mb-1"></span>
</a>
</p>
</div>
<div class="p-2">
<span class="text-2xl font-bold leading-none text-indigo-600">
<?php echo esc_html( $report_kpi_statistics['total_email_sent'] ); ?>
</span>
<p class="mt-1 font-medium leading-6 text-gray-500">
<?php echo esc_html__( 'Sent', 'email-subscribers' ); ?>
</p>
</div>
<div class="p-2">
<span class = "text-2xl font-bold leading-none text-indigo-600">
<?php echo esc_html( '0' ); ?>
</span>
<span class = "text-xl font-bold leading-none text-indigo-600">
<?php echo esc_html( '(0.00%)' ); ?>
</span>
<p class="mt-1 font-medium leading-6 text-gray-500">
<?php echo esc_html__( 'Unsubscribed', 'email-subscribers' ); ?>
<a target="_blank" href="<?php echo esc_url( $pricing_url ); ?>">
<span class="premium-icon max ml-2 mb-1"></span>
</a>
</p>
</div>
</div>
</div>
</div>
</div>
<?php
}
public function es_campaign_report_callback() {
?>
<?php
$this->ajax_response();
$paged = ig_es_get_request_data( 'paged', 1 );
$campaign_class = '';
if ( ES()->is_pro() ) {
$campaign_class = 'es_campaign_premium';
}
?>
<div id="poststuff" class="es-items-lists es-campaign-reports-table">
<div id="post-body" class="metabox-holder column-1">
<div id="post-body-content">
<div class="meta-box-sortables ui-sortable">
<form method="get" class="es_campaign_report <?php echo esc_html( $campaign_class ); ?>" id="es_campaign_report">
<input type="hidden" name="order" />
<input type="hidden" name="orderby" />
<input type="hidden" name="paged" value='<?php echo esc_attr( $paged ); ?>'/>
<p class="inline text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e( 'Activity Info', 'email-subscribers' ); ?></p>
<?php $this->display(); ?>
</form>
</div>
</div>
</div>
</div>
<?php
}
public function ajax_response() {
$this->prepare_items();
$no_placeholder = ig_es_get_request_data( 'no_placeholder', '' );
extract( $this->_args );
extract( $this->_pagination_args, EXTR_SKIP );
ob_start();
if ( ! empty( $no_placeholder ) ) {
$this->display_rows();
} else {
$this->display_rows_or_placeholder();
}
$rows = ob_get_clean();
ob_start();
$this->print_column_headers();
$headers = ob_get_clean();
ob_start();
$this->pagination( 'top' );
$pagination_top = ob_get_clean();
ob_start();
$this->pagination( 'bottom' );
$pagination_bottom = ob_get_clean();
$response = array( 'rows' => $rows );
$response['column_headers'] = $headers;
$response['pagination']['top'] = $pagination_top;
$response['pagination']['bottom'] = $pagination_bottom;
if ( isset( $total_items ) ) {
/* translators: %s: Total items in the table */
$response['total_items_i18n'] = sprintf( _n( '%s item', '%s items', $total_items, 'email-subscribers' ), number_format_i18n( $total_items ) );
}
if ( isset( $total_pages ) ) {
$response['total_pages'] = $total_pages;
$response['total_pages_i18n'] = number_format_i18n( $total_pages );
}
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
die( json_encode( $response ) );
} else {
return $response;
}
}
/**
* Columns to make sortable.
*
* @return array
*/
public function get_sortable_columns() {
$sortable_columns = array(
'email' => array( 'email', false ),
'country_flag' => array( 'country_flag', false ),
'os' => array( 'os', false ),
'email_client' => array( 'email_client', false ),
'sent_at' => array( 'sent_at', false ),
'opened_at' => array( 'opened_at', false ),
'status' => array( 'status', false ),
);
return $sortable_columns;
}
/**
* Handles data query and filter, sorting, and pagination.
*/
public function prepare_items() {
$per_page = 100;
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$data = $this->get_activity_table_data();
$total_items = $this->get_activity_table_data( true );
$this->items = $data;
/**
* Call to _set_pagination_args method for informations about
* total items, items for page, total pages and ordering
*/
$this->set_pagination_args(
array(
'total_items' => $total_items,
'per_page' => $per_page,
)
);
}
/**
* Method to handle display of WP_List table
*
* @Override of display method
*/
public function display() {
$search = ig_es_get_request_data( 's' );
$this->search_box( $search, 'campaign-reports-search-input' );
parent::display();
}
/**
* Prepare search box
*
* @param string $text
* @param string $input_id
*
* @since 4.6.12
*/
public function search_box( $text = '', $input_id = '' ) {
do_action( 'ig_es_campaign_reports_filter_options', $text, $input_id );
}
/**
* Associative array of columns
*
* @return array
*/
public function get_columns() {
$columns = array(
'sr_no' => '#',
'email' => __( 'Email', 'email-subscribers' ),
'status' => __( 'Status', 'email-subscribers' ),
'sent_at' => __( 'Sent Date', 'email-subscribers' ),
'opened_at' => __( 'Viewed Date', 'email-subscribers' ),
);
$columns = apply_filters( 'additional_es_campaign_report_columns', $columns );
return $columns;
}
/**
* Render a column when no column specific method exist.
*
* @param array $item
* @param string $column_name
*
* @return mixed
*/
public function column_default( $item, $column_name ) {
$column_data = ! empty( $item[ $column_name ] ) ? $item[ $column_name ] : '-';
return $column_data;
}
public function column_status( $item ) {
$status = ! empty( $item['status'] ) ? $item['status'] : ( ! empty( $item['es_deliver_sentstatus'] ) ? $item['es_deliver_sentstatus'] : '' );
switch ( $status ) {
case 'Sent':
?>
<svg class="h-6 w-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<title><?php echo esc_html__( 'Sent', 'email-subscribers' ); ?></title>
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
</svg>
<?php
break;
case 'In Queue':
?>
<svg class=" h-6 w-6 text-orange-400" fill="currentColor" viewBox="0 0 20 20">
<title><?php echo esc_html__( 'In Queue', 'email-subscribers' ); ?></title>
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/>
</svg>
<?php
break;
case 'Sending':
?>
<svg class=" h-6 w-6 text-yellow-400" fill="currentColor" viewBox="0 0 20 20">
<title><?php echo esc_html__( 'Sending', 'email-subscribers' ); ?></title>
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-8.707l-3-3a1 1 0 00-1.414 1.414L10.586 9H7a1 1 0 100 2h3.586l-1.293 1.293a1 1 0 101.414 1.414l3-3a1 1 0 000-1.414z" clip-rule="evenodd"/>
</svg>
<?php
break;
case 'Opened':
?>
<svg xmlns="http://www.w3.org/2000/svg" class="" width="28" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" style="color:green">
<title><?php echo esc_html__( 'Opened', 'email-subscribers' ); ?></title>
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M7 12l5 5l10 -10" />
<path d="M2 12l5 5m5 -5l5 -5" />
</svg>
<?php
break;
case 'Failed':
?>
<svg xmlns="http://www.w3.org/2000/svg" class="text-red-500" width="28" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<title><?php echo esc_html__( 'Failed', 'email-subscribers' ); ?></title>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<?php
break;
case '':
?>
<i class="dashicons dashicons-es dashicons-minus"/>
<?php
break;
default:
echo esc_html( $status );
break;
}
}
/**
* Get view activity table data
*/
public function get_activity_table_data( $return_count = false ) {
global $wpbd;
$hash = ig_es_get_request_data( 'list', '' );
$campaign_id = ig_es_get_request_data( 'campaign_id', '' );
$filter_by_status = ig_es_get_request_data( 'status', '' );
$filter_by_country = ig_es_get_request_data( 'country_code', '' );
$search = ig_es_get_request_data( 's' );
$orderby = ig_es_get_request_data( 'orderby' );
$order = ig_es_get_request_data( 'order', 'DESC' );
$page_number = ig_es_get_request_data( 'paged', 1 );
$message_id = 0;
$view_activity_data = array();
$delivery_table_exists = false;
$selects = array();
if ( ! empty( $hash ) ) {
$notification_data_from_hash = ES_DB_Mailing_Queue::get_notification_by_hash( $hash );
$campaign_id = $notification_data_from_hash['campaign_id'];
$message_id = $notification_data_from_hash['id'];
$delivery_table_exists = ES()->campaigns_db->table_exists( $wpbd->prefix . 'es_deliverreport' );
// We are assigning NULL values to sent_at and opened_at columns as actions tables have NULL values for these columns when no data is present in the column.
// Assigning NULL ensures sorting works as expected when both the tables are combined.
$queue_query = "SELECT queue.contact_id AS `contact_id`, queue.email AS `email`, 0 AS `type`, NULL AS `sent_at`, NULL AS `opened_at`, queue.status, '' AS `country`, '' AS `device`, '' AS `email_client`, '' AS `os`
FROM {$wpbd->prefix}ig_sending_queue AS queue
WHERE `mailing_queue_id` = %d AND `contact_id` NOT IN ( SELECT `contact_id` FROM {$wpbd->prefix}ig_actions WHERE campaign_id = %d AND message_id = %d )";
$delivery_query = $wpbd->prepare(
"SELECT
es_deliver_emailid AS `contact_id`,
es_deliver_emailmail AS `email`,
0 AS `type`,
UNIX_TIMESTAMP(es_deliver_sentdate) AS `sent_at`,
UNIX_TIMESTAMP(es_deliver_viewdate) AS `opened_at`,
es_deliver_sentstatus AS `status`,
'' AS `country`,
'' AS `device`,
'' AS `email_client`,
'' AS `os`
FROM {$wpbd->prefix}es_deliverreport WHERE es_deliver_sentguid = %s",
array( $hash )
);
$selects[] = $wpbd->prepare( $queue_query, $message_id, $campaign_id, $message_id );
}
$action_query = "SELECT
MAX(contacts.id) AS `contact_id`,
contacts.email AS `email`,
MAX(actions.type) AS `type`,
MAX(CASE WHEN actions.type = %d THEN actions.created_at END) AS `sent_at`,
MAX(CASE WHEN actions.type = %d THEN actions.created_at END) AS `opened_at`,
CASE WHEN MAX(actions.type) = %d THEN 'Sent' WHEN MAX(actions.type) = %d THEN 'Opened' END AS `status`,
MAX(actions.country) AS `country`,
MAX(actions.device) AS `device`,
MAX(actions.email_client) AS `email_client`,
MAX(actions.os) AS `os`
FROM {$wpbd->prefix}ig_actions AS actions
LEFT JOIN {$wpbd->prefix}ig_contacts AS contacts ON actions.contact_id = contacts.id
WHERE actions.campaign_id = %d AND actions.message_id = %d AND actions.type IN (%d, %d)
GROUP BY email";
$query_args = array(
IG_MESSAGE_SENT,
IG_MESSAGE_OPEN,
IG_MESSAGE_SENT,
IG_MESSAGE_OPEN,
$campaign_id,
$message_id,
IG_MESSAGE_SENT,
IG_MESSAGE_OPEN,
);
$selects[] = $wpbd->prepare( $action_query, $query_args );
if ( $return_count ) {
$notification_query = 'SELECT count(*) FROM ( ';
} else {
$notification_query = 'SELECT * FROM ( ';
}
$notification_query .= implode( ' UNION ALL ', $selects );
$notification_query .= ') AS `activity`';
$notification = ES()->campaigns_db->get( $campaign_id );
$total_email_sent = ES()->actions_db->get_count_based_on_id_type( $notification['id'], $message_id, IG_MESSAGE_SENT );
$email_viewed_count = ES()->actions_db->get_count_based_on_id_type( $notification['id'], $message_id, IG_MESSAGE_OPEN );
$notification_query .= ' WHERE 1';
$search_query = '';
if ( ! empty( $search ) ) {
$search_query = $wpbd->prepare( ' AND email LIKE %s', '%' . $wpbd->esc_like( $search ) . '%' );
}
$status_query = '';
if ( ! empty( $filter_by_status ) ) {
$status = 'not_opened' === $filter_by_status ? 'Sent' : 'Opened';
$status_query = $wpbd->prepare( ' AND `status` = %s', $status );
}
$country_query = '';
if ( ! empty( $filter_by_country ) ) {
$country_query = $wpbd->prepare( ' AND `country` = %s', $filter_by_country );
}
$order_by_query = '';
$offset = 0;
if ( ! $return_count ) {
if ( empty( $orderby ) ) {
// By default sort by opened_at and sent_at columns.
$orderby = "`opened_at` {$order}, `sent_at` {$order}";
} else {
$orderby = "{$orderby} {$order}";
}
$orderby = sanitize_sql_orderby( $orderby );
if ( $orderby ) {
$per_page = 100;
$offset = $page_number > 1 ? ( $page_number - 1 ) * $per_page : 0;
$order_by_query = " ORDER BY {$orderby} LIMIT {$offset}, {$per_page}";
}
}
$notification_query .= $search_query . $status_query . $country_query . $order_by_query;
if ( $return_count ) {
$count = $wpbd->get_var( $notification_query );
if ( empty( $count ) && $delivery_table_exists ) {
$count_query = 'SELECT count(*) FROM ( ' . $delivery_query . ' ) AS delivery_report WHERE 1';
$count_query .= $search_query . $status_query . $country_query . $order_by_query;
// If no results exists then check data into es_deliverreport table as earlier version were using this table.
$count = $wpbd->get_var(
$count_query
);
}
return $count;
} else {
$results = $wpbd->get_results( $notification_query, ARRAY_A );
// If no results exists then check data into es_deliverreport table as earlier version were using this table.
if ( empty( $results ) && $delivery_table_exists ) {
$delivery_query = 'SELECT * FROM ( ' . $delivery_query . ' ) AS delivery_report WHERE 1';
$delivery_query .= $search_query . $status_query . $country_query . $order_by_query;
$results = $wpbd->get_results(
$delivery_query,
ARRAY_A
);
}
$sr_no = $offset + 1;
if ( ! empty( $results ) ) {
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
$gmt_offset = ig_es_get_gmt_offset( true );
$format = $date_format . ' ' . $time_format;
foreach ( $results as $notification_action ) {
$contact_id = $notification_action['contact_id'];
$sent_at = '';
if ( ! empty( $notification_action['sent_at'] ) ) {
$sent_timestamp = (int) $notification_action['sent_at'];
$sent_timestamp += $gmt_offset;
$sent_at = ES_Common::convert_timestamp_to_date( $sent_timestamp, $format );
}
$opened_at = '';
if ( ! empty( $notification_action['opened_at'] ) ) {
$opened_timestamp = (int) $notification_action['opened_at'];
$opened_timestamp += $gmt_offset;
$opened_at = ES_Common::convert_timestamp_to_date( $opened_timestamp, $format );
}
$view_activity_data[ $contact_id ] = array(
'sr_no' => $sr_no++,
'email' => $notification_action['email'],
'opened_at' => $opened_at,
'sent_at' => $sent_at,
'status' => $notification_action['status'],
'country_flag' => '',
'device' => '',
'email_client' => '',
'os' => '',
);
$view_activity_data = apply_filters( 'additional_es_report_activity_data', $view_activity_data, $contact_id, $notification_action );
}
}
}
if ( ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
$insight = ig_es_get_request_data( 'insight', '' );
$_wpnonce = ig_es_get_request_data( '_wpnonce', '' );
if ( ( ES()->is_pro() || $insight ) && 0 !== $message_id ) {
do_action( 'ig_es_view_report_data', $hash );
}
?>
<div class="wrap">
<?php if ( ! ES()->is_pro() && ! $insight ) { ?>
<?php do_action( 'ig_es_view_report_data_lite', $hash ); ?>
<a href="?page=es_reports&action=view&list=<?php echo esc_attr( $hash ); ?>&_wpnonce=<?php echo esc_attr( $_wpnonce ); ?>&insight=true" class="float-right top-10 relative ig-es-title-button px-2 py-2 mx-2 -mt-2 ig-es-imp-button cursor-pointer"><?php esc_html_e( 'Campaign Analytics', 'email-subscribers' ); ?></a>
<?php } ?>
</div>
<div class="mt-2 mb-2 inline-block relative es-activity-viewed-count">
<span class="pt-3 pb-4 leading-5 tracking-wide text-gray-600"><?php echo esc_html( '(Viewed ' . number_format( $email_viewed_count ) . '/' . number_format( $total_email_sent ) . ')' ); ?>
</span>
</div>
<?php
}
return $view_activity_data;
}
/**
* Handling filtering and sorting for view activity table
*/
public function es_view_activity_report_sort_and_filter() {
$hash = ig_es_get_request_data( 'list', '' );
$campaign_id = ig_es_get_request_data( 'campaign_id', '' );
?>
<script type="text/javascript">
(function ($) {
$(document).ready(
function () {
$('#es_campaign_report').on('click', '.tablenav-pages a, .manage-column.sortable a, .manage-column.sorted a', function (e) {
e.preventDefault();
var query = this.search.substring(1);
var paged = list.__query( query, 'paged' ) || '1';
var order = list.__query( query, 'order' ) || 'desc';
var orderby = list.__query( query, 'orderby' ) || '';
$("input[name='order']").val(order);
$("input[name='orderby']").val(orderby);
$("input[name='paged']").val(paged);
check_filter_value();
});
$('#campaign-report-search-submit').on('click', function (e) {
e.preventDefault();
$("input[name='paged']").val(1);
check_filter_value();
});
});
list = {
/** AJAX call
*
* Send the call and replace table parts with updated version!
*
* @param object data The data to pass through AJAX
*/
update: function (data) {
$.ajax({
url: ajaxurl,
data: $.extend(
{
action: 'ajax_fetch_report_list',
security: ig_es_js_data.security
},
data
),
beforeSend: function(){
$('#es_campaign_report table.wp-list-table.widefat.fixed.striped.table-view-list.reports tbody').addClass('es-pulse-animation').css({'filter': 'blur(1px)', '-webkit-filter' : 'blur(1px)'});
},
success: function (response) {
var response = $.parseJSON(response);
if (response.rows.length)
$('#the-list').html(response.rows);
if (response.column_headers.length)
$('#es_campaign_report thead tr, #es_campaign_report tfoot tr').html(response.column_headers);
if (response.pagination.bottom.length)
$('.tablenav.bottom .tablenav-pages').html($(response.pagination.bottom).html());
if (response.pagination.top.length)
$('.tablenav.top .tablenav-pages').html($(response.pagination.top).html());
},
error: function (err) {
}
}).always(function(){
$('#es_campaign_report table.wp-list-table.widefat.fixed.striped.table-view-list.reports tbody').removeClass('es-pulse-animation').css({'filter': 'blur(0px)', '-webkit-filter' : 'blur(0px)'});
});
},
/**
* Filter the URL Query to extract variables
*
* @see http://css-tricks.com/snippets/javascript/get-url-variables/
*
* @param string query The URL query part containing the variables
* @param string variable Name of the variable we want to get
*
* @return string|boolean The variable value if available, false else.
*/
__query: function (query, variable) {
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable)
return pair[1];
}
return false;
},
}
function check_filter_value( filter_value = '' ){
var search = $('#campaign-reports-search-input').val();
var country_code = $('#ig_es_filter_activity_report_by_country').val();
var report_activity_status = $('#ig_es_filter_activity_report_by_status').val();
var order = $("input[name='order']").val();
var orderby = $("input[name='orderby']").val();
var paged = $("input[name='paged']").val();
data =
{
list : "<?php echo esc_html( $hash ); ?>",
campaign_id : <?php echo ( ! empty( $campaign_id ) ? esc_html( $campaign_id ) : 0 ); ?>,
order : order,
orderby : orderby,
paged : paged,
s : search,
country_code : country_code,
status : report_activity_status
};
list.update(data);
}
})(jQuery);
</script>
<?php
}
}

View File

@@ -0,0 +1,465 @@
<?php
if ( ! class_exists( 'ES_Campaign' ) ) {
/**
* Class to handle single campaign options
*
* @class ES_Campaign
*/
class ES_Campaign {
/**
* Campaign id
*
* @since 4.4.1
* @var int
*/
public $id;
/**
* Workflow slug
*
* @since 4.4.1
* @var string
*/
public $slug;
/**
* Workflow name(slug)
*
* @since 4.4.1
* @var string
*/
public $name;
/**
* Workflow trigger object
*
* @since 4.4.1
* @var ES_Workflow_Trigger
*/
public $type;
/**
* Workflow actions
*
* @since 4.4.1
* @var ES_Workflow_Actions[]
*/
public $parent_id;
/**
* Workflow data absctraction class object
*
* @since 4.4.1
* @var ES_Workflow_Data_Layer
*/
public $parent_type;
/**
* Workflow status
*
* @since 4.4.1
* @var integer
*/
public $subject;
/**
* Workflow trigger name
*
* @since 4.4.1
* @var string
*/
public $body;
/**
* Workflow trigger options
*
* @since 4.4.1
* @var array
*/
public $from_name;
/**
* Workflow rules
*
* @since 4.4.1
* @var array
*/
public $from_email;
/**
* Workflow meta data
*
* @since 4.4.1
* @var array
*/
public $reply_to_email;
/**
* Workflow priority
*
* @since 4.4.1
* @var integer
*/
public $categories;
/**
* Workflow priority
*
* @since 4.4.1
* @var integer
*/
public $list_ids;
/**
* Camapign base template id
*
* @since 4.4.1
* @var integer
*/
public $base_template_id;
/**
* Camapign meta
*
* @since 4.4.1
* @var integer
*/
public $meta;
/**
* Campaign creation date/time
*
* @since 4.4.1
* @var string
*/
public $created_at;
/**
* Campaign last update date/time
*
* @since 4.4.1
* @var string
*/
public $updated_at;
/**
* Flag to check whether valid campaign object or not
*
* @since 4.4.1
* @var bool
*/
public $exists = false;
/**
* Campaign status
*
* @since 4.4.1
* @var bool
*/
public $status = '';
/**
* Added Logger Context
*
* @since 4.2.0
* @var array
*/
public $logger_context = array(
'source' => 'ig_es_workflow',
);
/**
* Class constructor
*
* @param $post mixed (object or post ID)
*/
public function __construct( $campaign = null ) {
if ( is_numeric( $campaign ) ) {
// Get from id
$campaign = self::get_instance( $campaign );
}
if ( is_object( $campaign ) ) {
$this->exists = true;
$this->id = $campaign->id;
$this->slug = $campaign->slug;
$this->name = $campaign->name;
$this->type = $campaign->type;
$this->parent_id = $campaign->parent_id;
$this->parent_type = $campaign->parent_type;
$this->subject = $campaign->subject;
$this->body = $campaign->body;
$this->from_name = $campaign->from_name;
$this->from_email = $campaign->from_email;
$this->reply_to_email = $campaign->reply_to_email;
$this->categories = $campaign->categories;
$this->list_ids = $campaign->list_ids;
$this->base_template_id = $campaign->base_template_id;
$this->status = $campaign->status;
$this->meta = maybe_unserialize( $campaign->meta );
$this->created_at = $campaign->created_at;
$this->updated_at = $campaign->updated_at;
}
}
/**
* Retrieve ES_Workflow instance.
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param int $campaign_id Worfklow ID.
* @return ES_Workflow|false Worfklow object, false otherwise.
*/
public static function get_instance( $campaign_id = 0 ) {
$campaign_id = ES_Clean::id( $campaign_id );
if ( ! $campaign_id ) {
return false;
}
$_campaign = ES()->campaigns_db->get( $campaign_id, 'object' );
if ( ! $_campaign ) {
return false;
}
return new ES_Campaign( $_campaign );
}
/**
* Get workflow id
*
* @return int
*/
public function get_id() {
return $this->id ? ES_Clean::id( $this->id ) : 0;
}
/**
* Get workflow slug
*
* @return string
*/
public function get_slug() {
return $this->slug;
}
/**
* Get workflow name
*
* @return string
*/
public function get_name() {
return $this->name;
}
/**
* Get workflow type
*
* @return string
*/
public function get_type() {
return $this->type;
}
/**
* Get workflow parent_id
*
* @return string
*/
public function get_parent_id() {
return $this->parent_id;
}
/**
* Get workflow parent_type
*
* @return string
*/
public function get_parent_type() {
return $this->parent_type;
}
/**
* Get workflow subject
*
* @return string
*/
public function get_subject() {
return $this->subject;
}
/**
* Get workflow body
*
* @return string
*/
public function get_body() {
return $this->body;
}
/**
* Get workflow from_name
*
* @return string
*/
public function get_from_name() {
return $this->from_name;
}
/**
* Get workflow from_email
*
* @return string
*/
public function get_from_email() {
return $this->from_email;
}
/**
* Get workflow reply_to_email
*
* @return string
*/
public function get_reply_to_email() {
return $this->reply_to_email;
}
/**
* Get workflow categories
*
* @return string
*/
public function get_categories() {
return $this->categories;
}
/**
* Get workflow list_ids
*
* @return string
*/
public function get_list_ids() {
return $this->list_ids;
}
/**
* Get workflow base_template_id
*
* @return string
*/
public function get_base_template_id() {
return $this->base_template_id;
}
/**
* Get creation date/time of workflow.
*
* @return string
*/
public function get_date_created() {
return $this->created_at;
}
/**
* Get scheduled time to run workflow.
*
* @return string
*/
public function get_scheduled_time() {
return ES_Clean::string( $this->get_meta( 'scheduled_time' ) );
}
/**
* Is workflow active.
*
* @return bool
*/
public function is_active() {
if ( ! $this->exists ) {
return false;
}
return $this->get_status() === 'active';
}
/**
* Get workflow status.
*
* Possible statuses are active|inactive|trash
*
* @since 4.6
*
* @return string
*/
public function get_status() {
$status = $this->status;
if ( 1 === $status ) {
$status = 'active';
} elseif ( 0 === $status ) {
$status = 'inactive';
}
return $status;
}
/**
* Update worflow status.
*
* @param string $status active|inactive i.e 1|0
*/
public function update_status( $status ) {
if ( 'active' === $status ) {
$campaign_status = 1;
} elseif ( 'inactive' === $status ) {
$campaign_status = 0;
} else {
$campaign_status = $status;
}
$campaign_id = $this->get_id();
$status_updated = ES()->campaigns_db->update_status( $campaign_id, $campaign_status );
return $status_updated;
}
/**
* Get workflow meta data from meta key.
*
* @param $key
* @return mixed
*/
public function get_meta( $key ) {
return isset( $this->meta[ $key ] ) ? $this->meta[ $key ] : '';
}
/**
* Method to get edit url of a campaign
*
* @since 5.5.13
*
* @return string $edit_url Campaign edit URL
*/
public function get_edit_url() {
$id = $this->get_id();
$edit_url = admin_url( 'admin.php?page=es_newsletters' );
$edit_url = add_query_arg(
array(
'id' => $id,
'action' => 'edit',
),
$edit_url
);
return $edit_url;
}
}
}

View File

@@ -0,0 +1,679 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
class ES_Campaigns_Table extends ES_List_Table {
/**
* Class instance.
*
* @var ES_Campaigns_Table $instance
*/
public static $instance;
/**
* Number of campaigns to be shown on the page
*
* @since 4.2.1
* @var string
*/
public static $option_per_page = 'es_campaigns_per_page';
/**
* ES_DB_Campaigns object
*
* @since 4.3.4
* @var $db
*/
protected $db;
/**
* ES_Campaigns_Table constructor.
*
* @since 4.0
*/
public function __construct() {
parent::__construct(
array(
'singular' => __( 'Campaign', 'email-subscribers' ), // singular name of the listed records
'plural' => __( 'Campaign', 'email-subscribers' ), // plural name of the listed records
'ajax' => false, // does this table support ajax?
'screen' => 'es_campaigns',
)
);
$this->db = new ES_DB_Campaigns();
$this->init();
}
/**
* Get class instance.
*
* @since 4.7.8
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Add Screen Option
*
* @since 4.2.1
*/
public static function screen_options() {
$option = 'per_page';
$args = array(
'label' => __( 'Number of campaigns per page', 'email-subscribers' ),
'default' => 20,
'option' => self::$option_per_page,
);
add_screen_option( $option, $args );
}
/**
* Render Campaigns table
*
* @since 4.0
*/
public function render() {
?>
<div id="ig-es-campaign-dashboard"></div>
<?php
}
public function custom_admin_notice() {
$es_note_cat = ig_es_get_request_data( 'es_note_cat' );
if ( $es_note_cat ) {
echo '<div class="updated"><p>' . esc_html__( 'Notification Added Successfully!', 'email-subscribers' ) . '</p></div>';
}
}
/**
* Retrieve lists data from the database
*
* @param int $per_page
* @param int $page_number
*
* @return mixed
*/
public function get_lists( $per_page = 5, $page_number = 1, $do_count_only = false ) {
global $wpdb, $wpbd;
$order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
$order = ig_es_get_request_data( 'order' );
$search = ig_es_get_request_data( 's' );
$filter_by_campaign_type = ig_es_get_request_data( 'filter_by_campaign_type' );
$filter_by_campaign_status = ig_es_get_request_data( 'filter_by_campaign_status' );
if ( $do_count_only ) {
$sql = 'SELECT count(*) as total FROM ' . IG_CAMPAIGNS_TABLE;
} else {
$sql = 'SELECT * FROM ' . IG_CAMPAIGNS_TABLE;
}
$args = array();
$query = array();
$add_where_clause = true;
$query[] = "( deleted_at IS NULL OR deleted_at = '0000-00-00 00:00:00' )";
$query[] = " type != 'workflow_email'";
if ( ! empty( $search ) ) {
$query[] = ' name LIKE %s ';
$args[] = '%' . $wpdb->esc_like( $search ) . '%';
}
$query = apply_filters( 'ig_es_campaign_list_where_caluse', $query );
if ( $add_where_clause ) {
$sql .= ' WHERE ';
if ( count( $query ) > 0 ) {
$sql .= implode( ' AND ', $query );
if ( count( $args ) > 0 ) {
$sql = $wpbd->prepare( $sql, $args );
}
}
}
if ( ! empty( $filter_by_campaign_status ) || ( '0' === $filter_by_campaign_status ) ) {
if ( $add_where_clause ) {
$sql .= $wpdb->prepare( ' AND status = %s', $filter_by_campaign_status );
} else {
$sql .= $wpdb->prepare( ' WHERE status = %s', $filter_by_campaign_status );
}
}
if ( ! empty( $filter_by_campaign_type ) ) {
if ( $add_where_clause ) {
$sql .= $wpdb->prepare( ' AND type = %s', $filter_by_campaign_type );
} else {
$sql .= $wpdb->prepare( ' WHERE type = %s', $filter_by_campaign_type );
}
}
if ( ! $do_count_only ) {
$order = ! empty( $order ) ? strtolower( $order ) : 'desc';
$expected_order_values = array( 'asc', 'desc' );
if ( ! in_array( $order, $expected_order_values ) ) {
$order = 'desc';
}
$default_order_by = esc_sql( 'created_at' );
$expected_order_by_values = array( 'name', 'type', 'created_at' );
if ( ! in_array( $order_by, $expected_order_by_values ) ) {
$order_by_clause = " ORDER BY {$default_order_by} DESC";
} else {
$order_by = esc_sql( $order_by );
$order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
}
$sql .= $order_by_clause;
$sql .= " LIMIT $per_page";
$sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
$result = $wpbd->get_results( $sql, 'ARRAY_A' );
} else {
$result = $wpbd->get_var( $sql );
}
return $result;
}
/**
* Text Display when no items available
*
* @since 4.0
*/
public function no_items() {
esc_html_e( 'No Campaigns Found.', 'email-subscribers' );
}
/**
* Get Campaign statuses
*
* @param string $status
*
* @return array|mixed
*
* @since 4.3.6
*/
public function get_statuses( $status = '' ) {
$statuses = array(
IG_ES_CAMPAIGN_STATUS_IN_ACTIVE => __( 'In Active', 'email-subscribers' ),
IG_ES_CAMPAIGN_STATUS_ACTIVE => __( 'Active', 'email-subscribers' ),
IG_ES_CAMPAIGN_STATUS_SCHEDULED => __( 'Scheduled', 'email-subscribers' ),
IG_ES_CAMPAIGN_STATUS_QUEUED => __( 'Queued', 'email-subscribers' ),
IG_ES_CAMPAIGN_STATUS_PAUSED => __( 'Paused', 'email-subscribers' ),
IG_ES_CAMPAIGN_STATUS_FINISHED => __( 'Finished', 'email-subscribers' ),
);
// We are getting $status = 0 for "In Active".
// So, we can't check empty()
if ( '' != $status ) {
return $statuses[ $status ];
}
return $statuses;
}
/**
* Render a column when no column specific method exist.
*
* @param array $item
* @param string $column_name
*
* @return mixed
*
* @modified 4.4.4 Removed 'status' column switch case.
*/
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'list_ids':
if ( ! empty( $item[ $column_name ] ) ) {
$list_ids = explode( ',', $item[ $column_name ] );
return ES_Common::prepare_list_name_by_ids( $list_ids );
} else {
$type = isset( $item['type'] ) ? $item['type'] : '';
$list_ids = array();
if ( ! empty( $item['meta'] ) ) {
$list_ids = ES()->campaigns_db->get_list_ids( $item );
}
if ( $list_ids ) {
return ES_Common::prepare_list_name_by_ids( $list_ids );
} else {
return '';
}
}
break;
case 'created_at':
case 'updated_at':
return ! empty( $item[ $column_name ] ) ? ig_es_format_date_time( $item[ $column_name ] ) : '';
break;
case 'categories':
if ( ! empty( $item[ $column_name ] ) ) {
$campaign_type = $item['type'];
if ( IG_CAMPAIGN_TYPE_POST_NOTIFICATION === $campaign_type || IG_CAMPAIGN_TYPE_POST_DIGEST === $campaign_type ) {
$campaign_id = $item[ 'id' ];
if ( ES_Campaign_Controller::is_using_new_category_format( $campaign_id ) ) {
$categories = $item[ $column_name ];
$categories_str = trim( trim( $categories ), '##' );
$categories_array = explode( '##', $categories_str );
foreach ( $categories_array as $category ) {
$cat_cpts = explode( '|', $category );
foreach ( $cat_cpts as $cat_cpt ) {
list( $post_type, $cats ) = explode( ':', $cat_cpt );
if ( 'post' === $post_type ) {
if ( 'all' === $cats ) {
$categories = __( 'All', 'email-subscribers' );
} elseif ( 'none' === $cats ) {
$categories = __( 'None', 'email-subscribers' );
} else {
$cats = explode( ',', $cats );
$categories = array_map( array( 'ES_Common', 'convert_id_to_name' ), $cats );
$categories = trim( trim( implode( ', ', $categories ) ), ',' );
}
}
}
}
} else {
$categories = ES_Common::convert_categories_string_to_array( $item[ $column_name ], false );
if ( strpos( $item[ $column_name ], '{a}All{a}' ) ) {
$categories = __( 'All', 'email-subscribers' );
} elseif ( strpos( $item[ $column_name ], '{a}None{a}' ) ) {
$categories = __( 'None', 'email-subscribers' );
} else {
$categories = trim( trim( implode( ', ', $categories ) ), ',' );
}
}
return $categories;
} else {
return '-';
}
} else {
return '-';
}
break;
default:
return $item[ $column_name ];
}
}
/**
* Render the bulk edit checkbox
*
* @param array $item
*
* @return string
*/
public function column_cb( $item ) {
return sprintf(
'<input type="checkbox" name="campaigns[]" value="%s" />',
$item['id']
);
}
/**
* Method for name column
*
* @param array $item an array of DB data
*
* @return string
*/
public function column_name1( $item ) {
global $wpdb;
$actions = array();
$type = $item['type'];
$nonce = wp_create_nonce( 'es_post_notification' );
$template = get_post( $item['base_template_id'] );
$report = ES_DB_Mailing_Queue::get_notification_by_campaign_id( $item['id'] );
if ( 'newsletter' !== $type ) {
/*
if ( $template instanceof WP_Post ) {
$title = '<strong>' . $template->post_title . '</strong>';
} else {
$title = ! empty( $item['name'] ) ? $item['name'] : '';
}
*/
$title = ! empty( $item['name'] ) ? $item['name'] : '';
$slug = ( in_array( $item['type'], array( 'post_notification', 'post_digest' ) ) ) ? esc_attr( 'es_notifications' ) : 'es_' . $item['type'];
if ( 'workflow' === $type ) {
$actions ['edit'] = '<a href="?page=es_workflows&action=edit&id=' . absint( $item['parent_id'] ) . '&_wpnonce=' . $nonce . '" class="text-indigo-600">' . esc_html__( 'Edit', 'email-subscribers' ) . '</a>';
} else {
$actions ['edit'] = '<a href="?page=' . esc_attr( $slug ) . '&action=edit&list=' . absint( $item['id'] ) . '&_wpnonce=' . $nonce . '" class="text-indigo-600">' . esc_html__( 'Edit', 'email-subscribers' ) . '</a>';
}
if ( in_array( $type, array( 'post_notification', 'post_digest' ), true ) ) {
// Add reports link if there are any reports related to the post notification.
if ( ! empty( $report ) ) {
$actions['report'] = '<a href="?page=' . esc_attr( 'es_reports' ) . '&campaign_id=' . esc_attr( $item['id'] ) . '" class="text-indigo-600">' . esc_html__( 'Report', 'email-subscribers' ) . '</a>';
}
} elseif ( in_array( $type, array( 'sequence', 'workflow' ), true ) ) {
$actions['report'] = '<a href="?page=' . esc_attr( 'es_reports' ) . '&campaign_id=' . esc_attr( $item['id'] ) . '" class="text-indigo-600">' . esc_html__( 'Report', 'email-subscribers' ) . '</a>';
}
} else {
$title = $item['name'];
$slug = 'es_newsletters';
$status = $item['status'];
$broadcast_allowed_edit_statuses = array(
IG_ES_CAMPAIGN_STATUS_IN_ACTIVE, // Draft status.
IG_ES_CAMPAIGN_STATUS_SCHEDULED, // Scheduled status.
IG_ES_CAMPAIGN_STATUS_QUEUED, // Sending status.
IG_ES_CAMPAIGN_STATUS_PAUSED, // Paused status.
);
if ( in_array( $status, $broadcast_allowed_edit_statuses ) ) {
$actions ['edit'] = '<a href="?page=' . esc_attr( $slug ) . '&action=edit&list=' . absint( $item['id'] ) . '&_wpnonce=' . $nonce . '" class="text-indigo-600">' . esc_html__( 'Edit', 'email-subscribers' ) . '</a>';
}
$broadcast_allowed_report_statuses = array(
IG_ES_CAMPAIGN_STATUS_SCHEDULED,
IG_ES_CAMPAIGN_STATUS_QUEUED,
IG_ES_CAMPAIGN_STATUS_ACTIVE,
IG_ES_CAMPAIGN_STATUS_FINISHED,
IG_ES_CAMPAIGN_STATUS_PAUSED,
);
if ( in_array( $status, $broadcast_allowed_report_statuses ) && ! empty( $report ) ) {
$es_nonce = wp_create_nonce( 'es_notification' );
$actions['report'] = '<a href="?page=' . esc_attr( 'es_reports' ) . '&action=view&list=' . $report['hash'] . '&_wpnonce=" ' . $es_nonce . '" class="text-indigo-600">' . esc_html__( 'Report', 'email-subscribers' ) . '</a>';
}
}
$campaign_type = array( 'post_notification', 'post_digest' );
if ( ! in_array( $item['type'], $campaign_type ) ) {
$actions = apply_filters( 'ig_es_campaign_actions', $actions, $item );
}
if ( 'workflow' !== $item['type'] ) {
$actions['delete'] = '<a href="?page=' . esc_attr( 'es_campaigns' ) . '&action=delete&list=' . absint( $item['id'] ) . '&_wpnonce=' . $nonce . '" onclick="return checkDelete()">' . esc_html__( 'Delete', 'email-subscribers' ) . '</a>';
}
$title .= $this->row_actions( $actions );
return $title;
}
/**
* Method for campaign status HTML
*
* @return string $status_html Campaign status HTML.
*
* @since 4.4.4
*/
public function column_status_text( $item ) {
$campaign_id = ! empty( $item['id'] ) ? $item['id'] : 0;
$campaign_status = ! empty( $item['status'] ) ? (int) $item['status'] : 0;
$campaign_statuses = array(
IG_ES_CAMPAIGN_STATUS_ACTIVE,
IG_ES_CAMPAIGN_STATUS_IN_ACTIVE,
);
$campaign_type = '';
if ( ! empty( $campaign_id ) ) {
$campaign_type = ES()->campaigns_db->get_campaign_type_by_id( $campaign_id );
}
$status_text = '-';
if ( 'newsletter' !== $campaign_type && in_array( $campaign_status, $campaign_statuses, true ) ) {
switch ( $campaign_status ) {
case IG_ES_CAMPAIGN_STATUS_ACTIVE:
$status_text = __( 'Active', 'email-subscribers' );
break;
case IG_ES_CAMPAIGN_STATUS_IN_ACTIVE:
$status_text = __( 'Draft', 'email-subscribers' );
break;
}
} else {
switch ( $campaign_status ) {
case IG_ES_CAMPAIGN_STATUS_ACTIVE:
$notification = ES_DB_Mailing_Queue::get_notification_by_campaign_id( $campaign_id );
if ( ! empty( $notification ) ) {
$notification_status = $notification['status'];
if ( 'In Queue' === $notification_status ) {
$status_text = __( 'Scheduled', 'email-subscribers' );
} elseif ( 'Sending' === $notification_status ) {
$status_text = __( 'Sending', 'email-subscribers' );
} else {
$status_text = __( 'Sent', 'email-subscribers' );
}
}
break;
case IG_ES_CAMPAIGN_STATUS_IN_ACTIVE:
$status_text = __( 'Draft', 'email-subscribers' );
break;
case IG_ES_CAMPAIGN_STATUS_SCHEDULED:
$status_text = __( 'Scheduled', 'email-subscribers' );
break;
case IG_ES_CAMPAIGN_STATUS_QUEUED:
$status_text = __( 'Sending', 'email-subscribers' );
break;
case IG_ES_CAMPAIGN_STATUS_PAUSED:
$status_text = __( 'Paused', 'email-subscribers' );
break;
default:
$status_text = __( 'Sent', 'email-subscribers' );
break;
}
}
?>
<?php
return $status_text;
}
/**
* Associative array of columns
*
* @return array
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'name' => __( 'Name', 'email-subscribers' ),
'type' => __( 'Type', 'email-subscribers' ),
'list_ids' => __( 'List(s)', 'email-subscribers' ),
'categories' => __( 'Categories', 'email-subscribers' ),
'created_at' => __( 'Created', 'email-subscribers' ),
'status' => __( 'Status', 'email-subscribers' ),
);
return $columns;
}
/**
* Columns to make sortable.
*
* @return array
*/
public function get_sortable_columns() {
$sortable_columns = array(
// 'base_template_id' => array( 'base_template_id', true ),
// 'list_ids' => array( 'list_ids', true ),
// 'status' => array( 'status', true )
'name' => array( 'name', true ),
'type' => array( 'type', true ),
'created_at' => array( 'created_at', true ),
);
return $sortable_columns;
}
/**
* Returns an associative array containing the bulk action
*
* @return array
*/
public function get_bulk_actions() {
$actions = array(
'bulk_delete' => 'Delete',
);
return $actions;
}
/**
* Prepare search box
*
* @param string $text
* @param string $input_id
*
* @since 4.0.0
* @since 4.3.4 Added esc_attr()
*/
public function search_box( $text = '', $input_id = '' ) {
?>
<p class="search-box">
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_attr( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
<?php submit_button( __( 'Search Campaigns', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
</p>
<p class="search-box search-group-box box-ma10">
<?php $filter_by_status = ig_es_get_request_data( 'filter_by_campaign_status' ); ?>
<select name="filter_by_campaign_status" id="ig_es_filter_campaign_status_by_type">
<?php
$allowedtags = ig_es_allowed_html_tags_in_esc();
add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
$campaign_types = ES_Common::prepare_campaign_statuses_dropdown_options( $filter_by_status, __( 'All Statuses', 'email-subscribers' ) );
echo wp_kses( $campaign_types, $allowedtags );
?>
</select>
</p>
<p class="search-box search-group-box box-ma10">
<?php $filter_by_campaign_type = ig_es_get_request_data( 'filter_by_campaign_type' ); ?>
<select name="filter_by_campaign_type" id="ig_es_filter_campaign_type">
<?php
$campaign_statuses = ES_Common::prepare_campaign_type_dropdown_options( $filter_by_campaign_type, __( 'All Type', 'email-subscribers' ) );
echo wp_kses( $campaign_statuses, $allowedtags );
?>
</select>
</p>
<?php
}
/**
* Handles data query and filter, sorting, and pagination.
*/
public function prepare_items() {
$this->_column_headers = $this->get_column_info();
/** Process bulk action */
$this->process_bulk_action();
// Note: Disable Search box for now.
$search = ig_es_get_request_data( 's' );
$this->search_box( $search, 'notification-search-input' );
$per_page = $this->get_items_per_page( self::$option_per_page, 25 );
$current_page = $this->get_pagenum();
$total_items = $this->get_lists( 0, 0, true );
$this->set_pagination_args(
array(
'total_items' => $total_items, // We have to calculate the total number of items
'per_page' => $per_page, // We have to determine how many items to show on a page
)
);
$this->items = $this->get_lists( $per_page, $current_page );
}
public function process_bulk_action() {
$campaign_id = ig_es_get_request_data( 'list' );
if ( 'delete' === $this->current_action() ) {
// In our file that handles the request, verify the nonce.
$nonce = ig_es_get_request_data( '_wpnonce' );
if ( ! wp_verify_nonce( $nonce, 'es_post_notification' ) ) {
$message = __( 'You are not allowed to delete campaign.', 'email-subscribers' );
$status = 'error';
} else {
$this->db->delete_campaigns( $campaign_id );
$message = __( 'Campaign deleted successfully!', 'email-subscribers' );
$status = 'success';
}
ES_Common::show_message( $message, $status );
}
$campaign_action = $this->current_action();
do_action( 'ig_es_campaign_action', $campaign_id, $campaign_action );
$action = ig_es_get_request_data( 'action' );
$action2 = ig_es_get_request_data( 'action2' );
// If the delete bulk action is triggered
if ( ( 'bulk_delete' === $action ) || ( 'bulk_delete' === $action2 ) ) {
$ids = ig_es_get_request_data( 'campaigns' );
if ( is_array( $ids ) && count( $ids ) > 0 ) {
// Delete multiple Campaigns
$this->db->delete_campaigns( $ids );
$message = __( 'Campaign(s) deleted successfully!', 'email-subscribers' );
ES_Common::show_message( $message );
} else {
$message = __( 'Please select campaign(s) to delete.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
}
}
}
}

View File

@@ -0,0 +1,51 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_Compatibility' ) ) {
/**
* Make ES Compatible with other plugins
*
* Class ES_Compatibility
*
* @since 4.3.9
*/
class ES_Compatibility {
/**
* ES_Compatibility constructor.
*
* @since 4.3.9
*/
public function __construct() {
add_filter( 'wp_mail_smtp_providers_mailer_get_body', array( $this, 'wp_mail_smtp_modify_header' ), 10, 2 );
}
/**
* Outlook require X-Return-Path instead of Return-Path as a header
* So,we can handle it using 'wp_mail_smtp_providers_mailer_get_body'
* filter of WP Mail SMTP plugin.
*
* @param $body
* @param $mailer
*
* @return mixed
*
* @since 4.3.9
*/
public function wp_mail_smtp_modify_header( $body, $mailer ) {
if ( 'outlook' === $mailer ) {
$headers = $body['message']['internetMessageHeaders'];
foreach ( $headers as $key => $header ) {
if ( 'Return-Path' === $header['name'] ) {
$body['message']['internetMessageHeaders'][ $key ]['name'] = 'X-Return-Path';
}
}
}
return $body;
}
}
}

View File

@@ -0,0 +1,735 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Cron {
/**
* ES_Cron constructor.
*
* @since 4.0.0
* @since 4.3.5 Added ig_es_after_settings_save action
*/
public function __construct() {
add_action( 'wp_loaded', array( &$this, 'init' ), 1 );
add_filter( 'cron_schedules', array( &$this, 'cron_schedules' ) );
add_action( 'ig_es_plugin_deactivate', array( &$this, 'clear' ) );
add_action( 'ig_es_after_settings_save', array( &$this, 'reschedule' ) );
}
/**
* Initialize Cron
*
* @since 4.3.1
*/
public function init() {
add_action( 'ig_es_cron', array( &$this, 'hourly' ) );
add_action( 'ig_es_cron_worker', array( &$this, 'handler' ), - 1 );
if ( ! wp_next_scheduled( 'ig_es_cron' ) ) {
$this->update( true );
}
$this->handle_cron_request();
$this->handle_data_request();
}
/**
* Schedule/ Clear Cronjob
*
* @param bool $hourly_only
*
* @return bool
*
* @since 4.3.1
*/
public function update( $hourly_only = false ) {
// Schedule Main Cron
if ( ! wp_next_scheduled( 'ig_es_cron' ) ) {
wp_schedule_event( strtotime( 'midnight' ) - 300, 'hourly', 'ig_es_cron' );
return true;
} elseif ( $hourly_only ) {
return false;
}
// Don't want to use WP_CRON?
if ( ! $this->is_wp_cron_enable() ) {
$this->clear();
return true;
}
$this->schedule();
return false;
}
/**
* Is WP Cron enable?
*
* @return bool
*
* @since 4.3.5
*/
public function is_wp_cron_enable() {
$ig_es_disable_wp_cron = get_option( 'ig_es_disable_wp_cron', 'no' );
// Don't want to use WP_CRON?
if ( 'yes' === $ig_es_disable_wp_cron ) {
return false;
}
return true;
}
/**
* Reschedule Crons
*
* @since 4.3.5
*/
public function reschedule() {
$this->clear();
if ( $this->is_wp_cron_enable() ) {
$this->schedule();
}
}
/**
* Update Crons every hour
*
* @since 4.3.1
*/
public function hourly() {
$this->update();
}
/**
* Schedule Events if it's not already scheduled
*
* @since 4.3.1
*/
public function schedule() {
global $ig_es_tracker;
$sending_service = new ES_Service_Email_Sending();
// Add worker only once
if ( ! wp_next_scheduled( 'ig_es_cron_auto_responder' ) ) {
wp_schedule_event( floor( time() / 300 ) * 300 - 120, 'ig_es_cron_interval', 'ig_es_cron_auto_responder' );
}
if ( ! wp_next_scheduled( 'ig_es_cron_worker' ) ) {
wp_schedule_event( floor( time() / 300 ) * 300, 'ig_es_cron_interval', 'ig_es_cron_worker' );
}
if ( ES_Service_Email_Sending::opted_for_sending_service() ) {
$sending_service->schedule_ess_cron();
}
if ( ES()->is_pro() ) {
if ( ! wp_next_scheduled('ig_es_calculate_engagement_score')) {
$local_time = 'midnight';
$timestamp = strtotime( $local_time ) - ( get_option('gmt_offset') * HOUR_IN_SECONDS );
wp_schedule_event( $timestamp , 'daily', 'ig_es_calculate_engagement_score');
}
if ( 'yes' === get_option( 'ig_es_enable_bounce_handling_feature', 'yes' ) ) {
if ( ! wp_next_scheduled( 'ig_es_bounce_handler_cron_action' ) ) {
wp_schedule_event( time(), 'daily', 'ig_es_bounce_handler_cron_action', array() );
}
}
$is_woocommerce_active = $ig_es_tracker::is_plugin_activated( 'woocommerce/woocommerce.php' );
if ( $is_woocommerce_active ) {
if ( IG_ES_Abandoned_Cart_Options::is_cart_tracking_enabled() ) {
if ( ! wp_next_scheduled( 'ig_es_wc_abandoned_cart_worker' ) ) {
wp_schedule_event( floor( time() / 300 ) * 300, 'ig_es_two_minutes', 'ig_es_wc_abandoned_cart_worker' );
}
}
// Cron job to detect WooCommerce products which are on sale.
if ( ! wp_next_scheduled( 'ig_es_wc_products_on_sale_worker' ) ) {
wp_schedule_event( floor( time() / 300 ) * 300, 'ig_es_fifteen_minutes', 'ig_es_wc_products_on_sale_worker' );
}
}
$es_services = ES()->get_es_services();
if ( ! empty( $es_services ) && in_array( 'list_cleanup', $es_services, true ) ) {
$list_cleanup_cron_scheduled = wp_next_scheduled( 'ig_es_list_cleanup_worker' );
if ( ! $list_cleanup_cron_scheduled ) {
wp_schedule_event( floor( time() / 300 ) * 300, 'ig_es_monthly_interval', 'ig_es_list_cleanup_worker' );
}
}
}
}
/**
* Clear all ES Cronjob
*
* @since 4.3.1
*/
public function clear() {
wp_clear_scheduled_hook( 'ig_es_cron' );
wp_clear_scheduled_hook( 'ig_es_cron_worker' );
wp_clear_scheduled_hook( 'ig_es_cron_auto_responder' );
$cron_url = $this->url();
if ( ! empty( $cron_url ) ) {
parse_str( $cron_url, $output );
$guid = $output['guid'];
wp_clear_scheduled_hook( 'ig_es_cron_fifteen_mins', array( 'cron', $guid ) );
}
}
/**
* Lock Cron to avoid multiple execution of a cron
*
* @param int $key
*
* @return bool
*
* @since 4.3.1
*/
public function lock( $key = 0 ) {
$process_id = get_option( 'ig_es_cron_lock_' . $key, false );
if ( $process_id && $this->is_locked( $key ) ) {
return $process_id;
}
// On some hosts getmypid is disabled due to security reasons.
if ( function_exists( 'getmypid' ) ) {
$process_id = @getmypid();
} else {
$process_id = wp_rand();
}
update_option( 'ig_es_cron_lock_' . $key, $process_id, false );
return true;
}
/**
* Unlock Cron
*
* @param int $key
*
* @since 4.3.1
*/
public function unlock( $key = 0 ) {
update_option( 'ig_es_cron_lock_' . $key, false, false );
}
/**
* Should Unlock Cron?
*
* @param bool $force
*
* @return bool
*
* @since 4.3.3
*/
public function should_unlock( $force = false ) {
if ( $force ) {
return true;
}
$cron_last_hit = $this->get_last_hit();
// Initially we don't have timetamp data. So, set as 900 to unlock cron lock
$time_lapsed = isset( $cron_last_hit['timestamp'] ) ? ( round( time() - $cron_last_hit['timestamp'] ) ) : 900;
return $time_lapsed > ( 10 * MINUTE_IN_SECONDS );
}
/**
* Check If Cron Locked
*
* @param $key
*
* @return bool
*
* @since 4.3.1
*/
public function is_locked( $key = 0 ) {
global $wpdb;
$lock = 'ig_es_cron_lock_' . $key . '%';
$res = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}options WHERE option_name LIKE %s AND option_value != ''", $lock ) );
return ! ! $res;
}
/**
* Set interval for Email Subscribers Cronjob
*
* @return mixed
*
* @since 4.3.1
* @since 4.3.2 Changed name from filter_cron_schedules to cron_schedules
*/
public function cron_schedules( $schedules = array() ) {
$es_schedules = array(
'ig_es_cron_interval' => array(
'interval' => $this->get_cron_interval(),
'display' => __( 'Icegram Express Cronjob Interval', 'email-subscribers' ),
),
'ig_es_two_minutes' => array(
'interval' => 2 * MINUTE_IN_SECONDS,
'display' => __( 'Two minutes', 'email-subscribers' ),
),
'ig_es_fifteen_minutes' => array(
'interval' => 15 * MINUTE_IN_SECONDS,
'display' => __( 'Fifteen minutes', 'email-subscribers' ),
),
'ig_es_monthly_interval' => array(
'interval' => 30 * DAY_IN_SECONDS,
'display' => __( 'Monthly', 'email-subscribers' ),
),
);
$schedules = array_merge( $schedules, $es_schedules );
return $schedules;
}
/**
* Get Cron Interval
*
* @return int
*
* @since 4.3.5
*/
public function get_cron_interval() {
$cron_interval = (int) get_option( 'ig_es_cron_interval', IG_ES_CRON_INTERVAL );
if ( $cron_interval <= 0 ) {
$cron_interval = IG_ES_CRON_INTERVAL;
}
return $cron_interval;
}
/**
* Get available cron intervals
*
* @return array
*
* @since 4.3.5
*/
public function cron_intervals() {
return array(
600 => __( '10 minutes', 'email-subscribers' ),
900 => __( '15 minutes', 'email-subscribers' ),
1200 => __( '20 minutes', 'email-subscribers' ),
1500 => __( '25 minutes', 'email-subscribers' ),
1800 => __( '30 minutes', 'email-subscribers' ),
);
}
/**
* Get Cron URL
*
* @param bool $self
* @param bool $pro
* @param string $campaign_hash
*
* @return mixed|string|void
*
* @since 4.3.1
*/
public function url( $self = false, $pro = false, $campaign_hash = '' ) {
$cron_url = get_option( 'ig_es_cronurl', '' );
$result = array();
if ( ! empty( $cron_url ) ) {
parse_str( $cron_url, $result );
}
// Adding site url with a trailing slash
$site_url = trailingslashit( site_url() );
$cron_url = add_query_arg( 'es', 'cron', $site_url );
if ( empty( $result['guid'] ) ) {
$guid = ES_Common::generate_guid();
} else {
$guid = $result['guid'];
}
$cron_url = add_query_arg( 'guid', $guid, $cron_url );
update_option( 'ig_es_cronurl', $cron_url );
if ( ! empty( $campaign_hash ) ) {
$cron_url = add_query_arg( 'campaign_hash', $campaign_hash, $cron_url );
}
if ( $self ) {
$cron_url = add_query_arg( 'self', true, $cron_url );
$nonce = wp_create_nonce( 'ig_es_self_cron' );
$cron_url = add_query_arg( '_wpnonce', $nonce, $cron_url );
}
if ( $pro ) {
$cron_url = add_query_arg( 'es_pro', true, $cron_url );
}
return $cron_url;
}
/**
* Set Cron Last Hit data
*
* @return bool
*
* @since 4.3.3
*
* @modify 5.4.5
*/
public function set_last_hit() {
$last_hit = get_option( 'ig_es_cron_last_hit', array() );
$last_hit['timestamp'] = time();
if ( isset( $_SERVER['HTTP_X_ES_EMAIL_SENDING_LIMIT'] ) ) {
$last_hit['icegram_timestamp'] = time();
}
return update_option( 'ig_es_cron_last_hit', $last_hit );
}
/**
* Get Cron Last Hit data
*
* @return mixed|void
*
* @since 4.3.3
*/
public function get_last_hit() {
return get_option( 'ig_es_cron_last_hit', array() );
}
/**
* Handler
*
* @return bool
*
* @since 4.3.1
*/
public function handler() {
if ( defined( 'IG_ES_DOING_CRON' ) || defined( 'DOING_AJAX' ) || defined( 'DOING_AUTOSAVE' ) || defined( 'WP_INSTALLING' ) || defined( 'MAILSTER_DO_UPDATE' ) ) {
return false;
}
define( 'IG_ES_DOING_CRON', microtime( true ) );
register_shutdown_function( array( &$this, 'shutdown' ) );
}
/**
* Handle Shutdown event
*
* @since 4.3.1
*/
public function shutdown() {
if ( ! defined( 'IG_ES_DOING_CRON' ) ) {
return;
}
// Unlock Cron Lock
$this->unlock();
}
/**
* Handle Cron Request
*
* @since 4.0.0
*
* @modify 5.4.5.
*/
public function handle_cron_request() {
$execution_start_time = microtime( true );
$es_request = ig_es_get_request_data( 'es' );
$guid = ig_es_get_request_data( 'guid' );
// It's not a cron request . Say Goodbye!
if ( 'cron' !== $es_request ) {
return;
}
$self = ig_es_get_request_data( 'self', 0 );
$verified_self = false;
if ( 1 == $self && wp_verify_nonce( ig_es_get_request_data( '_wpnonce' ), 'ig_es_self_cron' ) ) {
$verified_self = true;
}
if ( 0 == $self || $verified_self ) {
if ( ! empty( $guid ) ) {
$response = array(
'status' => 'SUCCESS',
'es_remaining_email_count' => 100,
);
$es_process_request = true;
// filter request
$es_process_request = apply_filters( 'ig_es_email_sending_limit', $es_process_request );
if ( true === $es_process_request ) {
$security1 = strlen( $guid );
$es_c_cronguid_noslash = str_replace( '-', '', $guid );
$security2 = strlen( $es_c_cronguid_noslash );
if ( 34 == $security1 && 30 == $security2 ) {
if ( ! preg_match( '/[^a-z]/', $es_c_cronguid_noslash ) ) {
$cron_url = ES()->cron->url();
parse_str( $cron_url, $output );
// Now, all check pass.
if ( $guid === $output['guid'] ) {
// Should I unlock cron?
if ( $this->should_unlock( $verified_self ) ) {
$this->unlock();
}
if ( ! $this->is_locked() ) {
// Set Last Hit time.
$this->set_last_hit();
// Release WP_CRON if it should
if ( wp_next_scheduled( 'ig_es_cron' ) - $execution_start_time < 0 ) {
spawn_cron();
}
// Lock Cron to avoid duplicate
$this->lock();
// Queue Auto Responder
do_action( 'ig_es_cron_auto_responder' );
// Worker
do_action( 'ig_es_cron_worker' );
$response['total_emails_sent'] = get_transient( 'ig_es_total_emails_sent' );
$response['es_remaining_email_count'] = get_transient( 'ig_es_remaining_email_count' );
$response['message'] = 'EMAILS_SENT';
$response['status'] = 'SUCCESS';
// Unlock it.
$this->unlock();
} else {
$response['status'] = 'ERROR';
$response['message'] = 'CRON_LOCK_ENABLED';
}
} else {
$self = false;
$response['status'] = 'ERROR';
$response['message'] = 'CRON_GUID_DOES_NOT_MATCH';
}
} else {
$self = false;
$response['status'] = 'ERROR';
$response['message'] = 'CRON_GUID_PATTERN_DOES_NOT_MATCH';
}
} else {
$self = false;
$response['status'] = 'ERROR';
$response['message'] = 'INVALID_CRON_GUID';
}
} else {
$self = false;
$response['status'] = 'ERROR';
$response['message'] = 'DO_NOT_PROCESS_REQUEST';
}
} else {
$self = false;
$response['status'] = 'ERROR';
$response['message'] = 'EMPTY_CRON_GUID';
}
} else {
$response['es_remaining_email_count'] = 0;
$response['message'] = 'PLEASE_TRY_AGAIN_LATER';
$response['status'] = 'ERROR';
}
if ( $self ) {
$total_emails_sent = ! empty( $response['total_emails_sent'] ) ? $response['total_emails_sent'] : 0;
$status = ! empty( $response['status'] ) ? $response['status'] : 'ERROR';
$total_emails_to_be_sent = ! empty( $response['es_remaining_email_count'] ) ? $response['es_remaining_email_count'] : 0;
$cron_url = ES()->cron->url( true );
if ( 'SUCCESS' === $status ) {
$message = __( sprintf( 'Email(s) sent successfully!' ), 'email-subscribers' );
} else {
$message = $this->get_status_messages( $response['message'] );
}
include ES_PLUGIN_DIR . 'lite/public/partials/cron-message.php';
die();
} else {
echo json_encode( $response );
die();
}
}
/**
* Handle Data Request
*
* @since 4.6.6
*/
public function handle_data_request() {
$es_request = ig_es_get_request_data( 'es' );
// It's not a cron request . Say Goodbye!
if ('get_info' !== $es_request ) {
return;
}
$guid = ig_es_get_request_data( 'guid' );
$is_valid_request = $this->is_valid_request( $guid );
$response = array();
if ( $is_valid_request ) {
$allow_tracking = apply_filters( 'ig_es_allow_tracking', '' );
if ( 'yes' === $allow_tracking ) {
/*
* Trial start date
* Total # Contacts they have
* Total # lists they have
* Some of ES settings like enable track opens, track clicks etc
* Uninstall Date
*/
$response = apply_filters( 'ig_es_tracking_data', array() );
}
}
echo json_encode( $response );
die();
}
/**
* Get Status Message
*
* @param string $message
*
* @return mixed|string
*
* @since 4.0.0
*/
public function get_status_messages( $message = '' ) {
if ( empty( $message ) ) {
return '';
}
$status_messages = array(
'EMAILS_SENT' => __( 'Emails sent successfully!', 'email-subscribers' ),
'EMAILS_NOT_FOUND' => __( 'Emails not found.', 'email-subscribers' ),
'NOTIFICATION_NOT_FOUND' => __( 'No notifications found to send.', 'email-subscribers' ),
'CRON_GUID_DOES_NOT_MATCH' => __( 'Invalid GUID.', 'email-subscribers' ),
'CRON_GUID_PATTERN_DOES_NOT_MATCH' => __( 'Invalid GUID.', 'email-subscribers' ),
'INVALID_CRON_GUID' => __( 'Invalid GUID.', 'email-subscribers' ),
'DO_NOT_PROCESS_REQUEST' => __( 'Not allowed to process request.', 'email-subscribers' ),
'EMPTY_CRON_GUID' => __( 'GUID is empty.', 'email-subscribers' ),
'PLEASE_TRY_AGAIN_LATER' => __( 'Please try after sometime.', 'email-subscribers' ),
'EMAIL_SENDING_LIMIT_EXCEEDED' => __( 'You have hit your hourly email sending limit. Please try after sometime.', 'email-subscribers' ),
'CRON_LOCK_ENABLED' => __( 'Cron lock enabled. Please try after sometime.', 'email-subscribers' ),
);
$message_text = ! empty( $status_messages[ $message ] ) ? $status_messages[ $message ] : '';
return $message_text;
}
/**
* Is valid request
*
* @param string $guid
*
* @return bool
*
* @since 4.6.6
*/
public function is_valid_request( $guid = '' ) {
$security1 = strlen( $guid );
$es_c_cronguid_noslash = str_replace( '-', '', $guid );
$security2 = strlen( $es_c_cronguid_noslash );
if ( 34 == $security1 && 30 == $security2 ) {
if ( ! preg_match( '/[^a-z]/', $es_c_cronguid_noslash ) ) {
$cron_guid = $this->get_cron_guid();
// Now, all check pass.
if ( ! empty( $cron_guid ) && $guid === $cron_guid ) {
return true;
}
}
}
return false;
}
/**
* Get cron guid
*
* @return string $guid
*
* @since 4.7.7
*/
public function get_cron_guid() {
$cron_url = ES()->cron->url();
parse_str( $cron_url, $result );
$guid = ! empty( $result['guid'] ) ? $result['guid'] : '';
return $guid;
}
/**
* Method to get list of cron jobs being used in the plugin
*
* @return array $es_cron_jobs List of cron jobs used in the plugin
*
* @since 4.6.4
*/
public function get_cron_jobs_list() {
$es_cron_jobs = array(
'ig_es_cron',
'ig_es_cron_worker',
'ig_es_cron_auto_responder',
);
return $es_cron_jobs;
}
}

View File

@@ -0,0 +1,192 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Drag_And_Drop_Editor {
public static $instance;
public function __construct() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
}
public static function is_dnd_editor_page() {
$is_dnd_editor_page = false;
if ( ES()->is_es_admin_screen() ) {
$current_page = ig_es_get_request_data( 'page' );
$edit_campaign_pages = array(
'es_notifications',
'es_newsletters',
'es_campaigns'
);
$is_edit_campaign_page = in_array( $current_page, $edit_campaign_pages, true );
if ( $is_edit_campaign_page ) {
$is_dnd_editor_page = true;
} else {
if ( 'es_forms' === $current_page ) {
$action = ig_es_get_request_data( 'action' );
$is_new_form = 'new' === $action;
if ( $is_new_form ) {
$is_dnd_editor_page = true;
} else {
$form_id = ig_es_get_request_data( 'form' );
if ( ! empty( $form_id ) ) {
$form_data = ES()->forms_db->get( $form_id );
$settings_data = maybe_unserialize( $form_data['settings'] );
$editor_type = ! empty( $settings_data['editor_type'] ) ? $settings_data['editor_type'] : '';
$is_dnd_editor_page = IG_ES_DRAG_AND_DROP_EDITOR === $editor_type;
}
}
} elseif ( 'es_template' === $current_page ) {
$action = ig_es_get_request_data( 'action' );
$is_new_template = 'new' === $action;
if ( $is_new_template ) {
$is_dnd_editor_page = true;
} else {
$template_id = ig_es_get_request_data( 'id' );
if ( ! empty( $template_id ) ) {
$editor_type = get_post_meta( $template_id, 'es_editor_type', true );
$is_dnd_editor_page = IG_ES_DRAG_AND_DROP_EDITOR === $editor_type;
}
}
}
}
}
return $is_dnd_editor_page;
}
public function enqueue_scripts() {
if ( ! self::is_dnd_editor_page() ) {
return;
}
$current_page = ig_es_get_request_data( 'page' );
//Only for development - this branch only
if ( defined( 'IG_ES_DEV_MODE' ) && IG_ES_DEV_MODE ) {
wp_register_script( 'es_editor_js', 'http://localhost:9000/main.js', array(), time(), true );
} else {
$js_file_name = '';
if ( 'es_forms' === $current_page) {
//TODO: Change this when form UI is updated with new UI
$js_file_name = 'form-editor.js';
} else {
$js_file_name = 'editor.js';
}
wp_register_script( 'es_editor_js', ES_PLUGIN_URL . 'lite/admin/js/' . $js_file_name, array( ), ES_PLUGIN_VERSION, true );
}
if ( 'es_forms' === $current_page ) {
$lists = ES()->lists_db->get_lists();
//Get the site tags for DND editor
$campaign_admin = ES_Campaign_Admin::get_instance();
$site_tags = $campaign_admin->get_dnd_site_tags();
$form_editor_data = array(
'site_url' => home_url(),
'siteTags'=>$site_tags,
'lists' => $lists,
'i18n' => array(
'no_list_selected_message' => __( 'Please select list(s) in which contact will be subscribed.', 'email-subscribers' ),
),
);
$form_editor_data = apply_filters( 'ig_es_form_editor_data', $form_editor_data );
wp_localize_script( 'es_editor_js', 'ig_es_form_editor_data', $form_editor_data );
} else {
$campaign_admin = ES_Campaign_Admin::get_instance();
$campaign_tags = $campaign_admin->get_dnd_campaign_tags();
$subscriber_tags = $campaign_admin->get_dnd_subscriber_tags();
$site_tags = $campaign_admin->get_dnd_site_tags();
$campaign_editor_data = array(
'classicEditor' => IG_ES_CLASSIC_EDITOR,
'dndEditor' => IG_ES_DRAG_AND_DROP_EDITOR,
'postTags' => $campaign_tags['post_notification'],
'subscriberTags' => $subscriber_tags,
'siteTags' => $site_tags,
'isPro' => ES()->is_pro(),
'plugin_url' => ES_PLUGIN_URL,
'i18n' => array(
'survey_block_heading_text' => __( 'Happy with our products and services?', 'email-subscribers' ),
'survey_block_default_thank_you_text' => __( 'Thank you for your response! Your feedback is highly appreciated.', 'email-subscribers' ),
'survey_type_field_label' => __( 'Survey type', 'email-subscribers' ),
'survey_message_field_label' => __( 'Survey message', 'email-subscribers' ),
),
);
$campaign_editor_data = apply_filters( 'ig_es_campaign_editor_data', $campaign_editor_data );
wp_localize_script( 'es_editor_js', 'ig_es_campaign_editor_data', $campaign_editor_data );
}
wp_enqueue_script( 'es_editor_js' );
wp_enqueue_media();
}
/**
* Register the stylesheets for the admin area.
*
* @since 4.0
*/
public function enqueue_styles() {
if ( ! self::is_dnd_editor_page() ) {
return;
}
if ( defined( 'IG_ES_DEV_MODE' ) && IG_ES_DEV_MODE ) {
wp_enqueue_style( 'es_editor_css', 'http://localhost:9000/main.css', array(), time(), 'all' );
} else {
$css_file_name = '';
$current_page = ig_es_get_request_data('page');
if ( 'es_forms' === $current_page) {
//TODO: Change this when form UI is updated with new UI
$css_file_name = 'form-editor.css';
} else {
$css_file_name = 'editor.css';
}
wp_enqueue_style( 'es_editor_css', ES_PLUGIN_URL . 'lite/admin/css/' . $css_file_name, array(), ES_PLUGIN_VERSION, 'all' );
}
}
public function show_editor( $editor_args = array() ) {
$editor_attributes = ! empty( $editor_args['attributes'] ) ? $editor_args['attributes'] : array();
?>
<div id="ig-es-dnd-builder"
<?php
if ( ! empty( $editor_attributes ) ) :
foreach ( $editor_attributes as $arg_key => $arg_value ) :
echo esc_attr( $arg_key ) . '="' . esc_attr( $arg_value ) . '" ';
endforeach;
endif;
?>
>
</div>
<?php
}
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}
ES_Drag_And_Drop_Editor::get_instance();

View File

@@ -0,0 +1,446 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* CSV Exporter bootstrap file
*/
class Export_Subscribers {
/**
* Constructor
*/
public function __construct() {
$report = ig_es_get_request_data( 'report' );
$status = ig_es_get_request_data( 'status' );
$link_id = ig_es_get_request_data( 'link_id' );
$campaign_id = ig_es_get_request_data( 'campaign_id' );
$can_access = ES_Common::ig_es_can_access( 'audience' );
$can_access_campaign = ES_Common::ig_es_can_access( 'campaigns' );
$export_nonce = ig_es_get_request_data('export-nonce');
if (wp_verify_nonce($export_nonce, 'ig-es-subscriber-export-nonce')) {
if ($report && $status && $can_access) {
$status = trim( $status );
$selected_list_id = 0;
if ( 'select_list' === $status ) {
$selected_list_id = ig_es_get_request_data( 'list_id', 0 );
if ( 0 === $selected_list_id ) {
$this->show_error_message(__('Please select list', 'email-subscribers'));
}
}
$csv = $this->generate_csv($status, $selected_list_id);
$file_name = sprintf('%s-contacts.csv', strtolower($status));
$this->output_CSV($csv, $file_name);
} elseif ($report && $link_id && $campaign_id && $can_access_campaign) {
$subscribers = ES()->actions_db->get_link_cliked_subscribers($campaign_id, $link_id);
if ( count( $subscribers ) > 0 ) {
$sub_headers = [
__('First Name', 'email-subscribers'),
__('Last Name', 'email-subscribers'),
__('Email', 'email-subscribers'),
];
$csv = implode(',', $sub_headers);
$csv.="\n";
foreach ($subscribers as $subscriber) {
$data = [
'first_name' => $this->escape_and_trim_data($subscriber['first_name']),
'last_name' => $this->escape_and_trim_data($subscriber['last_name']),
'email' => $this->escape_and_trim_data($subscriber['email']),
];
$csv .= '"' . implode('","', $data) . "\"\n";
}
}
if (empty($csv)) {
$this->show_error_message(__('No data available', 'email-subscribers'));
}
$this->output_CSV($csv, 'subscriber-contacts.csv');
}
}
add_filter( 'query_vars', array( $this, 'query_vars' ) );
add_action( 'parse_request', array( $this, 'parse_request' ) );
add_action( 'admin_menu', array( $this, 'plugin_menu' ) );
}
private function show_error_message( $message) {
ES_Common::show_message($message, 'error');
exit();
}
private function escape_and_trim_data( $data) {
return trim(str_replace('"', '""', $this->escape_data($data)));
}
private function output_CSV( $csv_content, $file_name) {
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private', false);
header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename=$file_name");
header('Content-Transfer-Encoding: binary');
echo wp_kses_post($csv_content);
exit();
}
public function plugin_menu() {
add_submenu_page( null, 'Export Contacts', __( 'Export Contacts', 'email-subscribers' ), 'edit_posts', 'es_export_subscribers', array( $this, 'export_subscribers_page' ) );
}
public function prepare_header_footer_row() {
?>
<tr class="bg-gray-100 text-sm text-left leading-4 text-gray-500 tracking-wider border-b border-t border-gray-200 ">
<th class="w-1/12 pl-8 py-4 font-medium" scope="col"><?php esc_html_e( 'No.', 'email-subscribers' ); ?></th>
<th class="w-2/12 pl-4 py-4 font-medium" scope="col"><?php esc_html_e( 'Contacts', 'email-subscribers' ); ?></th>
<th class="w-2/12 pl-8 py-4 font-medium" scope="col"><?php esc_html_e( 'Total contacts', 'email-subscribers' ); ?></th>
<th class="w-2/12 pl-16 py-4 font-medium" scope="col"><?php esc_html_e( 'Export', 'email-subscribers' ); ?></th>
</tr>
<?php
}
public function prepare_body() {
$list_dropdown_html = "<select class='form-select sm:w-32 lg:w-40' name='list_id' id='ig_es_export_list_dropdown'>";
$list_dropdown_html .= ES_Common::prepare_list_dropdown_options();
$list_dropdown_html .= '</select>';
$export_lists = array(
'all' => __( 'All contacts', 'email-subscribers' ),
'subscribed' => __( 'Subscribed contacts', 'email-subscribers' ),
'unsubscribed' => __( 'Unsubscribed contacts', 'email-subscribers' ),
'unconfirmed' => __( 'Unconfirmed contacts', 'email-subscribers' ),
'select_list' => $list_dropdown_html,
);
$i = 1;
$export_nonce = wp_create_nonce( 'ig-es-subscriber-export-nonce' );
foreach ( $export_lists as $key => $export_list ) {
$url = "admin.php?page=download_report&report=users&status={$key}&export-nonce={$export_nonce}";
?>
<tr class="border-b text-sm font-normal text-gray-700 border-gray-200" id="ig_es_export_<?php echo esc_attr( $key ); ?>">
<td class="py-2 pl-10 w-1/12"><?php echo esc_html( $i ); ?></td>
<td class="py-2 pl-4 w-2/12">
<?php
$allowedtags = ig_es_allowed_html_tags_in_esc();
echo wp_kses( $export_list, $allowedtags );
?>
</td>
<td class="py-2 pl-8 w-2/12 font-medium ig_es_total_contacts"><?php echo esc_html( $this->count_subscribers( $key ) ); ?></td>
<td class="py-2 pl-8 w-2/12">
<div class="inline-flex pl-10"><a href="<?php echo esc_url( $url ); ?>" id="ig_es_export_link_<?php echo esc_attr( $key ); ?>">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-indigo-600 hover:text-indigo-500 active:text-indigo-600"><path d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</a>
</div>
</td>
</tr>
<?php
$i ++;
}
}
public function export_subscribers_page() {
$audience_tab_main_navigation = array();
$active_tab = 'export';
$audience_tab_main_navigation = apply_filters( 'ig_es_audience_tab_main_navigation', $active_tab, $audience_tab_main_navigation );
?>
<div class="max-w-full -mt-3 font-sans">
<header class="wp-heading-inline">
<div class="flex">
<div>
<nav class="text-gray-400 my-0" aria-label="Breadcrumb">
<ol class="list-none p-0 inline-flex">
<li class="flex items-center text-sm tracking-wide">
<a class="hover:underline " href="admin.php?page=es_subscribers"><?php esc_html_e( 'Audience ', 'email-subscribers' ); ?></a>
<svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
</li>
</ol>
</nav>
<h2 class="-mt-1.5 text-2xl font-medium text-gray-700 sm:leading-7 sm:truncate"> <?php esc_html_e( 'Export Contacts', 'email-subscribers' ); ?>
</h2>
</div>
<div class="mt-4 ml-2">
<?php
ES_Common::prepare_main_header_navigation( $audience_tab_main_navigation );
?>
</div>
</div>
</header>
<div><hr class="wp-header-end"></div>
<div class="mt-8 shadow rounded-lg overflow-hidden">
<form name="frm_es_subscriberexport" method="post">
<table class="min-w-full" id="straymanage">
<thead>
<?php $this->prepare_header_footer_row(); ?>
</thead>
<tbody class="bg-white">
<?php $this->prepare_body(); ?>
</tbody>
<tfoot>
<?php $this->prepare_header_footer_row(); ?>
</tfoot>
</table>
</form>
</div>
<?php
}
/**
* Count total subscribers
*
* @param string $status
*
* @return string|null
*/
public function count_subscribers( $status = 'all' ) {
global $wpdb;
switch ( $status ) {
case 'all':
return ES()->lists_contacts_db->get_all_contacts_count( 0, false );
break;
case 'subscribed':
return ES()->lists_contacts_db->get_subscribed_contacts_count( 0, false );
break;
case 'unsubscribed':
return ES()->lists_contacts_db->get_unsubscribed_contacts_count( 0, false );
break;
case 'confirmed':
return ES()->lists_contacts_db->get_confirmed_contacts_count( 0, false );
break;
case 'unconfirmed':
return ES()->lists_contacts_db->get_unconfirmed_contacts_count( 0, false );
break;
case 'select_list':
default:
return '-';
break;
}
}
/**
* Allow for custom query variables
*/
public function query_vars( $query_vars ) {
$query_vars[] = 'download_report';
return $query_vars;
}
/**
* Parse the request
*/
public function parse_request( &$wp ) {
if ( array_key_exists( 'download_report', $wp->query_vars ) ) {
$this->download_report();
exit;
}
}
/**
* Download report
*/
public function download_report() {
?>
<div class="wrap">
<div id="icon-tools" class="icon32"></div>
<h2>Download Report</h2>
<p>
<a href="?page=download_report&report=users"><?php esc_html_e( 'Export the Subscribers', 'email-subscribers' ); ?></a>
</p>
<?php
}
/**
* Generate CSV
* first_name, last_name, email, status, list, subscribed_at, unsubscribed_at
*
* @param string $status
* @param string $list_id
*
* @return string
*/
public function generate_csv( $status = 'all', $list_id = 0 ) {
global $wpbd;
// Add filter to increase memory limit
add_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' );
wp_raise_memory_limit( 'ig_es' );
// Remove the added filter function so that it won't be called again if wp_raise_memory_limit called later on.
remove_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' );
set_time_limit( IG_SET_TIME_LIMIT );
$results = array();
if ( 'all' === $status ) {
$results = ES()->lists_contacts_db->get_all_contacts();
} elseif ( 'subscribed' === $status ) {
$results = ES()->lists_contacts_db->get_all_subscribed_contacts();
} elseif ( 'unsubscribed' === $status ) {
$results = ES()->lists_contacts_db->get_all_unsubscribed_contacts();
} elseif ( 'confirmed' === $status ) {
$results = ES()->lists_contacts_db->get_all_confirmed_contacts();
} elseif ( 'unconfirmed' === $status ) {
$results = ES()->lists_contacts_db->get_all_unconfirmed_contacts();
} elseif ( 'select_list' === $status ) {
$list_id = absint( $list_id );
$results = ES()->lists_contacts_db->get_all_contacts_from_list( $list_id );
}
$subscribers = array();
if ( count( $results ) > 0 ) {
$contact_list_map = array();
$contact_ids = array();
foreach ( $results as $result ) {
if ( ! in_array( $result['contact_id'], $contact_ids, true ) ) {
$contact_ids[] = $result['contact_id'];
}
$contact_list_map[ $result['contact_id'] ][] = array(
'status' => $result['status'],
'list_id' => $result['list_id'],
'optin_type' => $result['optin_type'],
);
}
$contact_ids_str = implode( ',', $contact_ids );
$select_columns = array(
'id',
'first_name',
'last_name',
'email',
'created_at',
);
$custom_fields = ES()->custom_fields_db->get_custom_fields();
if ( ! empty( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
$select_columns[] = $field['slug'];
}
}
$query = 'SELECT ' . implode( ',', $select_columns ) . " FROM {$wpbd->prefix}ig_contacts WHERE id IN ({$contact_ids_str})";
$subscribers = $wpbd->get_results( $query, ARRAY_A );
}
$csv_output = '';
if ( count( $subscribers ) > 0 ) {
$headers = array(
__( 'First Name', 'email-subscribers' ),
__( 'Last Name', 'email-subscribers' ),
__( 'Email', 'email-subscribers' ),
__( 'List', 'email-subscribers' ),
__( 'Status', 'email-subscribers' ),
__( 'Opt-In Type', 'email-subscribers' ),
__( 'Created On', 'email-subscribers' ),
);
if ( ! empty( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
$headers[] = $field['label'];
}
}
$lists_id_name_map = ES()->lists_db->get_list_id_name_map();
$csv_output .= implode( ',', $headers );
foreach ( $subscribers as $key => $subscriber ) {
$data = array();
$data['first_name'] = trim( str_replace( '"', '""', $this->escape_data( $subscriber['first_name'] ) ) );
$data['last_name'] = trim( str_replace( '"', '""', $this->escape_data( $subscriber['last_name'] ) ) );
$data['email'] = trim( str_replace( '"', '""', $this->escape_data( $subscriber['email'] ) ) );
$contact_id = $subscriber['id'];
if ( ! empty( $contact_list_map[ $contact_id ] ) ) {
foreach ( $contact_list_map[ $contact_id ] as $list_details ) {
$data['list'] = $lists_id_name_map[ $list_details['list_id'] ];
$data['status'] = ucfirst( $list_details['status'] );
$data['optin_type'] = ( 1 == $list_details['optin_type'] ) ? 'Single Opt-In' : 'Double Opt-In';
$data['created_at'] = $subscriber['created_at'];
if ( ! empty( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
$column_name = $field['slug'];
$data[ $column_name ] = $subscriber[ $column_name ];
}
}
$csv_output .= "\n";
$csv_output .= '"' . implode( '","', $data ) . '"';
}
}
}
}
return $csv_output;
}
/**
* Escape a string to be used in a CSV context
*
* Malicious input can inject formulas into CSV files, opening up the possibility
* for phishing attacks and disclosure of sensitive information.
*
* Additionally, Excel exposes the ability to launch arbitrary commands through
* the DDE protocol.
*
* @see http://www.contextis.com/resources/blog/comma-separated-vulnerabilities/
* @see https://hackerone.com/reports/72785
*
* @since 5.5.3
* @param string $data CSV field to escape.
* @return string
*/
public function escape_data( $data ) {
$active_content_triggers = array( '=', '+', '-', '@' );
if ( in_array( mb_substr( $data, 0, 1 ), $active_content_triggers, true ) ) {
$data = "'" . $data;
}
return $data;
}
}

View File

@@ -0,0 +1,106 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Form_Widget extends WP_Widget {
public function __construct() {
parent::__construct( 'email-subscribers-form', __( 'Icegram Express', 'email-subscribers' ), array( 'description' => __( 'Icegram Express Form', 'email-subscribers' ) ) );
}
public function widget( $args, $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
$title = apply_filters( 'widget_title', $title );
echo wp_kses_post( $args['before_widget'] );
if ( ! empty( $title ) ) {
echo wp_kses_post( sprintf( '%s %s %s', $args['before_title'], $title, $args['after_title'] ) );
}
$form_id = isset( $instance['form_id'] ) ? esc_attr( $instance['form_id'] ) : 0;
$form_data = array();
if ( ! empty( $form_id ) ) {
$form = ES()->forms_db->get_form_by_id( $form_id );
if ( $form ) {
$form_data = ES_Forms_Table::get_form_data_from_body( $form );
}
}
$data = array();
$data['form_id'] = $form_id;
$data['list'] = '';
$data['name_visible'] = ( ! empty( $form_data['name_visible'] ) && 'yes' === $form_data['name_visible'] ) ? 'yes' : '';
$data['name_required'] = ( ! empty( $form_data['name_required'] ) && 'yes' === $form_data['name_required'] ) ? 'yes' : '';
$data['list_visible'] = ( ! empty( $form_data['list_visible'] ) && 'yes' === $form_data['list_visible'] ) ? 'yes' : '';
$data['list_label'] = ! empty( $form_data['list_label'] ) ? $form_data['list_label'] : __( 'Select list(s)', 'email-subscribers' );
;
$data['lists'] = ( ! empty( $form_data['lists'] ) ) ? $form_data['lists'] : array();
$data['desc'] = ( ! empty( $form_data['desc'] ) ) ? $form_data['desc'] : '';
$data['name_label'] = ( ! empty( $form_data['name_label'] ) ) ? $form_data['name_label'] : '';
$data['name_place_holder'] = ( ! empty( $form_data['name_place_holder'] ) ) ? $form_data['name_place_holder'] : '';
$data['email_label'] = ( ! empty( $form_data['email_label'] ) ) ? $form_data['email_label'] : '';
$data['email_place_holder'] = ( ! empty( $form_data['email_place_holder'] ) ) ? $form_data['email_place_holder'] : '';
$data['button_label'] = ( ! empty( $form_data['button_label'] ) ) ? $form_data['button_label'] : '';
$data['form_version'] = ( ! empty( $form_data['form_version'] ) ) ? $form_data['form_version'] : '';
$data['gdpr_consent'] = ( ! empty( $form_data['gdpr_consent'] ) ) ? $form_data['gdpr_consent'] : 'no';
$data['gdpr_consent_text'] = ( ! empty( $form_data['gdpr_consent_text'] ) ) ? $form_data['gdpr_consent_text'] : '';
$data['captcha'] = ( ! empty( $form_data['captcha'] ) ) ? $form_data['captcha'] : 'no';
if ( ! empty ( $form_data['custom_fields'] ) ) {
$data['custom_fields'] = ( ! empty( $form_data['custom_fields' ] ) ) ? $form_data['custom_fields' ] : '';
}
if ( ! empty( $form_data['settings'] ) ) {
$data['settings']['editor_type'] = ! empty( $form_data['settings']['editor_type'] ) ? $form_data['settings']['editor_type'] : array();
$data['settings']['dnd_editor_css'] = ! empty( $form_data['settings']['dnd_editor_css'] ) ? $form_data['settings']['dnd_editor_css'] : array();
$data['settings']['lists'] = ! empty( $form_data['settings']['lists'] ) ? $form_data['settings']['lists'] : array();
}
if ( ! empty( $form_data['body'] ) ) {
$data['body'] = ! empty( $form_data['body'] ) ? $form_data['body'] : '';
}
ES_Shortcode::render_form( $data );
echo wp_kses_post( $args['after_widget'] );
}
public function form( $instance ) {
$selected_form_id = isset( $instance['form_id'] ) ? esc_attr( $instance['form_id'] ) : '';
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Widget Title:', 'email-subscribers' ); ?></label>
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
</p>
<p>
<label for="widget-email-subscribers-2-es_group"><?php esc_html_e( 'Forms', 'email-subscribers' ); ?></label>
<select id="<?php echo esc_attr( $this->get_field_id( 'form_id' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'form_id' ) ); ?>" class="widefat" style="width:100%;">
<?php
$form_dropdown = ES_Common::prepare_form_dropdown_options( $selected_form_id, null );
$allowedtags = ig_es_allowed_html_tags_in_esc();
echo wp_kses( $form_dropdown, $allowedtags );
?>
</select>
</p>
<?php
}
public function update( $new_instance, $old_instance ) {
$instance = array();
$instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
$instance['form_id'] = ( ! empty( $new_instance['form_id'] ) ) ? strip_tags( $new_instance['form_id'] ) : '';
return $instance;
}
}

View File

@@ -0,0 +1,967 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
class ES_Forms_Table extends ES_List_Table {
/**
* Number of form options per page
*
* @since 4.2.1
* @var string
*/
public static $option_per_page = 'es_forms_per_page';
/**
* ES_DB_Forms object
*
* @since 4.3.1
* @var $db
*/
protected $db;
/**
* ES_Forms_Table constructor.
*
* @since 4.0
*/
public function __construct() {
parent::__construct(
array(
'singular' => __( 'Forms', 'email-subscribers' ), // singular name of the listed records
'plural' => __( 'Forms', 'email-subscribers' ), // plural name of the listed records
'ajax' => false, // does this table support ajax?,
'screen' => 'es_forms',
)
);
$this->db = new ES_DB_Forms();
$this->init();
}
public function init() {
add_action( 'ig_es_additional_form_options', array( $this, 'show_additional_form_setting' ) );
}
/**
* Add Screen Option
*
* @since 4.2.1
*/
public static function screen_options() {
$action = ig_es_get_request_data( 'action' );
if ( empty( $action ) ) {
$option = 'per_page';
$args = array(
'label' => __( 'Number of forms per page', 'email-subscribers' ),
'default' => 20,
'option' => self::$option_per_page,
);
add_screen_option( $option, $args );
}
}
/**
* Render Forms list view
*
* @since 4.0
*/
public function render() {
$action = ig_es_get_request_data( 'action' );
?>
<div class="wrap pt-4 font-sans">
<?php
if ( 'new' === $action ) {
$this->es_new_form_callback();
} elseif ( 'edit' === $action ) {
$form = ig_es_get_request_data( 'form' );
echo wp_kses_post( $this->edit_form( absint( $form ) ) );
} else {
?>
<div class="flex">
<div>
<h2 class="wp-heading-inline text-3xl font-bold text-gray-700 sm:leading-9 sm:truncate pr-4">
<?php esc_html_e( 'Forms', 'email-subscribers' ); ?>
</h2>
</div>
<div class="mt-1">
<a href="admin.php?page=es_forms&action=new" class="ig-es-title-button ml-2 leading-5 align-middle">
<?php esc_html_e( 'Add New', 'email-subscribers' ); ?>
</a>
<?php
do_action( 'ig_es_after_form_buttons' );
?>
</div>
</div>
<div><hr class="wp-header-end"></div>
<?php
if ( 'form_created' === $action ) {
$message = __( 'Form added successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
} elseif ( 'form_updated' === $action ) {
$message = __( 'Form updated successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
}
?>
<div id="poststuff" class="es-items-lists">
<div id="post-body" class="metabox-holder column-1">
<div id="post-body-content">
<div class="meta-box-sortables ui-sortable">
<form method="get">
<input type="hidden" name="page" value="es_forms" />
<?php
// Display search field and other available filter fields.
$this->prepare_items();
?>
</form>
<form method="post">
<?php
// Display bulk action fields, pagination and list items.
$this->display();
?>
</form>
</div>
<?php
do_action('ig_es_render_after_form_table');
?>
</div>
</div>
<br class="clear">
</div>
</div>
<?php
}
}
public function validate_data( $data ) {
$editor_type = ! empty( $data['editor_type'] ) ? $data['editor_type'] : '';
$is_dnd_editor = IG_ES_DRAG_AND_DROP_EDITOR === $editor_type;
$nonce = $data['nonce'];
$form_name = $data['name'];
$lists = $data['lists'];
$status = 'error';
$error = false;
$message = '';
if ( ! wp_verify_nonce( $nonce, 'es_form' ) ) {
$message = __( 'You do not have permission to edit this form.', 'email-subscribers' );
$error = true;
} elseif ( empty( $form_name ) ) {
$message = __( 'Please add form name.', 'email-subscribers' );
$error = true;
}
if ( ! $is_dnd_editor ) {
if ( empty( $lists ) ) {
$message = __( 'Please select list(s) in which contact will be subscribed.', 'email-subscribers' );
$error = true;
}
}
if ( ! $error ) {
$status = 'success';
}
$response = array(
'status' => $status,
'message' => $message,
);
return $response;
}
public function es_new_form_callback() {
$submitted = ig_es_get_request_data( 'submitted' );
if ( 'submitted' === $submitted ) {
$nonce = ig_es_get_request_data( '_wpnonce' );
$form_data = ig_es_get_request_data( 'form_data', array(), false );
$lists = ig_es_get_request_data( 'lists' );
$form_data['lists'] = $lists;
$editor_type = ! empty( $form_data['settings']['editor_type'] ) ? $form_data['settings']['editor_type'] : '';
$validate_data = array(
'nonce' => $nonce,
'name' => ! empty( $form_data['name'] ) ? sanitize_text_field( $form_data['name'] ) : '',
'lists' => ! empty( $form_data['lists'] ) ? $form_data['lists'] : array(),
'editor_type' => $editor_type,
);
$response = $this->validate_data( $validate_data );
if ( 'error' === $response['status'] ) {
$message = $response['message'];
ES_Common::show_message( $message, 'error' );
$this->prepare_list_form( null, $form_data );
return;
}
$this->save_form( null, $form_data );
$form_url = admin_url( 'admin.php?page=es_forms&action=form_created' );
wp_safe_redirect( $form_url );
exit();
}
$this->prepare_list_form();
}
public function edit_form( $id ) {
global $wpdb;
if ( $id ) {
$form_data = array();
$data = ES()->forms_db->get_by_conditions( $wpdb->prepare( ' id = %d', $id ) );
if ( count( $data ) > 0 ) {
$submitted = ig_es_get_request_data( 'submitted' );
if ( 'submitted' === $submitted ) {
$nonce = ig_es_get_request_data( '_wpnonce' );
$form_data = ig_es_get_request_data( 'form_data', array(), false );
$lists = ig_es_get_request_data( 'lists' );
$form_data['captcha'] = ! empty( $form_data['captcha'] ) ? $form_data['captcha'] : 'no';
$form_data['lists'] = $lists;
$editor_type = ! empty( $form_data['settings']['editor_type'] ) ? $form_data['settings']['editor_type'] : '';
$validate_data = array(
'nonce' => $nonce,
'name' => $form_data['name'],
'lists' => $form_data['lists'],
'editor_type' => $editor_type,
);
$response = $this->validate_data( $validate_data );
if ( 'error' === $response['status'] ) {
$message = $response['message'];
ES_Common::show_message( $message, 'error' );
$this->prepare_list_form( $id, $form_data );
return;
}
$this->save_form( $id, $form_data );
$form_url = admin_url( 'admin.php?page=es_forms&action=form_updated' );
wp_safe_redirect( $form_url );
exit();
} else {
$data = $data[0];
$id = $data['id'];
$form_data = self::get_form_data_from_body( $data );
}
} else {
$message = __( 'Sorry, form not found', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
}
$this->prepare_list_form( $id, $form_data );
}
}
public function prepare_list_form( $id = 0, $data = array() ) {
$is_new = empty( $id ) ? 1 : 0;
$editor_type = '';
if ( $is_new ) {
$editor_type = IG_ES_DRAG_AND_DROP_EDITOR;
$data['settings']['editor_type'] = $editor_type;
} else {
$editor_type = ! empty( $data['settings']['editor_type'] ) ? $data['settings']['editor_type'] : '';
}
$is_dnd_editor = IG_ES_DRAG_AND_DROP_EDITOR === $editor_type;
if ( $is_dnd_editor ) {
do_action( 'ig_es_render_dnd_form', $id, $data );
} else {
do_action( 'ig_es_render_classic_form', $id, $data );
}
}
/**
* Show additional form setting for es form
*
* @param $form_data
*
* @since 5.6.1
*/
public function show_additional_form_setting( $form_data ) {
$editor_type = ! empty( $form_data['settings']['editor_type'] ) ? $form_data['settings']['editor_type'] : '';
$is_dnd_editor = IG_ES_DRAG_AND_DROP_EDITOR === $editor_type;
if ( $is_dnd_editor ) {
$this->show_dnd_show_in_popup_settings( $form_data );
$this->show_success_message( $form_data );
} else {
$this->show_classic_show_in_popup_settings( $form_data );
}
}
/**
* Show success message
*
* @param $form_data
*
* @since 5.6.1
*
* @modify 5.6.3
*/
public function show_success_message( $form_data ) {
$action_after_submit = ! empty( $form_data['settings']['action_after_submit'] ) ? $form_data['settings']['action_after_submit'] : 'show_success_message';
$success_message = ! empty( $form_data['settings']['success_message'] ) ? $form_data['settings']['success_message'] : '';
?>
<div class="pt-2 mx-4 border-t border-gray-200">
<div class="block w-full">
<span class="block pr-4 text-sm font-medium text-gray-600 pb-2"><?php esc_html_e( 'after submit...', 'email-subscribers' ); ?></span>
<div class="py-2">
<input id="success_message" type="radio" name="form_data[settings][action_after_submit]" class="form-radio ig_es_action_after_submit" value="show_success_message" <?php checked( $action_after_submit, 'show_success_message' ); ?>/>
<label for="success_message"
class="text-sm font-medium text-gray-500"><?php echo esc_html__( 'Show message', 'email-subscribers' ); ?>
</label>
<br>
<div id="show_message_block" class="pt-2 px-6">
<input class="form-input block border-gray-400 w-full pl-3 pr-3 shadow-sm focus:bg-gray-100 sm:text-sm sm:leading-5" name="form_data[settings][success_message]" value="<?php echo esc_attr( stripslashes( $success_message ) ); ?>" />
</div>
</div>
</div>
</div>
<?php
do_action( 'ig_es_redirect_to_url' );
}
/**
* Show show in popup setting in classic form
*
* @param $form_data
*
* @since 5.6.1
*/
public function show_classic_show_in_popup_settings( $form_data ) {
$popup_field_name = 'form_data[show_in_popup]';
$popup_field_value = $form_data['show_in_popup'];
$headline_field_name = 'form_data[popup_headline]';
$headline_field_value = $form_data['popup_headline'];
?>
<div class="flex flex-row border-b border-gray-100">
<div class="flex w-1/5">
<div class="ml-4 pt-4 mb-2">
<label for="tag-link"><span class="block ml-4 pr-4 text-sm font-medium text-gray-600 pb-2"><?php esc_html_e( 'Show in popup', 'email-subscribers' ); ?></span></label>
<p class="italic text-xs text-gray-400 ml-4 leading-snug pt-2"><?php echo esc_html__( 'Show form in popup', 'email-subscribers' ); ?></p>
</div>
</div>
<div>
<div class="ml-16 mb-3 mr-4 mt-6">
<label for="show_in_popup" class="inline-flex items-center cursor-pointer">
<span class="relative">
<input id="show_in_popup" type="checkbox" class=" absolute es-check-toggle opacity-0 w-0 h-0" name="<?php echo esc_attr( $popup_field_name ); ?>" value="yes"
<?php
if ( 'yes' === $popup_field_value ) {
echo 'checked="checked"';
}
?>
/>
<span class="es-mail-toggle-line"></span>
<span class="es-mail-toggle-dot"></span>
</span>
</label>
</div>
<div class="ml-16 mb-4 mr-4 mt-8" id="popup_input_block" style="display:none">
<table class="ig-es-form-table ">
<tr class="form-field">
<td class="pr-12">
<b class="text-gray-500 text-sm font-normal pb-2"><?php esc_html_e( 'Headline', 'email-subscribers' ); ?></b>
</td>
<td class="pr-12">
<input id="popup_headline" class="form-input block border-gray-400 w-full pl-3 pr-12 shadow-sm focus:bg-gray-100 sm:text-sm sm:leading-5" name="<?php echo esc_attr( $headline_field_name ); ?>" value="<?php echo esc_html( stripslashes( $headline_field_value ) ); ?>" />
</td>
</tr>
</table>
<p class="italic text-xs text-gray-400 leading-snug pt-2">
<?php
/* translators: %s: Form attribute */
echo sprintf( esc_html__( 'To disable it at a specific instance of a form add this attribute %s in the form\'s shortcode', 'email-subscribers'), '<code class="text-gray-500"><em><strong>show-in-popup="no"</em></strong></code>' );
?>
</p>
</div>
</div>
</div>
<?php
}
/**
* Show show in popup setting in DND form
*
* @param $form_data
*
* @since 5.6.1
*/
public function show_dnd_show_in_popup_settings( $form_data ) {
$popup_field_name = 'form_data[settings][show_in_popup]';
$popup_field_value = isset( $form_data['settings']['show_in_popup'] ) ? $form_data['settings']['show_in_popup'] : 'no';
$headline_field_name = 'form_data[settings][popup_headline]';
$headline_field_value = ! empty( $form_data['settings']['popup_headline'] ) ? $form_data['settings']['popup_headline'] : '';
?>
<div class="pt-2 pb-4 mx-4">
<div class="flex w-full">
<div class="w-11/12 text-sm font-normal text-gray-600">
<?php echo esc_html__( 'Show in popup', 'email-subscribers' ); ?>
</div>
<div>
<label for="show_in_popup" class="inline-flex items-center cursor-pointer">
<span class="relative">
<input id="show_in_popup" type="checkbox"
class=" absolute es-check-toggle opacity-0 w-0 h-0"
name="form_data[settings][show_in_popup]"
value="yes"
<?php
if ( 'yes' === $popup_field_value ) {
echo 'checked="checked"';
}
?>
/>
<span class="es-mail-toggle-line"></span>
<span class="es-mail-toggle-dot"></span>
</span>
</label>
</div>
</div>
</div>
<div class="pt-2 pb-4 mx-4" id="popup_input_block" style="display:none">
<div class="flex w-full">
<div class="w-4/12 text-sm font-normal text-gray-600">
<?php echo esc_html__( 'Headline', 'email-subscribers' ); ?>
</div>
<div class="w-8/12">
<input id="popup_headline" class="form-input block border-gray-400 w-full pl-3 pr-3 shadow-sm focus:bg-gray-100 sm:text-sm sm:leading-5" name="<?php echo esc_attr( $headline_field_name ); ?>" value="<?php echo esc_html( stripslashes( $headline_field_value ) ); ?>" />
</div>
</div>
<p class="italic text-xs text-gray-400 leading-snug pt-2">
<?php
/* translators: %s: Form attribute */
echo sprintf( esc_html__( 'To disable it at a specific instance of a form add this attribute %s in the form\'s shortcode', 'email-subscribers'), '<code class="text-gray-500"><em><strong>show-in-popup="no"</em></strong></code>' );
?>
</p>
</div>
<?php
}
public function save_form( $id, $data ) {
global $wpdb;
$form_data = self::prepare_form_data( $data );
if ( ! empty( $id ) ) {
$form_data['updated_at'] = ig_get_current_date_time();
// We don't want to change the created_at date for update
unset( $form_data['created_at'] );
$return = $wpdb->update( IG_FORMS_TABLE, $form_data, array( 'id' => $id ) );
} else {
$return = $wpdb->insert( IG_FORMS_TABLE, $form_data );
}
return $return;
}
public static function prepare_form_data( $data ) {
$form_data = array();
$name = ! empty( $data['name'] ) ? sanitize_text_field( $data['name'] ) : '';
$editor_type = ! empty( $data['settings']['editor_type'] ) ? sanitize_text_field( $data['settings']['editor_type'] ) : '';
$is_dnd_editor = IG_ES_DRAG_AND_DROP_EDITOR === $editor_type;
$es_form_popup = ! empty( $data['show_in_popup'] ) ? 'yes' : 'no';
$es_popup_headline = ! empty( $data['popup_headline'] ) ? sanitize_text_field( $data['popup_headline'] ) : '';
if ( ! $is_dnd_editor ) {
$desc = ! empty( $data['desc'] ) ? wp_kses_post( trim( wp_unslash( $data['desc'] ) ) ) : '';
$email_label = ! empty( $data['email_label'] ) ? sanitize_text_field( $data['email_label'] ) : '';
$email_place_holder = ! empty( $data['email_place_holder'] ) ? sanitize_text_field( $data['email_place_holder'] ) : '';
$name_label = ! empty( $data['name_label'] ) ? sanitize_text_field( $data['name_label'] ) : '';
$name_place_holder = ! empty( $data['name_place_holder'] ) ? sanitize_text_field( $data['name_place_holder'] ) : '';
$button_label = ! empty( $data['button_label'] ) ? sanitize_text_field( $data['button_label'] ) : '';
$name_visible = ( ! empty( $data['name_visible'] ) && 'yes' === $data['name_visible'] ) ? true : false;
$name_required = ( ! empty( $data['name_required'] ) && 'yes' === $data['name_required'] ) ? true : false;
$list_label = ! empty( $data['list_label'] ) ? sanitize_text_field( $data['list_label'] ) : '';
$list_visible = ( ! empty( $data['list_visible'] ) && 'yes' === $data['list_visible'] ) ? true : false;
$list_required = true;
$list_ids = ! empty( $data['lists'] ) ? $data['lists'] : array();
$gdpr_consent = ! empty( $data['gdpr_consent'] ) ? sanitize_text_field( $data['gdpr_consent'] ) : 'no';
$gdpr_consent_text = ! empty( $data['gdpr_consent_text'] ) ? wp_kses_post( $data['gdpr_consent_text'] ) : '';
$captcha = ! empty( $data['captcha'] ) ? ES_Common::get_captcha_setting( null, $data ) : 'no';
$body = array(
array(
'type' => 'text',
'name' => 'Name',
'id' => 'name',
'params' => array(
'label' => $name_label,
'place_holder' => $name_place_holder,
'show' => $name_visible,
'required' => $name_required,
),
'position' => 1,
),
array(
'type' => 'text',
'name' => 'Email',
'id' => 'email',
'params' => array(
'label' => $email_label,
'place_holder' => $email_place_holder,
'show' => true,
'required' => true,
),
'position' => 2,
),
array(
'type' => 'checkbox',
'name' => 'Lists',
'id' => 'lists',
'params' => array(
'label' => $list_label,
'show' => $list_visible,
'required' => $list_required,
'values' => $list_ids,
),
'position' => 3,
),
);
$form_body = apply_filters( 'es_add_custom_fields_data_in_form_body', $body, $data );
$submit_button_position = count( $form_body ) + 1;
$submit_data = array(
array(
'type' => 'submit',
'name' => 'submit',
'id' => 'submit',
'params' => array(
'label' => $button_label,
'show' => true,
'required' => true,
),
'position' => $submit_button_position,
),
);
$body = array_merge( $form_body, $submit_data );
$settings = array(
'lists' => $list_ids,
'desc' => $desc,
'form_version' => ES()->forms_db->version,
'captcha' => $captcha,
'gdpr' => array(
'consent' => $gdpr_consent,
'consent_text' => $gdpr_consent_text,
),
'es_form_popup' => array(
'show_in_popup' => $es_form_popup,
'popup_headline' => $es_popup_headline,
),
);
$settings = apply_filters( 'ig_es_form_settings', $settings, $data );
$form_data['body'] = maybe_serialize( $body );
} else {
$form_data['body'] = ES_Form_Admin::process_form_body($data['body']);
$settings = $data['settings'];
}
$af_id = ! empty( $data['af_id'] ) ? $data['af_id'] : 0;
$form_data['name'] = $name;
$form_data['settings'] = maybe_serialize( $settings );
$form_data['styles'] = null;
$form_data['created_at'] = ig_get_current_date_time();
$form_data['updated_at'] = null;
$form_data['deleted_at'] = null;
$form_data['af_id'] = $af_id;
return $form_data;
}
public static function get_form_data_from_body( $data ) {
$name = ! empty( $data['name'] ) ? $data['name'] : '';
$id = ! empty( $data['id'] ) ? $data['id'] : '';
$af_id = ! empty( $data['af_id'] ) ? $data['af_id'] : '';
$body_data = maybe_unserialize( $data['body'] );
$settings_data = maybe_unserialize( $data['settings'] );
$desc = ! empty( $settings_data['desc'] ) ? $settings_data['desc'] : '';
$form_version = ! empty( $settings_data['form_version'] ) ? $settings_data['form_version'] : '0.1';
$editor_type = ! empty( $settings_data['editor_type'] ) ? $settings_data['editor_type'] : '';
$is_dnd_editor = IG_ES_DRAG_AND_DROP_EDITOR === $editor_type;
if ( ! $is_dnd_editor ) {
$gdpr_consent = 'no';
$gdpr_consent_text = '';
$es_form_popup = ! empty( $settings_data['es_form_popup']['show_in_popup'] ) ? $settings_data['es_form_popup']['show_in_popup'] : 'no';
$es_popup_headline = ! empty( $settings_data['es_form_popup']['popup_headline'] ) ? $settings_data['es_form_popup']['popup_headline'] : '';
$captcha = ES_Common::get_captcha_setting( $id, $settings_data );
if ( ! empty( $settings_data['gdpr'] ) ) {
$gdpr_consent = ! empty( $settings_data['gdpr']['consent'] ) ? $settings_data['gdpr']['consent'] : 'no';
$gdpr_consent_text = ! empty( $settings_data['gdpr']['consent_text'] ) ? $settings_data['gdpr']['consent_text'] : '';
}
$form_data = array(
'form_id' => $id,
'name' => $name,
'af_id' => $af_id,
'desc' => $desc,
'form_version' => $form_version,
'gdpr_consent' => $gdpr_consent,
'gdpr_consent_text' => $gdpr_consent_text,
'captcha' => $captcha,
'show_in_popup' => $es_form_popup,
'popup_headline' => $es_popup_headline,
'editor_type' => $editor_type,
);
foreach ( $body_data as $d ) {
if ( 'name' === $d['id'] ) {
$form_data['name_visible'] = ( true === $d['params']['show'] ) ? 'yes' : '';
$form_data['name_required'] = ( true === $d['params']['required'] ) ? 'yes' : '';
$form_data['name_label'] = ! empty( $d['params']['label'] ) ? $d['params']['label'] : '';
$form_data['name_place_holder'] = ! empty( $d['params']['place_holder'] ) ? $d['params']['place_holder'] : '';
} elseif ( 'lists' === $d['id'] ) {
$form_data['list_label'] = ! empty( $d['params']['label'] ) ? $d['params']['label'] : '';
$form_data['list_visible'] = ( true === $d['params']['show'] ) ? 'yes' : '';
$form_data['list_required'] = ( true === $d['params']['required'] ) ? 'yes' : '';
$form_data['lists'] = ! empty( $d['params']['values'] ) ? $d['params']['values'] : array();
} elseif ( 'email' === $d['id'] ) {
$form_data['email_label'] = ! empty( $d['params']['label'] ) ? $d['params']['label'] : '';
$form_data['email_place_holder'] = ! empty( $d['params']['place_holder'] ) ? $d['params']['place_holder'] : '';
} elseif ( 'submit' === $d['id'] ) {
$form_data['button_label'] = ! empty( $d['params']['label'] ) ? $d['params']['label'] : '';
} elseif ( $d['is_custom_field'] ) {
$form_data['custom_fields'][] = $d;
}
}
$form_data = apply_filters('ig_es_form_fields_data', $form_data, $settings_data, $body_data);
} else {
$form_data = array(
'form_id' => $id,
'body' => $body_data,
'name' => $name,
'af_id' => $af_id,
'form_version' => $form_version,
'settings' => $settings_data,
);
}
return $form_data;
}
/**
* Retrieve lists data from the database
*
* @param int $per_page
* @param int $page_number
*
* @return mixed
*/
public function get_lists( $per_page = 5, $page_number = 1, $do_count_only = false ) {
global $wpdb, $wpbd;
$order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
$order = ig_es_get_request_data( 'order' );
$search = ig_es_get_request_data( 's' );
$forms_table = IG_FORMS_TABLE;
if ( $do_count_only ) {
$sql = "SELECT count(*) as total FROM {$forms_table}";
} else {
$sql = "SELECT * FROM {$forms_table}";
}
$args = array();
$query = array();
$add_where_clause = false;
if ( ! empty( $search ) ) {
$query[] = ' name LIKE %s ';
$args[] = '%' . $wpdb->esc_like( $search ) . '%';
$add_where_clause = true;
}
if ( $add_where_clause ) {
$sql .= ' WHERE ';
if ( count( $query ) > 0 ) {
$sql .= implode( ' AND ', $query );
if ( count( $args ) > 0 ) {
$sql = $wpbd->prepare( $sql, $args );
}
}
}
if ( ! $do_count_only ) {
$order = ! empty( $order ) ? strtolower( $order ) : 'desc';
$expected_order_values = array( 'asc', 'desc' );
if ( ! in_array( $order, $expected_order_values ) ) {
$order = 'desc';
}
$default_order_by = esc_sql( 'created_at' );
$expected_order_by_values = array( 'name', 'created_at' );
if ( ! in_array( $order_by, $expected_order_by_values ) ) {
$order_by_clause = " ORDER BY {$default_order_by} DESC";
} else {
$order_by = esc_sql( $order_by );
$order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
}
$sql .= $order_by_clause;
$sql .= " LIMIT $per_page";
$sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
$result = $wpbd->get_results( $sql, 'ARRAY_A' );
} else {
$result = $wpbd->get_var( $sql );
}
return $result;
}
/**
* Render a column when no column specific method exist.
*
* @param array $item
* @param string $column_name
*
* @return mixed
*/
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
// case 'status':
// return $this->status_label_map( $item[ $column_name ] );
case 'created_at':
return ig_es_format_date_time( $item[ $column_name ] );
break;
case 'shortcode':
$shortcode = '[email-subscribers-form id="' . $item['id'] . '"]';
return '<code class="es-code">' . $shortcode . '</code>';
break;
case 'total_active_subscribers':
$total_active_subscribers = ES()->contacts_db->get_total_contacts_by_form_id( $item['id'] );
return number_format( $total_active_subscribers );
default:
return '';
}
}
/**
* Render the bulk edit checkbox
*
* @param array $item
*
* @return string
*/
public function column_cb( $item ) {
return sprintf(
'<input type="checkbox" name="forms[]" value="%s" />',
$item['id']
);
}
/**
* Method for name column
*
* @param array $item an array of DB data
*
* @return string
*/
public function column_name( $item ) {
$list_nonce = wp_create_nonce( 'es_form' );
$title = '<strong>' . stripslashes( $item['name'] ) . '</strong>';
$page = ig_es_get_request_data( 'page' );
$actions = array(
'edit' => '<a href="?page=' . esc_attr( $page ) . '&action=edit&form=' . absint( $item['id'] ) . '&_wpnonce=' . $list_nonce . '" class="text-indigo-600">' . esc_html__( 'Edit', 'email-subscribers' ) . '</a>',
'delete' => '<a href="?page=' . esc_attr( $page ) . '&action=delete&form=' . absint( $item['id'] ) . '&_wpnonce=' . $list_nonce . '" onclick="return checkDelete()">' . esc_html__( 'Delete', 'email-subscribers' ) . '</a>',
);
$actions = apply_filters('ig_es_form_table_row_actions', $actions, $item);
return $title . $this->row_actions( $actions );
}
/**
* Associative array of columns
*
* @return array
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'name' => __( 'Name', 'email-subscribers' ),
'shortcode' => __( 'Shortcode', 'email-subscribers' ),
'total_active_subscribers' => __( 'Subscribers', 'email-subscribers' ),
'created_at' => __( 'Created', 'email-subscribers' ),
);
return $columns;
}
/**
* Columns to make sortable.
*
* @return array
*/
public function get_sortable_columns() {
$sortable_columns = array(
'name' => array( 'name', true ),
'created_at' => array( 'created_at', true ),
);
return $sortable_columns;
}
/**
* Returns an associative array containing the bulk action
*
* @return array
*/
public function get_bulk_actions() {
return array(
'bulk_delete' => __( 'Delete', 'email-subscribers' ),
);
}
public function process_bulk_action() {
if ( 'delete' === $this->current_action() ) {
// In our file that handles the request, verify the nonce.
$nonce = ig_es_get_request_data( '_wpnonce' );
if ( ! wp_verify_nonce( $nonce, 'es_form' ) ) {
$message = __( 'You do not have permission to delete this form.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
} else {
$form = ig_es_get_request_data( 'form' );
$this->db->delete_forms( array( $form ) );
$message = __( 'Form deleted successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
}
}
$action = ig_es_get_request_data( 'action' );
$action2 = ig_es_get_request_data( 'action2' );
// If the delete bulk action is triggered
if ( ( 'bulk_delete' === $action ) || ( 'bulk_delete' === $action2 ) ) {
$forms = ig_es_get_request_data( 'forms' );
if ( ! empty( $forms ) > 0 ) {
$this->db->delete_forms( $forms );
$message = __( 'Form(s) deleted successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
} else {
$message = __( 'Please select form(s) to delete.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
return;
}
}
}
public function status_label_map( $status ) {
$statuses = array(
'enable' => __( 'Enable', 'email-subscribers' ),
'disable' => __( 'Disable', 'email-subscribers' ),
);
if ( ! in_array( $status, array_keys( $statuses ) ) ) {
return '';
}
return $statuses[ $status ];
}
public function search_box( $text, $input_id ) {
?>
<p class="search-box">
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_attr( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
<?php submit_button( __( 'Search Forms', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
</p>
<?php
}
/** Text displayed when no list data is available */
public function no_items() {
esc_html_e( 'No Forms avaliable.', 'email-subscribers' );
}
}

View File

@@ -0,0 +1,454 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Geolocation class
*
* Handles geolocation and updating the geolocation database.
*
* @version 4.5.0
*/
/**
* ES_Geolocation Class.
*/
class ES_Geolocation {
/**
* API endpoints for geolocating an IP address
*
* @var array
*/
private static $geoip_apis = array(
'ipinfo.io' => 'https://ipinfo.io/%s/json',
'ip-api.com' => 'http://ip-api.com/json/%s',
);
/**
* Icegram API endpoints for geolocating an IP address
*
* @var string
*
* @since 4.7.3
*/
private static $icegram_api_url = 'http://api.icegram.com/geo/';
/**
* Geolocate an IP address.
*
* @param string $ip_address IP Address.
*
* @return array
*/
public static function geolocate_ip( $ip_address = '' ) {
/**
* Get geolocation filter.
*
* @param string $ip_address IP Address.
*
* @since 4.5.0
*/
$geolocation = apply_filters(
'ig_es_get_geolocation',
array(),
$ip_address
);
if ( ! empty( $geolocation ) ) {
return $geolocation;
}
if ( ! is_array( $geolocation ) ) {
$geolocation = array();
}
$geolocation = self::geolocate_via_api( $ip_address );
return $geolocation;
}
/**
* Convert the String TimeZone to seconds
*
* @param $timezone
*
* @return string
*/
public static function convert_timezone_to_seconds( $timezone ) {
if ( empty( $timezone ) ) {
return '+0:00';
}
try {
$current = timezone_open( $timezone );
$utcTime = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
$offset_in_secs = $current->getOffset( $utcTime );
$hours_and_sec = gmdate( 'H:i', abs( $offset_in_secs ) );
return stripos( $offset_in_secs, '-' ) === false ? "+{$hours_and_sec}" : "-{$hours_and_sec}";
} catch ( Exception $exception ) {
return '+0:00';
}
}
/**
* Use APIs to Geolocate the user.
*
* Geolocation APIs can be added through the use of the ig_es_geolocation_geoip_apis filter.
* Provide a name=>value pair for service-slug=>endpoint.
*
* If APIs are defined, one will be chosen at random to fulfil the request. After completing, the result
* will be cached in a transient.
*
* @param string $ip_address IP address.
*
* @return array
*/
private static function geolocate_via_api( $ip_address ) {
$geo_ip_data = get_transient( 'ig_es_geoip_' . $ip_address );
if ( empty( $geo_ip_data ) ) {
$geo_ip_data = array();
$geoip_services = apply_filters( 'ig_es_geolocation_geoip_apis', self::$geoip_apis );
if ( empty( $geoip_services ) ) {
return $geo_ip_data;
}
$geoip_services_keys = array_keys( $geoip_services );
shuffle( $geoip_services_keys );
foreach ( $geoip_services_keys as $service_name ) {
$service_endpoint = $geoip_services[ $service_name ];
$response = wp_safe_remote_get( sprintf( $service_endpoint, $ip_address ), array( 'timeout' => 2 ) );
if ( ! is_wp_error( $response ) && $response['body'] ) {
switch ( $service_name ) {
case 'ipinfo.io':
$data = json_decode( $response['body'] );
$country_code = isset( $data->country ) ? $data->country : '';
$timezone = isset( $data->timezone ) ? self::convert_timezone_to_seconds( $data->timezone ) : '+0:00';
break;
case 'ip-api.com':
$data = json_decode( $response['body'] );
$country_code = isset( $data->countryCode ) ? $data->countryCode : ''; // @codingStandardsIgnoreLine
$timezone = isset( $data->timezone ) ? self::convert_timezone_to_seconds( $data->timezone ) : '+0:00';
break;
default:
$country_code = apply_filters( 'ig_es_geolocation_geoip_response_' . $service_name, '', $response['body'] );
$timezone = apply_filters( 'ig_es_geolocation_geoip_timezone_response_' . $service_name, '', $response['body'] );
break;
}
$country_code = sanitize_text_field( strtoupper( $country_code ) );
if ( $country_code ) {
$geo_ip_data['country_code'] = $country_code;
$geo_ip_data['timezone'] = $timezone;
break;
}
}
}
// Use Icegram geo location API incase if we still don't have the location data.
if ( empty( $geo_ip_data ) ) {
$response = wp_safe_remote_get(
self::$icegram_api_url . $ip_address,
array(
'timeout' => 2,
)
);
if ( ! is_wp_error( $response ) && $response['body'] ) {
$data = json_decode( $response['body'] );
$country_code = isset( $data->country_code ) ? $data->country_code : '';
$timezone = isset( $data->timezone ) ? self::convert_timezone_to_seconds( $data->timezone ) : '+0:00';
if ( $country_code ) {
$geo_ip_data['country_code'] = $country_code;
$geo_ip_data['timezone'] = $timezone;
}
}
}
if ( ! empty( $geo_ip_data ) ) {
set_transient( 'ig_es_geoip_' . $ip_address, $geo_ip_data, WEEK_IN_SECONDS );
}
}
return $geo_ip_data;
}
/**
* Method to get country name based on ISO code.
*
* @since 4.5.0
*/
public static function get_country_name_from_country_code( $country_code = '' ) {
$countries_data = self::get_countries();
if ( isset( $countries_data[ $country_code ] ) ) {
return $countries_data[ $country_code ];
} else {
return '';
}
}
public static function get_countries() {
$countries_data = array(
'AF' => 'Afghanistan',
'AX' => 'Aland Islands',
'AL' => 'Albania',
'DZ' => 'Algeria',
'AS' => 'American Samoa',
'AD' => 'Andorra',
'AO' => 'Angola',
'AI' => 'Anguilla',
'AQ' => 'Antarctica',
'AG' => 'Antigua And Barbuda',
'AR' => 'Argentina',
'AM' => 'Armenia',
'AW' => 'Aruba',
'AU' => 'Australia',
'AT' => 'Austria',
'AZ' => 'Azerbaijan',
'BS' => 'Bahamas',
'BH' => 'Bahrain',
'BD' => 'Bangladesh',
'BB' => 'Barbados',
'BY' => 'Belarus',
'BE' => 'Belgium',
'BZ' => 'Belize',
'BJ' => 'Benin',
'BM' => 'Bermuda',
'BT' => 'Bhutan',
'BO' => 'Bolivia',
'BA' => 'Bosnia And Herzegovina',
'BW' => 'Botswana',
'BV' => 'Bouvet Island',
'BR' => 'Brazil',
'IO' => 'British Indian Ocean Territory',
'BN' => 'Brunei Darussalam',
'BG' => 'Bulgaria',
'BF' => 'Burkina Faso',
'BI' => 'Burundi',
'KH' => 'Cambodia',
'CM' => 'Cameroon',
'CA' => 'Canada',
'CV' => 'Cape Verde',
'KY' => 'Cayman Islands',
'CF' => 'Central African Republic',
'TD' => 'Chad',
'CL' => 'Chile',
'CN' => 'China',
'CX' => 'Christmas Island',
'CC' => 'Cocos Island',
'CO' => 'Colombia',
'KM' => 'Comoros',
'CG' => 'Congo',
'CD' => 'Congo, Democratic Republic',
'CK' => 'Cook Islands',
'CR' => 'Costa Rica',
'CI' => 'Cote D\'Ivoire',
'HR' => 'Croatia',
'CU' => 'Cuba',
'CY' => 'Cyprus',
'CZ' => 'Czech Republic',
'DK' => 'Denmark',
'DJ' => 'Djibouti',
'DM' => 'Dominica',
'DO' => 'Dominican Republic',
'EC' => 'Ecuador',
'EG' => 'Egypt',
'SV' => 'El Salvador',
'GQ' => 'Equatorial Guinea',
'ER' => 'Eritrea',
'EE' => 'Estonia',
'ET' => 'Ethiopia',
'FK' => 'Falkland Islands',
'FO' => 'Faroe Islands',
'FJ' => 'Fiji',
'FI' => 'Finland',
'FR' => 'France',
'GF' => 'French Guiana',
'PF' => 'French Polynesia',
'TF' => 'French Southern Territories',
'GA' => 'Gabon',
'GM' => 'Gambia',
'GE' => 'Georgia',
'DE' => 'Germany',
'GH' => 'Ghana',
'GI' => 'Gibraltar',
'GR' => 'Greece',
'GL' => 'Greenland',
'GD' => 'Grenada',
'GP' => 'Guadeloupe',
'GU' => 'Guam',
'GT' => 'Guatemala',
'GG' => 'Guernsey',
'GN' => 'Guinea',
'GW' => 'Guinea-Bissau',
'GY' => 'Guyana',
'HT' => 'Haiti',
'HM' => 'Heard Island & Mcdonald Islands',
'VA' => 'Holy See (Vatican City State)',
'HN' => 'Honduras',
'HK' => 'Hong Kong',
'HU' => 'Hungary',
'IS' => 'Iceland',
'IN' => 'India',
'ID' => 'Indonesia',
'IR' => 'Iran, Islamic Republic Of',
'IQ' => 'Iraq',
'IE' => 'Ireland',
'IM' => 'Isle Of Man',
'IL' => 'Israel',
'IT' => 'Italy',
'JM' => 'Jamaica',
'JP' => 'Japan',
'JE' => 'Jersey',
'JO' => 'Jordan',
'KZ' => 'Kazakhstan',
'KE' => 'Kenya',
'KI' => 'Kiribati',
'KR' => 'Korea',
'KW' => 'Kuwait',
'KG' => 'Kyrgyzstan',
'LA' => 'Lao People\'s Democratic Republic',
'LV' => 'Latvia',
'LB' => 'Lebanon',
'LS' => 'Lesotho',
'LR' => 'Liberia',
'LY' => 'Libyan Arab Jamahiriya',
'LI' => 'Liechtenstein',
'LT' => 'Lithuania',
'LU' => 'Luxembourg',
'MO' => 'Macao',
'MK' => 'Macedonia',
'MG' => 'Madagascar',
'MW' => 'Malawi',
'MY' => 'Malaysia',
'MV' => 'Maldives',
'ML' => 'Mali',
'MT' => 'Malta',
'MH' => 'Marshall Islands',
'MQ' => 'Martinique',
'MR' => 'Mauritania',
'MU' => 'Mauritius',
'YT' => 'Mayotte',
'MX' => 'Mexico',
'FM' => 'Micronesia',
'MD' => 'Moldova',
'MC' => 'Monaco',
'MN' => 'Mongolia',
'ME' => 'Montenegro',
'MS' => 'Montserrat',
'MA' => 'Morocco',
'MZ' => 'Mozambique',
'MM' => 'Myanmar',
'NA' => 'Namibia',
'NR' => 'Nauru',
'NP' => 'Nepal',
'NL' => 'Netherlands',
'AN' => 'Netherlands',
'NC' => 'New Caledonia',
'NZ' => 'New Zealand',
'NI' => 'Nicaragua',
'NE' => 'Niger',
'NG' => 'Nigeria',
'NU' => 'Niue',
'NF' => 'Norfolk Island',
'MP' => 'Northern Mariana Islands',
'NO' => 'Norway',
'OM' => 'Oman',
'PK' => 'Pakistan',
'PW' => 'Palau',
'PS' => 'Palestine',
'PA' => 'Panama',
'PG' => 'Papua New Guinea',
'PY' => 'Paraguay',
'PE' => 'Peru',
'PH' => 'Philippines',
'PN' => 'Pitcairn',
'PL' => 'Poland',
'PT' => 'Portugal',
'PR' => 'Puerto Rico',
'QA' => 'Qatar',
'RE' => 'Reunion',
'RO' => 'Romania',
'RU' => 'Russia',
'RW' => 'Rwanda',
'BL' => 'Saint Barthelemy',
'SH' => 'Saint Helena',
'KN' => 'Saint Kitts And Nevis',
'LC' => 'Saint Lucia',
'MF' => 'Saint Martin',
'PM' => 'Saint Pierre And Miquelon',
'VC' => 'Saint Vincent And Grenadines',
'WS' => 'Samoa',
'SM' => 'San Marino',
'ST' => 'Sao Tome And Principe',
'SA' => 'Saudi Arabia',
'SN' => 'Senegal',
'RS' => 'Serbia',
'SC' => 'Seychelles',
'SL' => 'Sierra Leone',
'SG' => 'Singapore',
'SK' => 'Slovakia',
'SI' => 'Slovenia',
'SB' => 'Solomon Islands',
'SO' => 'Somalia',
'ZA' => 'South Africa',
'GS' => 'South Georgia And Sandwich Isl.',
'ES' => 'Spain',
'LK' => 'Sri Lanka',
'SD' => 'Sudan',
'SR' => 'Suriname',
'SJ' => 'Svalbard And Jan Mayen',
'SZ' => 'Swaziland',
'SE' => 'Sweden',
'CH' => 'Switzerland',
'SY' => 'Syrian Arab Republic',
'TW' => 'Taiwan',
'TJ' => 'Tajikistan',
'TZ' => 'Tanzania',
'TH' => 'Thailand',
'TL' => 'Timor-Leste',
'TG' => 'Togo',
'TK' => 'Tokelau',
'TO' => 'Tonga',
'TT' => 'Trinidad And Tobago',
'TN' => 'Tunisia',
'TR' => 'Turkey',
'TM' => 'Turkmenistan',
'TC' => 'Turks And Caicos Islands',
'TV' => 'Tuvalu',
'UG' => 'Uganda',
'UA' => 'Ukraine',
'AE' => 'United Arab Emirates',
'GB' => 'United Kingdom',
'US' => 'United States',
'UM' => 'United States Outlying Islands',
'UY' => 'Uruguay',
'UZ' => 'Uzbekistan',
'VU' => 'Vanuatu',
'VE' => 'Venezuela',
'VN' => 'Viet Nam',
'VG' => 'Virgin Islands, British',
'VI' => 'Virgin Islands, U.S.',
'WF' => 'Wallis And Futuna',
'EH' => 'Western Sahara',
'YE' => 'Yemen',
'ZM' => 'Zambia',
'ZW' => 'Zimbabwe',
);
return $countries_data;
}
}

View File

@@ -0,0 +1,605 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Handle_Post_Notification {
public $is_wp_5 = false;
public $is_rest_request = false;
public $do_post_notification_via_wp_5_hook = false;
public $do_post_notification_for = 0;
public function __construct() {
global $wp_version;
// Action is available after WordPress 2.3.0+
add_action( 'transition_post_status', array( $this, 'es_post_publish_callback' ), 10, 3 );
// Action is available WordPress 5.0+
add_action( 'rest_after_insert_post', array( $this, 'handle_post_publish' ), 10, 3 );
// Filter is available after WordPress 4.7.0+
add_filter( 'rest_pre_insert_post', array( $this, 'prepare_post_data' ), 10, 2 );
if ( version_compare( $wp_version, '5.0.0', '>=' ) ) {
$this->is_wp_5 = true;
}
add_action( 'ig_es_refresh_post_notification_content', array( $this, 'refresh_post_content' ), 10, 2 );
add_action( 'init', array( $this, 'init' ) );
}
/**
* Init hooks required for email queued admin notice functionality
*/
public function init() {
$post_types = array( 'post', 'page' );
$custom_post_types = ES_Common::get_custom_post_types();
$post_types = array_merge( $post_types, $custom_post_types );
foreach ( $post_types as $post_type ) {
add_filter( 'rest_prepare_' . $post_type, array( $this, 'add_generated_post_mailing_queue_ids' ), 10, 3 );
}
add_action( 'admin_notices', array( $this, 'show_emails_queued_notice' ) );
add_action( 'admin_footer', array( $this, 'enqueue_admin_scripts' ) );
}
public function prepare_post_data( $prepared_post, $request ) {
$this->is_rest_request = true;
return $prepared_post;
}
public function handle_post_publish( $post, $requst, $insert ) {
// If it's inserted for the first time????
// Not able to check whether it'a first time post or nth times
if ( is_object( $post ) && ( $post instanceof WP_Post ) ) { // Do it for the first time only
if ( $this->do_post_notification_via_wp_5_hook ) {
$post_id = $post->ID;
if ( $post_id == $this->do_post_notification_for ) {
$this->queue_post_notifications( $post_id );
}
}
}
}
public function es_post_publish_callback( $post_status, $original_post_status, $post ) {
if ( ( 'publish' == $post_status ) && ( 'publish' != $original_post_status ) ) {
if ( is_object( $post ) ) {
$post_id = $post->ID;
if ( ! empty( $post_id ) ) {
$post_date = $post->post_date;
$last_year_date = gmdate( 'Y-m-d H:i:s', strtotime('-1 year') );
$post_date_timestamp = strtotime( $post_date );
$last_year_date_timestamp = strtotime( $last_year_date );
$old_post = $post_date_timestamp < $last_year_date_timestamp;
$old_post_notification_disabled = apply_filters( 'ig_es_disable_old_post_notification', true );
if ( $old_post && $old_post_notification_disabled ) {
// don't send post notification to old post
return;
}
$is_post_notified = get_post_meta( $post_id, 'ig_es_is_post_notified', true );
//Return if post notification is already sent once.
if ( $is_post_notified ) {
return;
}
if ( $this->is_wp_5 && $this->is_rest_request ) {
$this->do_post_notification_via_wp_5_hook = true;
$this->do_post_notification_for = $post_id;
} else {
$this->queue_post_notifications( $post_id );
}
}
}
}
}
public function queue_post_notifications( $post_id ) {
if ( ! empty( $post_id ) ) {
$notifications = ES()->campaigns_db->get_campaigns_by_post_id( $post_id );
if ( count( $notifications ) > 0 ) {
$post_mailing_queue_ids = array();
foreach ( $notifications as $notification ) {
$notification_id = $notification['id'];
$notification_body = $notification['body'];
$notification_subject = $notification['name'];
if ( ! empty( $notification_subject ) && ! empty( $notification_body ) ) {
$list_id = $notification['list_ids'];
if ( ! empty( $list_id ) ) {
$list_id = explode( ',', $list_id );
}
$post = get_post( $post_id );
if ( is_object( $post ) ) {
/*
* Prepare Subject
* Prepare Body
* Add entry into mailing queue table
*/
// Prepare subject
$post_subject = self::prepare_subject( $notification_subject, $post );
if ( ES_Common::contains_posts_block( $notification_body ) ) {
$post_content = ES_Common::replace_single_posts_block( $notification_body, array( $post_id ) );
} else {
$post_content = self::prepare_body( $notification_body, $post_id, 0, $notification_id );
}
$guid = ES_Common::generate_guid( 6 );
$data = array(
'hash' => $guid,
'campaign_id' => $notification['id'],
'subject' => $post_subject,
'body' => $post_content,
'count' => 0,
'status' => '',
'start_at' => '',
'finish_at' => '',
'created_at' => ig_get_current_date_time(),
'updated_at' => ig_get_current_date_time(),
'meta' => maybe_serialize(
array(
'post_id' => $post_id,
'type' => 'post_notification',
)
),
);
// Add entry into mailing queue table
$mailing_queue_id = ES_DB_Mailing_Queue::add_notification( $data );
if ( $mailing_queue_id ) {
$mailing_queue_hash = $guid;
$campaign_id = $notification['id'];
$emails_queued = ES_DB_Sending_Queue::queue_emails( $mailing_queue_id, $mailing_queue_hash, $campaign_id, $list_id );
if ( $emails_queued ) {
update_post_meta( $post_id, 'ig_es_is_post_notified', 1 );
$post_mailing_queue_ids[] = $mailing_queue_id;
}
}
}
}
}
if ( ! empty( $post_mailing_queue_ids ) ) {
$trasient_expiry_time_in_seconds = 3;
set_transient( 'ig_es_post_mailing_queue_ids_' . $post->ID, $post_mailing_queue_ids, $trasient_expiry_time_in_seconds );
}
}
}
}
public static function prepare_subject( $notification_subject, $post ) {
// convert post subject here
$post_title = $post->post_title;
$blog_charset = get_option( 'blog_charset' );
$post_title = html_entity_decode( $post_title, ENT_QUOTES, $blog_charset );
$post_subject = str_replace( '{{POSTTITLE}}', $post_title, $notification_subject );
$post_subject = str_replace( '{{post.title}}', $post_title, $post_subject );
$post_link = get_permalink( $post );
$post_subject = str_replace( '{{POSTLINK}}', $post_link, $post_subject );
$post_subject = str_replace( '{{post.link}}', $post_link, $post_subject );
if ( strpos( $post_subject, '{{POSTCATS}}' ) >= 0 || strpos( $post_subject, '{{post.cats}}' ) >= 0 ) {
$taxonomies = get_object_taxonomies( $post );
$post_cats = array();
if ( ! empty( $taxonomies ) ) {
foreach ( $taxonomies as $taxonomy ) {
$taxonomy_object = get_taxonomy( $taxonomy );
// Check if taxonomy is hierarchical e.g. have parent-child relationship like categories
if ( $taxonomy_object->hierarchical ) {
$post_terms = get_the_terms( $post, $taxonomy );
if ( ! empty( $post_terms ) ) {
foreach ( $post_terms as $term ) {
$term_name = $term->name;
$post_cats[] = $term_name;
}
}
}
}
}
$post_subject = str_replace( '{{POSTCATS}}', implode( ', ', $post_cats ), $post_subject );
$post_subject = str_replace( '{{post.cats}}', implode( ', ', $post_cats ), $post_subject );
}
return $post_subject;
}
public static function prepare_body( $es_templ_body, $post_id, $email_template_id ) {
$post = get_post( $post_id );
$post_key = 'post';
// Making $post as global using $GLOBALS['post'] key. Can't use 'post' key directly into $GLOBALS since PHPCS throws global variable assignment warning for 'post'.
$GLOBALS[ $post_key ] = $post;
//$es_templ_body = $this->workflow->variable_processor()->process_field( $value, $allow_html );
$post_date = ES_Common::convert_date_to_wp_date( $post->post_modified );
$es_templ_body = str_replace( '{{DATE}}', $post_date, $es_templ_body );
$es_templ_body = str_replace( '{{post.date}}', $post_date, $es_templ_body );
$post_title = get_the_title( $post );
$es_templ_body = str_replace( '{{POSTTITLE}}', $post_title, $es_templ_body );
$es_templ_body = str_replace( '{{post.title}}', $post_title, $es_templ_body );
$post_link = get_permalink( $post_id );
// Size of {{POSTIMAGE}}
$post_thumbnail = '';
$post_thumbnail_link = '';
$post_thumbnail_url = '';
if ( ( function_exists( 'has_post_thumbnail' ) ) && ( has_post_thumbnail( $post_id ) ) ) {
$es_post_image_size = get_option( 'ig_es_post_image_size', 'full' );
switch ( $es_post_image_size ) {
case 'full':
$post_thumbnail = get_the_post_thumbnail( $post_id, 'full' );
break;
case 'medium':
$post_thumbnail = get_the_post_thumbnail( $post_id, 'medium' );
break;
case 'thumbnail':
default:
$post_thumbnail = get_the_post_thumbnail( $post_id, 'thumbnail' );
break;
}
}
if ( '' != $post_thumbnail ) {
$post_thumbnail_link = "<a href='" . $post_link . "' target='_blank'>" . $post_thumbnail . '</a>';
}
$es_templ_body = str_replace( '{{POSTIMAGE}}', $post_thumbnail_link, $es_templ_body );
$es_templ_body = str_replace( '{{post.image}}', $post_thumbnail_link, $es_templ_body );
$post_thumbnail_id = get_post_thumbnail_id( $post_id );
if ( ! empty( $post_thumbnail_id ) ) {
$post_thumbnail_url = wp_get_attachment_url( $post_thumbnail_id );
}
$es_templ_body = str_replace( '{{POSTIMAGE-URL}}', $post_thumbnail_url, $es_templ_body );
$es_templ_body = str_replace( '{{post.image_url}}', $post_thumbnail_url, $es_templ_body );
// Get post description
$post_description_length = 50;
$post_description = $post->post_content;
$post_description = strip_tags( self::strip_shortcodes( $post_description ) );
$words = explode( ' ', $post_description, $post_description_length + 1 );
if ( count( $words ) > $post_description_length ) {
array_pop( $words );
array_push( $words, '...' );
$post_description = implode( ' ', $words );
}
$es_templ_body = str_replace( '{{POSTDESC}}', $post_description, $es_templ_body );
$es_templ_body = str_replace( '{{post.description}}', $post_description, $es_templ_body );
// Get post excerpt
$post_excerpt = get_the_excerpt( $post );
$post_excerpt = wpautop( $post_excerpt );
$post_excerpt = wptexturize( $post_excerpt );
$es_templ_body = str_replace( '{{POSTEXCERPT}}', $post_excerpt, $es_templ_body );
$es_templ_body = str_replace( '{{post.excerpt}}', $post_excerpt, $es_templ_body );
$more_tag_data = get_extended( $post->post_content );
// Get text before the more(<!--more-->) tag.
$text_before_more_tag = $more_tag_data['main'];
$strip_excluded_tags = ig_es_get_strip_excluded_tags();
$text_before_more_tag = strip_tags( self::strip_shortcodes( $text_before_more_tag ), implode( '', $strip_excluded_tags ) );
$es_templ_body = str_replace( '{{POSTMORETAG}}', $text_before_more_tag, $es_templ_body );
$es_templ_body = str_replace( '{{post.more_tag}}', $text_before_more_tag, $es_templ_body );
// get post author
$post_author_id = $post->post_author;
$post_author = get_the_author_meta( 'display_name', $post_author_id );
$post_author_avatar_url = get_avatar_url( $post_author_id );
$author_avatar = '<img src="' . esc_attr( $post_author_avatar_url ) . '" alt="' . esc_attr( $post_author ) . '" width="auto" height="auto" />';
$es_templ_body = str_replace( '{{POSTAUTHOR}}', $post_author, $es_templ_body );
$es_templ_body = str_replace( '{{post.author}}', $post_author, $es_templ_body );
$es_templ_body = str_replace( '{{POSTLINK-ONLY}}', $post_link, $es_templ_body );
$es_templ_body = str_replace( '{{post.link_only}}', $post_link, $es_templ_body );
$es_templ_body = str_replace( '{{POSTAUTHORAVATAR}}', $author_avatar, $es_templ_body );
$es_templ_body = str_replace( '{{post.author_avatar}}', $author_avatar, $es_templ_body );
$es_templ_body = str_replace( '{{POSTAUTHORAVATARLINK-ONLY}}', $post_author_avatar_url, $es_templ_body );
$es_templ_body = str_replace( '{{post.author_avatar_url}}', $post_author_avatar_url, $es_templ_body );
// Check if template has {{POSTCATS}} placeholder.
if ( strpos( $es_templ_body, '{{POSTCATS}}' ) >= 0 || strpos( $es_templ_body, '{{post.cats}}' ) >= 0 ) {
$taxonomies = get_object_taxonomies( $post );
$post_cats = array();
if ( ! empty( $taxonomies ) ) {
foreach ( $taxonomies as $taxonomy ) {
$taxonomy_object = get_taxonomy( $taxonomy );
// Check if taxonomy is hierarchical e.g. have parent-child relationship like categories
if ( $taxonomy_object->hierarchical ) {
$post_terms = get_the_terms( $post, $taxonomy );
if ( ! empty( $post_terms ) ) {
foreach ( $post_terms as $term ) {
$term_name = $term->name;
$post_cats[] = $term_name;
}
}
}
}
}
$es_templ_body = str_replace( '{{POSTCATS}}', implode( ', ', $post_cats ), $es_templ_body );
$es_templ_body = str_replace( '{{post.cats}}', implode( ', ', $post_cats ), $es_templ_body );
}
if ( '' != $post_link ) {
$post_link_with_title = "<a href='" . $post_link . "' target='_blank'>" . $post_title . '</a>';
$es_templ_body = str_replace( '{{POSTLINK-WITHTITLE}}', $post_link_with_title, $es_templ_body );
$es_templ_body = str_replace( '{{post.link_with_title}}', $post_link_with_title, $es_templ_body );
$post_link = "<a href='" . urldecode( $post_link ) . "' target='_blank'>" . urldecode( $post_link ) . '</a>';
}
$es_templ_body = str_replace( '{{POSTLINK}}', $post_link, $es_templ_body );
$es_templ_body = str_replace( '{{post.link}}', $post_link, $es_templ_body );
// Get full post
$post_full = $post->post_content;
$post_full = wpautop( $post_full );
$es_templ_body = str_replace( '{{POSTFULL}}', $post_full, $es_templ_body );
$es_templ_body = str_replace( '{{post.full}}', $post_full, $es_templ_body );
// add pre header as post excerpt
/*
if ( ! empty( $post_excerpt ) ) {
$es_templ_body = '<span class="es_preheader" style="display: none !important; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;">' . $post_excerpt . '</span>' . $es_templ_body;
}
*/
if ( $email_template_id > 0 ) {
$es_templ_body = ES_Common::es_process_template_body( $es_templ_body, $email_template_id );
}
return apply_filters( 'ig_es_post_notification_body', $es_templ_body, $post_id );
}
public static function refresh_post_content( $content, $args ) {
$campaign_id = $args['campaign_id'];
$post_id = $args['post_id'];
$post = get_post( $post_id );
$template_id = ES()->campaigns_db->get_template_id_by_campaign( $campaign_id );
$template = get_post( $template_id );
$campaign = ES()->campaigns_db->get( $campaign_id );
$campaign_subject = $campaign['name'];
if ( ! empty( $campaign['body'] ) ) {
$template_content = $campaign['body'];
} else {
$template_content = $template->post_content;
}
$content['subject'] = self::prepare_subject( $campaign_subject, $post );
if ( ES_Common::contains_posts_block( $template_content ) ) {
$content['body'] = ES_Common::replace_single_posts_block( $template_content, array( $post_id ) );
} else {
$content['body'] = self::prepare_body( $template_content, $post_id, $template_id );
}
return $content;
}
/**
* Add generated post mailing queue ids to REST response.
*
* @since 5.4.0
*
* @param object $response REST response.
* @param object $post Post object.
* @param array $request REST request.
*
* @return array $response REST response.
*/
public function add_generated_post_mailing_queue_ids( $response, $post, $request ) {
if ( $post instanceof WP_Post ) {
$response->data['post_mailing_queue_ids'] = array();
$post_mailing_queue_ids = get_transient( 'ig_es_post_mailing_queue_ids_' . $post->ID );
if ( ! empty( $post_mailing_queue_ids ) ) {
$response->data['post_mailing_queue_ids'] = $post_mailing_queue_ids;
}
}
return $response;
}
/**
* Show emails queued notice when post is published in Classic Editor
*
* @since 5.4.0
*/
public function show_emails_queued_notice() {
if ( $this->is_post_edit_screen() ) {
global $post;
if ( $post instanceof WP_Post ) {
$post_mailing_queue_ids = get_transient( 'ig_es_post_mailing_queue_ids_' . $post->ID );
if ( ! empty( $post_mailing_queue_ids ) ) {
$notice_text = $this->get_emails_queued_notice_text();
$report_page_url = menu_page_url( 'es_reports', false );
?>
<div id="ig-es-reports-queued-notice" class="notice notice-success">
<p>
<strong><?php echo esc_html( $notice_text ); ?></strong>
<a href="<?php echo esc_url( $report_page_url ); ?>" target="_blank"><?php echo esc_html__( 'View Reports', 'email-subscribers' ); ?></a>
</p>
</div>
<?php
}
}
}
}
/**
* Check if current screen is post edit screen
*
* @since 5.4.0
*
* @return boolean $is_post_edit_screen True if current screen is post edit screen else false
*/
public function is_post_edit_screen() {
$current_screen = get_current_screen();
$is_post_edit_screen = 'post' === $current_screen->base;
return $is_post_edit_screen;
}
/**
* Enqueue admin scripts on post edit screen
*
* @since 5.4.0
*/
public function enqueue_admin_scripts() {
if ( ! $this->is_post_edit_screen() ) {
// Return if not on post edit screen.
return;
}
$current_screen = get_current_screen();
$is_block_editor_page = method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor();
if ( ! $is_block_editor_page ) {
// Return if Gutenberg isn't used.
return;
}
$report_page_url = menu_page_url( 'es_reports', false );
$notice_text = $this->get_emails_queued_notice_text();
?>
<script type="text/javascript">
jQuery(document).ready(function(){
if ( 'undefined' !== typeof wp.data && 'undefined' !== typeof wp.data.subscribe ) {
const { subscribe } = wp.data;
const report_page_url = '<?php echo esc_js( $report_page_url ); ?>';
let notice_shown = false;
const unsubscribe = subscribe( () => {
const coreEditor = wp.data.select( 'core/editor' );
if ( 'undefined' === typeof coreEditor || 'undefined' === typeof coreEditor.isPublishingPost ) {
return;
}
const isPublishingPost = coreEditor.isPublishingPost();
// wait for the post to be published before showing the notice
if ( isPublishingPost ) {
notice_shown = false;
return;
}
if ( 'undefined' === typeof coreEditor.isCurrentPostPublished ) {
return;
}
const currentPostPublished = coreEditor.isCurrentPostPublished();
if ( currentPostPublished ) {
if ( 'undefined' === typeof coreEditor.getCurrentPost ) {
return;
}
const currentPost = coreEditor.getCurrentPost();
if ( 'undefined' === typeof currentPost.post_mailing_queue_ids || currentPost.post_mailing_queue_ids.length === 0 ) {
return;
}
if ( ! notice_shown ) {
notice_shown = true;
setTimeout(() => {
wp.data.dispatch( 'core/notices' ).createNotice(
'success', // Can be one of: success, info, warning, error.
'<?php echo esc_js( $notice_text ); ?>', // Text string to display.
{
type: "snackbar",
isDismissible: true, // Whether the user can dismiss the notice.
// Any actions the user can perform.
actions: [
{
onClick: () => {
window.open(report_page_url, '_blank').focus();
},
label: '<?php echo esc_attr__( 'View Reports', 'email-subscribers' ); ?>',
},
],
}
);
}, 1000);
}
}
} );
}
});
</script>
<?php
}
/**
* Get admin notice text.
*
* @since 5.4.0
*
* @return string $notice_text Admin Notice text.
*/
public function get_emails_queued_notice_text() {
global $post;
$notice_text = '';
if ( $post instanceof WP_Post ) {
$post_type = $post->post_type;
$post_type_object = get_post_type_object( $post_type );
$post_type__name = $post_type_object->labels->singular_name;
/* translators: %s: Post type name */
$notice_text = sprintf( __( 'Notification emails has been queued for this %s.', 'email-subscribers' ), strtolower( $post_type__name ) );
}
return $notice_text;
}
public static function strip_shortcodes( $content ) {
$content = preg_replace('/\[[^\[\]]*\]/', '', $content);
return $content;
}
}

View File

@@ -0,0 +1,670 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
/**
* Handle subscription
*
* Class ES_Handle_Subscription
*
* @since 4.0.0
*/
class ES_Handle_Subscription {
/**
* Subscriber Email
*
* @since 4.0.0
* @var
*/
public $email;
/**
* Subscriber Name
*
* @since 4.0.0
* @var
*/
public $name;
/**
* Subscriber First Name
*
* @since 4.0.0
* @var
*/
public $first_name;
/**
* Subscriber Last Name
*
* @since 4.0.0
* @var
*/
public $last_name;
/**
* Optin type
*
* @since 4.0.0
* @var
*/
public $es_optin_type;
/**
* List Id
*
* @since 4.0.0
* @var
*/
public $list_ids;
/**
* List Hashes
*
* @since 4.6.12
* @var
*/
public $list_hashes;
/**
* Nonce value
*
* @since 4.0.0
* @var
*/
public $es_nonce;
/**
* Subscriber Status
*
* @since 4.0.0
* @var
*/
public $status;
/**
* To check if double-optin or not
*
* @since 4.0.0
* @var
*/
public $is_double_optin = false;
/**
* Guid
*
* @since 4.0.0
* @var
*/
public $guid;
/**
* Database Id
*
* @since 4.0.0
* @var
*/
public $db_id;
/**
* Form id
*
* @since 4.0.0
* @var
*/
public $form_id;
/**
* IP Address
*
* @since 4.7.3
* @var
*/
public $ip_address;
/**
* Reference Site
*
* @since 5.4.0
* @var
*/
public $reference_site;
/**
* If the user is subscribed from Rainmaker
*
* @since 4.0.0
* @var
*/
private $from_rainmaker = false;
/**
* ES_Handle_Subscription constructor.
*
* @param bool $from_rainmaker
*
* @since 4.0.0
*/
public function __construct( $from_rainmaker = false ) {
if ( defined( 'DOING_AJAX' ) && ( true === DOING_AJAX ) ) {
add_action( 'wp_ajax_es_add_subscriber', array( $this, 'process_ajax_request' ), 10 );
add_action( 'wp_ajax_nopriv_es_add_subscriber', array( $this, 'process_ajax_request' ), 10 );
}
$this->from_rainmaker = $from_rainmaker;
$this->handle_subscription();
}
/**
* Process form submission via ajax call
*/
public function process_ajax_request() {
$es_subscribe = ! empty( $_POST['esfpx_es-subscribe'] ) ? sanitize_text_field( wp_unslash( $_POST['esfpx_es-subscribe'] ) ) : '';
if ( ! empty( $es_subscribe ) && wp_verify_nonce( $es_subscribe, 'es-subscribe' ) ) {
$nonce_verified = true;
}
if ( ! empty( $es_subscribe ) ) {
defined( 'IG_ES_RETURN_HANDLE_RESPONSE' ) || define( 'IG_ES_RETURN_HANDLE_RESPONSE', true );
$response = $this->process_request( wp_unslash( $_POST ) );
} else {
$response = array( 'status' => 'ERROR', 'message' => 'es_unexpected_error_notice', );
}
$response = $this->do_response( $response );
wp_send_json( $response );
}
/**
* Process request
*
* @param array $external_form_data data from external form/APIs.
*
* @since 4.0.0
*
* @modified 4.5.7 Added $external_form_data parameter.
* @modified 4.8.2 Added IG_ES_RETURN_HANDLE_RESPONSE const.
*
* @return void | array
*/
public function process_request( $external_form_data = array() ) {
$response = array(
'status' => 'ERROR',
'message' => '',
);
$es = ! empty( $_POST['es'] ) ? sanitize_text_field( wp_unslash( $_POST['es'] ) ) : '';
$es_form_id = ! empty( $_POST['esfpx_form_id'] ) ? sanitize_text_field( wp_unslash( $_POST['esfpx_form_id'] ) ) : '';
$es_subscribe = ! empty( $_POST['esfpx_es-subscribe'] ) ? sanitize_text_field( wp_unslash( $_POST['esfpx_es-subscribe'] ) ) : '';
if ( ! empty( $es_subscribe ) && wp_verify_nonce( $es_subscribe, 'es-subscribe' ) ) {
$nonce_verified = true;
}
$doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
$return_response = defined( 'IG_ES_RETURN_HANDLE_RESPONSE' ) && IG_ES_RETURN_HANDLE_RESPONSE;
// Verify nonce only if it is submitted through Icegram Express' subscription form else check if we have form data in $external_form_data.
if ( ( 'subscribe' === $es ) || ! empty( $external_form_data ) ) {
// Get form data from external source if passed.
if ( ! empty( $external_form_data ) ) {
$form_data = $external_form_data;
} else {
// If external form data is not passed then get form data from $_POST.
$form_data = wp_unslash( $_POST );
}
$validate_response = $this->validate_data( $form_data );
if ( 'ERROR' === $validate_response['status'] ) {
// We want to pretend as "SUCCESS" for blocked emails.
// So, we are setting as "SUCCESS" even if this email is blocked
if ( 'es_email_address_blocked' === $validate_response['message'] ) {
$validate_response['status'] = 'SUCCESS';
$validate_response['message'] = 'es_optin_success_message';
}
$response = $this->do_response( $validate_response );
if ( $return_response ) {
return $response;
} elseif ( $doing_ajax ) {
wp_send_json( $response );
} else {
return $response;
}
}
$email = ! empty( $form_data['esfpx_email'] ) ? sanitize_email( $form_data['esfpx_email'] ) : '';
$name = ! empty( $form_data['esfpx_name'] ) ? sanitize_text_field( $form_data['esfpx_name'] ) : '';
$ip_address = ! empty( $form_data['esfpx_ip_address'] ) ? sanitize_text_field( $form_data['esfpx_ip_address'] ) : '';
$first_name = '';
$last_name = '';
if ( ! empty( $name ) ) {
// Get First Name and Last Name from Name.
$name_parts = ES_Common::prepare_first_name_last_name( $name );
$first_name = $name_parts['first_name'];
$last_name = $name_parts['last_name'];
}
$this->name = $first_name;
$this->first_name = $first_name;
$this->last_name = $last_name;
$this->email = $email;
$this->ip_address = $ip_address;
$this->list_hashes = isset( $form_data['esfpx_lists'] ) ? $form_data['esfpx_lists'] : array();
$this->es_nonce = isset( $form_data['esfpx_es-subscribe'] ) ? trim( $form_data['esfpx_es-subscribe'] ) : '';
$this->form_id = isset( $form_data['esfpx_form_id'] ) ? trim( $form_data['esfpx_form_id'] ) : 0;
$this->reference_site = isset( $form_data['esfpx_reference_site'] ) ? esc_url_raw( $form_data['esfpx_reference_site'] ) : null;
$this->es_optin_type = get_option( 'ig_es_optin_type' );
$this->guid = ES_Common::generate_guid();
if ( in_array( $this->es_optin_type, array( 'double_opt_in', 'double_optin' ) ) ) { // Backward Compatibility
$this->is_double_optin = true;
$this->status = 'unconfirmed';
} else {
$this->status = 'subscribed';
}
if ( ! empty( $this->list_hashes ) ) {
$list_hash_str = ES()->lists_db->prepare_for_in_query( $this->list_hashes );
$where = "hash IN ($list_hash_str)";
$this->list_ids = ES()->lists_db->get_column_by_condition( 'id', $where );
if ( ! empty( $this->list_ids ) ) {
$is_new = true;
/**
* Check if subscribers exists?
* - If yes, get id and save lists into ig_lists_contacts table
* - If not, create contact and then save list
*/
$contact_id = ES()->contacts_db->get_contact_id_by_email( $this->email );
if ( ! $contact_id ) {
$data = array();
$data['first_name'] = $this->first_name;
$data['last_name'] = $this->last_name;
$data['source'] = 'form';
$data['form_id'] = $this->form_id;
$data['email'] = $this->email;
$data['ip_address'] = $this->ip_address;
$data['status'] = 'verified';
$data['hash'] = $this->guid;
$data['created_at'] = ig_get_current_date_time();
$data['updated_at'] = null;
$data['meta'] = null;
if ( ! is_null( $this->reference_site ) ) {
$data['reference_site'] = $this->reference_site;
}
$data = apply_filters( 'ig_es_add_subscriber_data', $data );
$data = apply_filters( 'ig_es_add_custom_field_data' , $data, $form_data );
if ( 'ERROR' === $data['status'] ) {
$response = $this->do_response( $validate_response );
if ( $return_response ) {
return $response;
} elseif ( $doing_ajax ) {
wp_send_json( $response );
} else {
return $response;
}
}
$contact_id = ES()->contacts_db->insert( $data );
// do_action( 'ig_es_contact_added', $data);
} else {
$is_new = false;
}
$contact_lists = ES()->lists_contacts_db->get_list_ids_by_contact( $contact_id, 'subscribed' );
if ( empty( array_diff( $this->list_ids, $contact_lists ) ) ) {
$response['message'] = 'es_email_exists_notice';
$response = $this->do_response( $response );
if ( $return_response ) {
return $response;
} elseif ( $doing_ajax ) {
wp_send_json( $response );
} else {
return $response;
}
}
// If contact already exists then update the contact data.
if ( ! $is_new ) {
$data = array();
// Update first name and last name when both are provided
if ( ! empty( $this->first_name ) && ! empty( $this->last_name ) ) {
$data['first_name'] = $this->first_name;
$data['last_name'] = $this->last_name;
}
if ( ! empty( $this->ip_address ) ) {
$data['ip_address'] = $this->ip_address;
}
if ( ! empty( $data ) ) {
$data['updated_at'] = ig_get_current_date_time();
ES()->contacts_db->update( $contact_id, $data );
}
}
$optin_type = $this->is_double_optin ? IG_DOUBLE_OPTIN : IG_SINGLE_OPTIN;
$list_contact_data = array(
'contact_id' => $contact_id,
'status' => $this->status,
'subscribed_at' => ( 'subscribed' === $this->status ) ? ig_get_current_date_time() : '',
'optin_type' => $optin_type,
'subscribed_ip' => '',
);
ES()->lists_contacts_db->add_contact_to_lists( $list_contact_data, $this->list_ids );
if ( $contact_id ) {
do_action( 'ig_es_contact_subscribe', $contact_id, $this->list_ids );
$this->db_id = $contact_id;
// Get comma(,) separated lists name based on ids.
$list_name = ES_Common::prepare_list_name_by_ids( $this->list_ids );
$merge_tags = array(
'email' => $this->email,
'contact_id' => $contact_id,
'name' => ES_Common::prepare_name_from_first_name_last_name( $this->first_name, $this->last_name ),
'first_name' => $this->first_name,
'last_name' => $this->last_name,
'guid' => $this->guid,
'list_name' => $list_name,
'list_ids' => $this->list_ids,
);
if ( $this->is_double_optin ) {
$response['message'] = 'es_optin_success_message';
do_action( 'ig_es_contact_unconfirmed', $merge_tags );
} else {
do_action( 'ig_es_contact_subscribed', $merge_tags );
// Send Notifications to admins
//ES()->mailer->send_add_new_contact_notification_to_admins( $merge_tags );
$response['message'] = 'es_optin_success_message';
}
$response['status'] = 'SUCCESS';
$form_settings = ES()->forms_db->get_form_settings( $es_form_id );
$action_after_submit = ! empty( $form_settings['action_after_submit'] ) ? $form_settings['action_after_submit'] : '';
if ( 'redirect_to_url' === $action_after_submit ) {
$redirection_url = ! empty( $form_settings['redirection_url'] ) ? $form_settings['redirection_url'] : '';
$is_hash_not_added = false === strpos( $redirection_url, '#' );
$response['redirection_url'] = $is_hash_not_added ? $redirection_url . '#' : $redirection_url;
}
} else {
$response['message'] = 'es_db_error_notice';
}
} else {
$response['status'] = 'SUCCESS';
$response['message'] = 'es_optin_success_message';
$response = $this->do_response( $response );
if ( $return_response ) {
return $response;
} elseif ( $doing_ajax ) {
wp_send_json( $response );
} else {
return $response;
}
}
} else {
$response['message'] = 'es_no_list_selected';
$response = $this->do_response( $response );
if ( $return_response ) {
return $response;
} elseif ( $doing_ajax ) {
wp_send_json( $response );
} else {
return $response;
}
}
} else {
$response['message'] = 'es_permission_denied_notice';
}
$response = $this->do_response( $response );
if ( $return_response ) {
return $response;
} elseif ( $doing_ajax ) {
wp_send_json( $response );
} else {
return $response;
}
}
/**
* Send Response
*
* @param $response
*
* @since 4.0.0
*
* @modify 5.6.1
*/
public function do_response( $response ) {
$message = isset( $response['message'] ) ? $response['message'] : '';
$response['message_text'] = '';
if ( ! empty( $message ) ) {
$response['message_text'] = $this->get_messages( $message );
}
return $response;
}
/**
* Validate subscribers data
*
* @param $data
*
* @return array|mixed|void
*
* @since 4.0.0
*
* @modify 5.6.7
*/
public function validate_data( $data ) {
$es_response = array(
'status' => 'ERROR',
'message' => '',
);
if ( ! $this->from_rainmaker ) {
// Honeypot validation
// $hp_key = "esfpx_es_hp" . wp_create_nonce( 'es_hp' );
$hp_key = 'esfpx_es_hp_email';
if ( ! isset( $data[ $hp_key ] ) || ! empty( $data[ $hp_key ] ) ) {
$es_response['message'] = 'es_unexpected_error_notice';
return $es_response;
}
}
$name = isset( $data['esfpx_name'] ) ? $data['esfpx_name'] : '';
if ( strlen( $name ) > 50 ) {
$es_response['message'] = 'es_invalid_name_notice';
return $es_response;
}
$email = isset( $data['esfpx_email'] ) ? $data['esfpx_email'] : '';
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
$es_response['message'] = 'es_invalid_email_notice';
return $es_response;
}
$is_domain_blocked = ES_Common::is_domain_blocked( $email );
// Store it blocked emails
if ( $is_domain_blocked ) {
$data = array(
'email' => $email,
'ip' => ig_es_get_ip(),
);
ES()->blocked_emails_db->insert( $data );
$es_response['status'] = 'ERROR';
$es_response['message'] = 'es_email_address_blocked';
return $es_response;
}
$data = apply_filters( 'ig_es_validate_subscribers_data', $data );
if ( ! empty( $data['status'] ) && 'ERROR' === $data['status'] ) {
$es_response = $data;
return $es_response;
}
$timeout = ES_Subscription_Throttling::throttle();
if ( $timeout > 0 ) {
$es_response['message'] = 'es_rate_limit_notice';
return $es_response;
}
$es_response['status'] = 'SUCCESS';
return $es_response;
}
/**
* Get Message description based on message
*
* @param $message
*
* @return array|mixed|string|void
*
* @since 4.0.0
*
* @modify 5.6.1
*/
public function get_messages( $message ) {
$ig_es_form_submission_success_message = get_option( 'ig_es_form_submission_success_message' );
$form_data = ES()->forms_db->get_form_by_id( $this->form_id );
$settings = ig_es_get_data( $form_data, 'settings', array() );
if ( ! empty( $settings ) ) {
$settings = maybe_unserialize( $settings );
$success_message = ! empty( $settings['success_message'] ) ? $settings['success_message'] : '';
}
$messages = array(
'es_empty_email_notice' => __( 'Please enter email address', 'email-subscribers' ),
'es_rate_limit_notice' => __( 'You need to wait for some time before subscribing again', 'email-subscribers' ),
'es_optin_success_message' => ! empty( $success_message ) ? $success_message : $ig_es_form_submission_success_message,
'es_email_exists_notice' => __( 'Email Address already exists!', 'email-subscribers' ),
'es_unexpected_error_notice' => __( 'Oops.. Unexpected error occurred.', 'email-subscribers' ),
'es_invalid_email_notice' => __( 'Invalid email address', 'email-subscribers' ),
'es_invalid_name_notice' => __( 'Invalid name', 'email-subscribers' ),
'es_try_later_notice' => __( 'Please try after some time', 'email-subscribers' ),
'es_db_error_notice' => __( 'Oops...unable to add subscriber', 'email-subscribers' ),
'es_permission_denied_notice' => __( 'You do not have permission to add subscriber', 'email-subscribers' ),
'es_no_list_selected' => __( 'Please select the list', 'email-subscribers' ),
'es_invalid_captcha' => __( 'Invalid Captcha', 'email-subscribers' ),
);
$messages = apply_filters( 'ig_es_subscription_messages', $messages );
if ( ! empty( $messages ) ) {
return isset( $messages[ $message ] ) ? $messages[ $message ] : '';
}
return $messages;
}
/**
* Method to handle external subscriptions.
*
* @since 4.4.7
*
* @modify 5.6.2
**/
public function handle_subscription() {
$external_action = ig_es_get_request_data( 'ig_es_external_action' );
if ( ! empty( $external_action ) && 'subscribe' === $external_action ) {
$subscription_api_enabled = 'yes' === get_option( 'ig_es_allow_api', 'yes' );
if ( ! $subscription_api_enabled ) {
return;
}
$list_hash = ig_es_get_request_data( 'list' );
$lists_hash = ig_es_get_request_data( 'lists' );
if ( ! empty( $list_hash ) ) {
$list = ES()->lists_db->get_by( 'hash', $list_hash );
$lists = array( $list );
$lists_hash = array( $list_hash );
} elseif ( ! empty( $lists_hash ) ) {
$lists = ES()->lists_db->get_lists_by_hash( $lists_hash );
}
if ( ! empty( $lists ) ) {
$name = ig_es_get_request_data( 'name' );
$email = ig_es_get_request_data( 'email' );
$hp_email = ig_es_get_request_data( 'es_hp_email' );
$ip_address = ig_es_get_request_data( 'ip_address' );
$form_data = array(
'esfpx_name' => $name,
'esfpx_email' => $email,
'esfpx_es_hp_email' => $hp_email,
'esfpx_ip_address' => $ip_address,
'esfpx_lists' => $lists_hash,
'form_type' => 'external',
);
$response = $this->process_request( $form_data );
wp_send_json( $response );
}
}
$doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
// Run only when it is normal form submission and not ajax form submission.
if ( ! $doing_ajax ) {
$es_action = ig_es_get_post_data( 'es' );
if ( ! empty( $es_action ) && 'subscribe' === $es_action ) {
// Store the response, so that it can be shown while outputting the subscription form HTML.
$response = $this->process_request();
if ( ! empty ( $response['redirection_url'] ) ) {
wp_redirect( $response['redirection_url'] );
exit;
}
ES_Shortcode::$response = $response;
}
}
}
}
}

View File

@@ -0,0 +1,279 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Handle_Sync_Wp_User {
public static $instance;
public function __construct() {
// Sync upcoming WordPress users
// add_action( 'ig_es_sync_users_tabs_wordpress', array( $this, 'sync_wordpress_users_settings' ) );
// add_action( 'user_register', array( $this, 'sync_registered_wp_user' ) );
// add_action( 'delete_user', array( $this, 'delete_contact' ), 10, 1 );
}
/*
public function sync_wordpress_users_settings( $wordpress_tab ) {
if ( ! empty( $wordpress_tab['indicator_option'] ) ) {
update_option( $wordpress_tab['indicator_option'], 'no' );
}
$submitted = ig_es_get_post_data( 'submitted' );
if ( 'submitted' === $submitted ) {
$form_data = ig_es_get_post_data( 'form_data' );
$error = false;
if ( ! empty( $form_data['es_registered'] ) && 'YES' === $form_data['es_registered'] ) {
$list_id = ! empty( $form_data['es_registered_group'] ) ? $form_data['es_registered_group'] : 0;
if (0 === $list_id ) {
$message = __( 'Please select list', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
$error = true;
}
}
if ( ! $error ) {
update_option( 'ig_es_sync_wp_users', $form_data );
$message = __( 'Settings have been saved successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
}
}
$default_form_data = array(
'es_registered' => 'NO',
'es_registered_group' => 0,
);
$form_data = get_option( 'ig_es_sync_wp_users', array() );
$form_data = wp_parse_args( $form_data, $default_form_data );
?>
<table class="form-table">
<tbody>
<tr>
<th scope="row">
<label for="tag-image">
<?php esc_html_e( 'Sync WordPress Users?', 'email-subscribers' ); ?>
</label>
<p class="description"><?php esc_html_e( 'Whenever someone signup, it will automatically be added into selected list', 'email-subscribers' ); ?></p>
</th>
<td>
<select name="form_data[es_registered]" id="es_email_status">
<option value='NO'
<?php
if ('NO' == $form_data['es_registered'] ) {
echo "selected='selected'";
}
?>
><?php esc_html_e( 'No', 'email-subscribers' ); ?></option>
<option value='YES'
<?php
if ( 'YES' == $form_data['es_registered'] ) {
echo "selected='selected'";
}
?>
><?php esc_html_e( 'Yes', 'email-subscribers' ); ?></option>
</select>
</td>
</tr>
<tr>
<th>
<label for="tag-display-status">
<?php esc_html_e( 'Select List', 'email-subscribers' ); ?>
</label>
<p class="description"><?php esc_html_e( 'Select the list in which newly registered user will be subscribed to', 'email-subscribers' ); ?></p>
</th>
<td>
<select name="form_data[es_registered_group]">
<?php
$lists_dropdown = ES_Common::prepare_list_dropdown_options( $form_data['es_registered_group'], 'Select List' );
$allowedtags = ig_es_allowed_html_tags_in_esc();
echo wp_kses( $lists_dropdown , $allowedtags );
?>
</select>
</td>
</tr>
</tbody>
</table>
<input type="hidden" name="submitted" value="submitted"/>
<p style="padding-top:5px;">
<input type="submit" class="button-primary" value="<?php esc_html_e( 'Save Settings', 'email-subscribers' ); ?>"/>
</p>
<?php
}
*/
/**
* Sync/Add WP new user into ES
*
* @param $user_id
*
* @since 4.0
*
* @modify 4.3.12
*/
public function sync_registered_wp_user( $user_id ) {
$ig_es_sync_wp_users = get_option( 'ig_es_sync_wp_users', array() );
if ( ! empty( $ig_es_sync_wp_users ) ) {
$ig_es_sync_wp_users = maybe_unserialize( $ig_es_sync_wp_users );
$ig_es_registered = ( ! empty( $ig_es_sync_wp_users['es_registered'] ) ) ? $ig_es_sync_wp_users['es_registered'] : 'NO';
if ( 'YES' === $ig_es_registered ) {
$list_id = $ig_es_sync_wp_users['es_registered_group'];
// get user info
$user_info = get_userdata( $user_id );
if ( $user_info instanceof WP_User ) {
$user_first_name = $user_info->display_name;
$email = $user_info->user_email;
if ( empty( $user_first_name ) ) {
$user_first_name = ES_Common::get_name_from_email( $email );
}
// prepare data
$data = array(
'first_name' => $user_first_name,
'email' => $email,
'source' => 'wp',
'status' => 'verified',
'hash' => ES_Common::generate_guid(),
'created_at' => ig_get_current_date_time(),
'wp_user_id' => $user_id,
);
do_action( 'ig_es_add_contact', $data, $list_id );
}
}
}
}
/**
* Delete contact from ES when user deleted from WordPress
*
* @param $user_id
*
* @since 4.3.12
*/
public function delete_contact( $user_id = 0 ) {
$ig_es_sync_wp_users = get_option( 'ig_es_sync_wp_users', array() );
if ( ! empty( $ig_es_sync_wp_users ) ) {
$ig_es_sync_wp_users = maybe_unserialize( $ig_es_sync_wp_users );
$ig_es_registered = ( ! empty( $ig_es_sync_wp_users['es_registered'] ) ) ? $ig_es_sync_wp_users['es_registered'] : 'NO';
if ( 'YES' === $ig_es_registered ) {
if ( ! empty( $user_id ) ) {
global $wpdb;
$user = get_user_by( 'ID', $user_id );
if ( $user instanceof WP_User ) {
$email = $user->user_email;
$where = $wpdb->prepare( 'email = %s', $email );
$contact_id = ES()->contacts_db->get_column_by_condition( 'id', $where );
if ( $contact_id ) {
ES()->contacts_db->delete_contacts_by_ids( $contact_id );
}
}
}
}
}
}
public function prepare_sync_user() {
$audience_tab_main_navigation = array();
$active_tab = 'sync';
$audience_tab_main_navigation = apply_filters( 'ig_es_audience_tab_main_navigation', $active_tab, $audience_tab_main_navigation );
?>
<div class="max-w-full -mt-3 font-sans">
<header class="wp-heading-inline">
<div class="flex">
<div>
<nav class="text-gray-400 my-0" aria-label="Breadcrumb">
<ol class="list-none p-0 inline-flex">
<li class="flex items-center text-sm tracking-wide">
<a class="hover:underline " href="admin.php?page=es_subscribers"><?php esc_html_e( 'Audience ', 'email-subscribers' ); ?></a>
<svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
</li>
</ol>
</nav>
<h2 class="-mt-1.5 text-2xl font-medium text-gray-700 sm:leading-7 sm:truncate"> <?php esc_html_e( 'Sync contacts', 'email-subscribers' ); ?>
</h2>
</div>
<div class="mt-4 ml-2">
<?php
ES_Common::prepare_main_header_navigation( $audience_tab_main_navigation );
?>
</div>
</div>
</header>
<?php $this->sync_users_callback(); ?>
</div>
<?php
}
public function sync_users_callback() {
$logger = get_ig_logger();
$logger->trace( 'Sync Users' );
$active_tab = ig_es_get_request_data( 'tab', 'WordPress' );
$tabs = array(
'wordpress' => array(
'name' => __( 'WordPress', 'email-subscribers' ),
'url' => admin_url( 'admin.php?page=es_subscribers&action=sync&tab=wordpress' ),
),
);
$tabs = apply_filters( 'ig_es_sync_users_tabs', $tabs );
?>
<div class="ig-es-sync-settings-notice">
<div class="text-center py-4 lg:px-4 my-8">
<div class="p-2 bg-indigo-800 items-center text-indigo-100 leading-none lg:rounded-full flex lg:inline-flex mx-4 leading-normal" role="alert">
<span class="flex rounded-full bg-indigo-500 uppercase px-2 py-1 text-xs font-bold mr-3"><?php echo esc_html__( 'New', 'email-subscribers' ); ?></span>
<span class="font-semibold text-left flex-auto">
<?php
$workflows_page_url = menu_page_url( 'es_workflows', false );
/* translators: %s: Link to Workflow page */
echo wp_kses_post( sprintf( __( 'Hey!!! now sync users using Icegram Express\' workflows. <a href="%s" class="text-indigo-400">Create new workflows</a>', 'email-subscribers' ), $workflows_page_url ) );
?>
</span>
</div>
</div>
</div>
<?php
}
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}

View File

@@ -0,0 +1,166 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_IG_Redirect' ) ) {
class ES_IG_Redirect {
/**
* Redirect to icegram if require
*
* @since 4.4.1
*/
public static function go_to_icegram() {
global $ig_es_tracker;
$ig_install_url = admin_url( 'plugin-install.php?s=icegram&tab=search&type=term' );
$action = ig_es_get_request_data( 'action' );
$redirect_url = admin_url( 'post-new.php?post_type=ig_campaign' );
$ig_activate_url = admin_url( 'plugins.php?plugin_status=inactive' );
$plugin_url = 'https://wordpress.org/plugins/icegram';
if ( 'create_campaign' === $action ) {
$redirect_url = admin_url( 'edit.php?post_type=ig_campaign' );
/* translators: %s: Link to WordPress.org Icegram plugin page */
$info = sprintf( __( 'Create Onsite Campaigns using <a href="%s" target="_blank">Icegram</a>', 'email-subscribers' ), esc_url( $plugin_url ) );
} elseif ( 'create_template' === $action ) {
$redirect_url = admin_url( 'edit.php?ig_campaign&page=icegram-gallery' );
/* translators: %s: Link to WordPress.org Icegram plugin page */
$info = sprintf( __( 'Create Popups using <a href="%s" target="_blank">Icegram</a>', 'email-subscribers' ), esc_url( $plugin_url ) );
}
$icegram_plugin = 'icegram/icegram.php';
$active_plugins = $ig_es_tracker::get_active_plugins();
$inactive_plugins = $ig_es_tracker::get_inactive_plugins();
/**
* If Icegram Installed & Activated
* - Redirect to specific Icegram page
*
* If Icegram Installed & Not Activated
* - Show Intermediate page & ask them to activate Icegram
*
* If Icegram is not installed
* - Show Intermediate page & ask them to Install & activate Icegram
*/
if ( in_array( $icegram_plugin, $active_plugins ) ) {
wp_safe_redirect( $redirect_url );
exit;
} else { ?>
<div class="wrap font-sans pt-3" id="ig-es-container">
<header class="wp-heading-inline max-w-7xl mx-auto">
<div class="md:flex md:items-center md:justify-between">
<div class="flex-1 min-w-0">
<h2 class="text-3xl font-bold text-gray-700 sm:leading-9 sm:truncate pr-4 pb-1">
<?php echo wp_kses_post( $info ); ?>
</h2>
</div>
<div class="flex md:ml-4">
<span class="ml-3 shadow-sm rounded-md">
<div id="ig-es-create-button" class="relative inline-block text-left align-middle">
<div>
<span class="rounded-md shadow-sm">
<?php
if ( in_array( $icegram_plugin, $inactive_plugins ) ) {
?>
<a href="<?php echo esc_url( $ig_activate_url ); ?>"><button type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-white text-sm leading-5 font-medium text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue transition ease-in-out duration-150">
<?php
esc_html_e( 'Activate Icegram', 'email-subscribers' );
} else {
?>
<a href="<?php echo esc_url( $ig_install_url ); ?>"><button type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-white text-sm leading-5 font-medium text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue transition ease-in-out duration-150">
<?php
esc_html_e( 'Install Icegram', 'email-subscribers' );
}
?>
</button></a>
</span>
</div>
</div>
</span>
</div>
</header>
<div><hr class="wp-header-end"></div>
<main class="mt-8 max-w-7xl mx-auto">
<section class="md:flex md:items-start md:justify-between sm:px-4 py-2 my-4 sm:px-0 rounded-lg bg-white shadow sm:grid sm:grid-cols-3">
<div class="flex min-w-0 mr-4 pl-1">
<div class="relative bg-white rounded ">
<picture class="block">
<img class="border-0 h-20 mx-auto my-2" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/icegram-engage-visitors-person-flow.png" alt="feature-img">
</picture>
<div class="pt-2 block mr-6">
<h3 class="text-gray-700 font-bold md:text-base lg:text-lg"><?php esc_html_e( 'Engage Visitors', 'email-subscribers' ); ?></h3>
<p class="md:pt-6 lg:pt-2 text-sm font-normal text-gray-600 leading-snug">
<?php esc_html_e( 'Show right messages to right people at the right time in the right place. Drive people to landing pages, promotions and stop them from bouncing away.', 'email-subscribers' ); ?>
</p>
</div>
</div>
</div>
<div class="flex min-w-0 mr-4 pl-2">
<div class="relative bg-white rounded">
<picture class="block">
<img class="border-0 h-20 mx-auto my-2" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/icegram-engage-more-subscribers-and-visitors.png" alt="feature-img">
</picture>
<div class="pt-2 block mr-6">
<h3 class="text-lg text-gray-700 font-bold md:text-base lg:text-lg"><?php esc_html_e( 'More Subscribers & Customers', 'email-subscribers' ); ?></h3>
<p class="text-sm pt-2 font-normal text-gray-600 leading-snug">
<?php esc_html_e( 'Dramatically increase opt-ins and sales. Easily run powerful onsite marketing campaigns. Marketers, owners and visitors everyone loves Icegram!', 'email-subscribers' ); ?>
</p>
</div>
</div>
</div>
<div class="flex min-w-0 mr-4 pl-2">
<div class="relative bg-white rounded">
<picture class="block">
<img class="border-0 h-20 mx-auto my-2" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/icegram-engage-optimize-results.png" alt="feature-img">
</picture>
<div class="pt-2 block mr-6">
<h3 class="text-lg text-gray-700 font-bold md:text-base lg:text-lg"><?php esc_html_e( 'Optimize Results', 'email-subscribers' ); ?></h3>
<p class="md:pt-6 lg:pt-2 lg:text-sm font-normal text-gray-600 leading-snug">
<?php esc_html_e( 'Keep growing. Get everything you need to target, measure, re-target, behavior rules, personalize, split test, segment, automate and optimize.', 'email-subscribers' ); ?>
</p>
</div>
</div>
</div>
</section>
</main>
<main class="max-w-7xl mx-auto -py-4">
<section class="md:flex md:items-start md:justify-between sm:px-4 py-2 my-8 sm:px-0 sm:grid sm:grid-cols-2">
<div class="flex min-w-0 mr-2 pl-1 mx-8 my-4">
<div class="relative">
<picture class="block ">
<img class="w-11/12 border-0 h-62 rounded-lg bg-white shadow" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/optin_form_1.png" alt="feature-img">
</picture>
</div>
</div>
<div class="flex min-w-0 mr-2 pl-2 mx-8 my-4">
<div class="relative">
<picture class="block">
<img class="w-11/12 border-0 h-62 rounded-lg bg-white shadow" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/optin_form_2.png" alt="feature-img">
</picture>
</div>
</div>
</section>
</main>
</div>
<?php
}
}
}
}

View File

@@ -0,0 +1,60 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Info {
public static $instance;
public function __construct() {
add_action( 'admin_menu', array( $this, 'plugin_menu' ) );
}
public function plugin_menu() {
$update_text = ES()->is_starter() ? esc_html__( ' Go MAX', 'email-subscribers' ) : esc_html__( ' Go PRO', 'email-subscribers' );
// Start-IG-Code.
$help_title = __( 'Help & Info', 'email-subscribers' );
add_submenu_page( 'es_dashboard', $help_title, $help_title, 'edit_posts', 'es_general_information', array( $this, 'es_information_callback' ) );
$pro_title = $update_text . ' <span class="premium-icon-rocket"></span>';
if ( ! ES()->is_pro() ) {
add_submenu_page( 'es_dashboard', $pro_title, $pro_title, 'edit_posts', 'es_pricing', array( $this, 'es_pricing_callback' ) );
}
// End-IG-Code.
}
public function es_information_callback() {
$is_option_exists = get_option( 'current_sa_email_subscribers_db_version', false );
$enable_manual_update = false;
if ( $is_option_exists ) {
$enable_manual_update = true;
}
$update_url = add_query_arg( 'do_update_ig_es', 'true', admin_url( 'admin.php?page=es_general_information' ) );
$update_url = add_query_arg( 'from_db_version', '3.5.18', $update_url );
$update_url = wp_nonce_url( $update_url, 'ig_es_db_update', 'ig_es_db_update_nonce' );
include_once ES_PLUGIN_DIR . '/lite/admin/partials/help.php';
}
public static function es_pricing_callback() {
Email_Subscribers_Pricing::sm_show_pricing();
}
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}

View File

@@ -0,0 +1,128 @@
<?php
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
class ES_List_Table extends WP_List_Table {
/**
* Perpage items
*
* @since 4.6.6
* @var int
*/
public $per_page = 10;
/**
* Prepare Items
*
* @since 4.6.6
*/
public function prepare_items() {
$this->_column_headers = $this->get_column_info();
/** Process bulk action */
$this->process_bulk_action();
$search_str = ig_es_get_request_data( 's' );
$this->search_box( $search_str, 'form-search-input' );
$per_page = $this->get_items_per_page( static::$option_per_page, 25 );
// $per_page = $this->per_page; // Show Max 10 records per page
$current_page = $this->get_pagenum();
$total_items = $this->get_lists( 0, 0, true );
$this->set_pagination_args(
array(
'total_items' => $total_items, // WE have to calculate the total number of items
'per_page' => $per_page, // WE have to determine how many items to show on a page
)
);
$this->items = $this->get_lists( $per_page, $current_page );
}
/**
* Get Lists
*
* @param int $per_page
* @param int $current_page
* @param false $do_count_only
*
* @since 4.6.6
*/
public function get_lists( $per_page = 10, $current_page = 1, $do_count_only = false ) {
}
/**
* For Bulk actions
*
* @since 1.0.0
*/
public function process_bulk_action() {
}
/**
* Hide default search box
*
* @param string $text
* @param string $input_id
*
* @since 4.6.6
*/
public function search_box( $text, $input_id ) {
}
/**
* Hide top pagination
*
* @param string $which
*
* @since 4.6.6
*/
public function pagination( $which ) {
if ( 'bottom' == $which ) {
parent::pagination( $which );
}
}
/**
* Add Row action
*
* @param string[] $actions
* @param bool $always_visible
* @param string $class
*
* @return string
*
* @since 4.6.6
*/
protected function row_actions( $actions, $always_visible = false, $class = '' ) {
$action_count = count( $actions );
$i = 0;
if ( ! $action_count ) {
return '';
}
$out = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions ' . $class ) . '">';
foreach ( $actions as $action => $link ) {
++ $i;
( $i == $action_count ) ? $sep = '' : $sep = ' | ';
$out .= "<span class='$action'>$link$sep</span>";
}
$out .= '</div>';
$out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details', 'email-subscribers' ) . '</span></button>';
return $out;
}
}

View File

@@ -0,0 +1,800 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Lists_Table extends ES_List_Table {
/**
* ES_DB_Lists object
*
* @since 4.2.1
* @var $db
*/
protected $db;
/**
* Numbers of list options per page
*
* @since 4.2.1
* @var string
*/
public static $option_per_page = 'es_lists_per_page';
/**
* ES_Lists_Table constructor.
*
* @since 4.0
*/
public function __construct() {
parent::__construct(
array(
'singular' => __( 'List', 'email-subscribers' ), // singular name of the listed records
'plural' => __( 'Lists', 'email-subscribers' ), // plural name of the listed records
'ajax' => false, // does this table support ajax?,
'screen' => 'es_lists',
)
);
$this->db = new ES_DB_Lists();
}
/**
* Add Screen Option
*
* @since 4.2.1
*/
public static function screen_options() {
$option = 'per_page';
$args = array(
'label' => __( 'Number of lists per page', 'email-subscribers' ),
'default' => 20,
'option' => self::$option_per_page,
);
add_screen_option( $option, $args );
}
public function render() {
$action = ig_es_get_request_data( 'action' );
?>
<div class="wrap pt-4 font-sans">
<?php
if ( 'new' === $action ) {
$this->es_new_lists_callback();
} elseif ( 'edit' === $action ) {
$list = ig_es_get_request_data( 'list' );
echo wp_kses_post( $this->edit_list( absint( $list ) ) );
} else {
?>
<div class="max-w-full -mt-3 font-sans">
<header class="wp-heading-inline">
<div class="flex">
<div>
<nav class="text-gray-400 my-0" aria-label="Breadcrumb">
<ol class="list-none p-0 inline-flex">
<li class="flex items-center text-sm tracking-wide">
<a class="hover:underline " href="admin.php?page=es_subscribers"><?php esc_html_e( 'Audience ', 'email-subscribers' ); ?></a>
<svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
</li>
</ol>
</nav>
<h2 class="-mt-1.5 text-2xl font-medium text-gray-700 sm:leading-7 sm:truncate"> <?php esc_html_e( 'Lists', 'email-subscribers' ); ?>
</h2>
</div>
<div class="mt-4"> <a href="admin.php?page=es_lists&action=new" class="ig-es-title-button ml-2"><?php esc_html_e( 'Add New', 'email-subscribers' ); ?></a>
</div>
</div>
</header>
<div><hr class="wp-header-end"></div>
<div id="poststuff" class="es-items-lists es-lists-table">
<div id="post-body" class="metabox-holder column-1">
<div id="post-body-content">
<div class="meta-box-sortables ui-sortable">
<form method="get">
<input type="hidden" name="page" value="es_lists" />
<?php
// Display search field and other available filter fields.
$this->prepare_items();
?>
</form>
<form method="post">
<?php
// Display bulk action fields, pagination and list items.
$this->display();
?>
</form>
</div>
</div>
</div>
<br class="clear">
</div>
</div>
<?php
}
}
/**
* Validate data
*
* @param $data
*
* @return array
*/
public function validate_data( $data ) {
$nonce = $data['nonce'];
$list_name = $data['list_name'];
$list_id = ig_es_get_request_data('list');
$existing_list_data = $this->db->get_list_by_name( $list_name );
$status = 'error';
$message = '';
if ( ! wp_verify_nonce( $nonce, 'es_list' ) ) {
$message = __( 'You do not have permission to edit list', 'email-subscribers' );
} elseif ( empty( $list_name ) ) {
$message = __( 'Please add list name', 'email-subscribers' );
} elseif ( $this->db->is_list_exists( $list_name ) && isset( $existing_list_data['id'] ) && $existing_list_data['id'] != $list_id ) {
$message = __( 'List already exists. Please choose a different name', 'email-subscribers' );
} else {
$status = 'success';
}
$response = array(
'status' => $status,
'message' => $message,
);
return $response;
}
public function es_new_lists_callback() {
$submitted = ig_es_get_request_data( 'submitted' );
if ( 'submitted' === $submitted ) {
$nonce = ig_es_get_request_data( '_wpnonce' );
$list_name = ig_es_get_request_data( 'list_name' );
$list_desc = ig_es_get_request_data( 'list_desc' );
$validate_data = array(
'nonce' => $nonce,
'list_name' => $list_name,
'list_desc' => $list_desc,
);
$response = $this->validate_data( $validate_data );
if ( 'error' === $response['status'] ) {
$message = $response['message'];
ES_Common::show_message( $message, 'error' );
$this->prepare_list_form( null, $validate_data );
return;
}
$data = array(
'list_name' => $list_name,
'list_desc' => $list_desc,
);
$save = $this->save_list( null, $data );
if ( $save ) {
$message = __( 'List added successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
}
}
$this->prepare_list_form();
}
/**
* Edit List
*
* @param $id
*
* @since 4.0.0
*/
public function edit_list( $id ) {
$list = $this->db->get( $id );
$submitted = ig_es_get_request_data( 'submitted' );
if ( 'submitted' === $submitted ) {
$nonce = ig_es_get_request_data( '_wpnonce' );
$list_name = ig_es_get_request_data( 'list_name' );
$list_desc = ig_es_get_request_data( 'list_desc' );
$validate_data = array(
'nonce' => $nonce,
'list_name' => $list_name,
'list_desc' => $list_desc,
);
$response = $this->validate_data( $validate_data );
if ( 'error' === $response['status'] ) {
$message = $response['message'];
ES_Common::show_message( $message, 'error' );
$this->prepare_list_form( $id, $validate_data );
return;
}
$data = array(
'list_name' => $list_name,
'list_desc' => $list_desc,
'hash' => isset( $list['hash'] ) ? $list['hash'] : '',
);
$save = $this->save_list( $id, $data );
if ( $save ) {
$message = __( 'List updated successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
}
} else {
$id = $list['id'];
$data = array(
'list_name' => $list['name'],
'list_desc' => $list['description'],
'hash' => $list['hash'],
);
}
$this->prepare_list_form( $id, $data );
?>
<?php
}
public function prepare_list_form( $id = 0, $data = array() ) {
$is_new = empty( $id ) ? 1 : 0;
$action = 'new';
if ( ! $is_new ) {
$action = 'edit';
}
$list_name = isset( $data['list_name'] ) ? $data['list_name'] : '';
$list_desc = isset( $data['list_desc'] ) ? $data['list_desc'] : '';
$nonce = wp_create_nonce( 'es_list' );
?>
<div class="max-w-full -mt-3 font-sans">
<header class="wp-heading-inline">
<div class="md:flex md:items-center md:justify-between justify-center">
<div class="flex-1 min-w-0">
<nav class="text-gray-400 my-0" aria-label="Breadcrumb">
<ol class="list-none p-0 inline-flex">
<li class="flex items-center text-sm tracking-wide">
<a class="hover:underline " href="admin.php?page=es_subscribers"><?php esc_html_e( 'Audience ', 'email-subscribers' ); ?></a>
<svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
<a class="hover:underline" href="admin.php?page=es_lists&action=manage-lists"><?php esc_html_e( ' Lists ', 'email-subscribers' ); ?></a>
<svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
</li>
</ol>
</nav>
<h2 class="-mt-1 text-2xl font-medium text-gray-700 sm:leading-7 sm:truncate">
<?php
if ( $is_new ) {
esc_html_e( 'Add New List', 'email-subscribers' );
} else {
esc_html_e( 'Edit List', 'email-subscribers' );
}
?>
</h2>
</div>
</div>
</header>
<div><hr class="wp-header-end"></div>
<div class="rounded max-w-full ">
<div id="poststuff">
<div id="post-body" class="metabox-holder column-1 mt-0.5">
<div id="post-body-content">
<div class="bg-white shadow-md rounded-lg mt-5">
<form class="ml-5 mr-4 text-left pt-8 mt-2 item-center " method="post" action="admin.php?page=es_lists&action=<?php echo esc_attr( $action ); ?>&list=<?php echo esc_attr( $id ); ?>&_wpnonce=<?php echo esc_attr( $nonce ); ?>">
<div class="flex flex-row border-b border-gray-100">
<div class="flex w-1/5">
<div class="ml-4 pt-6 px-3 ">
<label for="name" class="block text-sm leading-5 font-medium text-gray-600"><?php esc_html_e( 'List name', 'email-subscribers' ); ?></label>
</div>
</div>
<div class="flex">
<div class="ml-16 mb-4 h-10 mr-4 mt-4">
<div class="h-10 relative">
<input class="form-input block border-gray-400 w-full pl-3 pr-12 focus:bg-gray-100 sm:text-sm sm:leading-5" placeholder="<?php echo esc_html__( 'Enter list name', 'email-subscribers' ); ?>" id="name" name="list_name" value="<?php echo esc_attr( $list_name ); ?>"/>
</div>
</div>
</div>
</div>
<div class="flex flex-row border-b border-gray-100">
<div class="flex w-1/5">
<div class="ml-4 pt-6 px-3 ">
<label for="name" class="block text-sm leading-5 font-medium text-gray-600"><?php esc_html_e( 'Description', 'email-subscribers' ); ?></label>
</div>
</div>
<div class="flex">
<div class="ml-16 mb-4 mr-4 mt-4">
<div class="relative">
<textarea class="form-textarea text-sm" rows="2" cols="40" name="list_desc"><?php echo esc_html( $list_desc ); ?></textarea>
</div>
</div>
</div>
</div>
<?php
if ( 'edit' === $action ) {
?>
<div class="flex flex-row border-b border-gray-100">
<div class="flex w-1/5">
<div class="ml-4 pt-4 px-3">
<label for="name" class="block text-sm leading-5 font-medium text-gray-600">
<?php
$allowedtags = ig_es_allowed_html_tags_in_esc();
$tooltip_html = ES_Common::get_tooltip_html( __( 'Unique hash key that can be used to subscribe users to the list from external sites.', 'email-subscribers' ) );
esc_html_e( 'Hash', 'email-subscribers' );
?>
&nbsp;
<?php echo wp_kses( $tooltip_html, $allowedtags ); ?>
</label>
</div>
</div>
<div class="flex">
<div class="ml-16 mb-4 mr-4 mt-4">
<div class="relative">
<code class="select-all p-1 text-md font-medium text-sm">
<?php
$hash = isset( $data['hash'] ) ? $data['hash'] : '';
echo esc_html( $hash );
?>
</code>
</div>
</div>
</div>
</div>
<?php
}
$submit_button_text = $is_new ? __( 'Save List', 'email-subscribers' ) : __( 'Save Changes', 'email-subscribers' );
?>
<input type="hidden" name="submitted" value="submitted"/>
<p><input type="submit" name="submit" id="submit" class="cursor-pointer align-middle ig-es-primary-button px-4 py-2 my-4 ml-6 mr-2" value="<?php echo esc_attr( $submit_button_text ); ?>"/>
<a href="admin.php?page=es_lists&action=manage-lists" class="cursor-pointer align-middle rounded-md border border-indigo-600 hover:shadow-md focus:outline-none focus:shadow-outline-indigo text-sm leading-5 font-medium transition ease-in-out duration-150 px-4 my-2 py-2 mx-2 "><?php esc_html_e( 'Cancel', 'email-subscribers' ); ?></a></p>
</form>
</div>
</div>
</div>
<br class="clear">
</div>
</div>
</div>
<?php
}
/**
* Save list
*
* @param $id
* @param $data
*
* @return bool|int|void
*
* @since 4.0.0
*/
public function save_list( $id, $data ) {
$name = sanitize_text_field( $data['list_name'] );
$desc = isset( $data['list_desc'] ) ? sanitize_text_field( $data['list_desc'] ) : '';
$list = array(
'name' => $name,
'desc' => $desc,
);
if ( ! empty( $id ) ) {
$return = $this->db->update_list( $id, $list );
} else {
$return = $this->db->add_list( $list );
}
return $return;
}
/**
* Retrieve lists data from the database
*
* @param int $per_page
* @param int $page_number
*
* @return mixed
*/
public function get_lists( $per_page = 5, $page_number = 1, $do_count_only = false ) {
global $wpbd;
$order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
$order = ig_es_get_request_data( 'order' );
$search = ig_es_get_request_data( 's' );
if ( $do_count_only ) {
$sql = 'SELECT count(*) as total FROM ' . IG_LISTS_TABLE;
} else {
$sql = 'SELECT * FROM ' . IG_LISTS_TABLE;
}
$args = array();
$query = array();
$add_where_clause = false;
if ( ! empty( $search ) ) {
$query[] = ' name LIKE %s ';
$args[] = '%' . $wpbd->esc_like( $search ) . '%';
$add_where_clause = true;
}
if ( $add_where_clause ) {
$sql .= ' WHERE ';
if ( count( $query ) > 0 ) {
$sql .= implode( ' AND ', $query );
if ( count( $args ) > 0 ) {
$sql = $wpbd->prepare( $sql, $args );
}
}
}
if ( ! $do_count_only ) {
// Prepare Order by clause
$order = ! empty( $order ) ? strtolower( $order ) : 'desc';
$expected_order_values = array( 'asc', 'desc' );
if ( ! in_array( $order, $expected_order_values ) ) {
$order = 'desc';
}
$default_order_by = esc_sql( 'created_at' );
$expected_order_by_values = array( 'name', 'created_at' );
if ( ! in_array( $order_by, $expected_order_by_values ) ) {
$order_by_clause = " ORDER BY {$default_order_by} DESC";
} else {
$order_by = esc_sql( $order_by );
$order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
}
$sql .= $order_by_clause;
$sql .= " LIMIT $per_page";
$sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
$result = $wpbd->get_results( $sql, 'ARRAY_A' );
} else {
$result = $wpbd->get_var( $sql );
}
return $result;
}
/**
* Render a column when no column specific method exist.
*
* @param array $item
* @param string $column_name
*
* @return mixed
*/
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'subscribed':
$count = ES()->lists_contacts_db->get_total_count_by_list( $item['id'], 'subscribed' );
if ( $count > 0 ) {
$url = admin_url( 'admin.php?page=es_subscribers&filter_by_status=subscribed&filter_by_list_id=' . $item['id'] );
/* translators: 1: Subscribed-Filter url 2: Count */
$count = '<a href="' . $url . '" target="_blank">' . number_format( $count ) . '</a>';
}
return $count;
break;
case 'unsubscribed':
$count = ES()->lists_contacts_db->get_total_count_by_list( $item['id'], 'unsubscribed' );
if ( $count > 0 ) {
$url = admin_url( 'admin.php?page=es_subscribers&filter_by_status=unsubscribed&filter_by_list_id=' . $item['id'] );
/* translators: 1: Unsubscribed-Filter url 2: Count */
$count = '<a href="' . $url . '" target="_blank">' . number_format( $count ) . '</a>';
}
return $count;
break;
case 'unconfirmed':
$count = ES()->lists_contacts_db->get_total_count_by_list( $item['id'], 'unconfirmed' );
if ( $count > 0 ) {
$url = admin_url( 'admin.php?page=es_subscribers&filter_by_status=unconfirmed&filter_by_list_id=' . $item['id'] );
/* translators: 1: Unconfirmed-Filter url 2: Count */
$count = '<a href="' . $url . '" target="_blank">' . number_format( $count ) . '</a>';
}
return $count;
break;
case 'all_contacts':
$count = ES()->lists_contacts_db->get_total_count_by_list( $item['id'], 'all' );
if ( $count > 0 ) {
$url = admin_url( 'admin.php?page=es_subscribers&filter_by_list_id=' . $item['id'] );
/* translators: 1: All contacts flters 2: Count */
$count = '<a href="' . $url . '" target="_blank">' . number_format( $count ) . '</a>';
}
return $count;
break;
case 'export':
$export_nonce = wp_create_nonce( 'ig-es-subscriber-export-nonce' );
return "<a href='admin.php?page=download_report&report=users&status=select_list&list_id={$item['id']}&export-nonce={$export_nonce}'><svg fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24' class='w-8 h-8 text-indigo-600 hover:text-indigo-500 active:text-indigo-600'><path d='M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z'></path></svg></a>";
break;
case 'description':
if ( empty( $item['description'] ) ) {
return '-';
}
$description = '<span class="es_list_desc" title="' . $item['description'] . '">';
$description .= strlen( $item['description'] ) > 50 ? substr( $item['description'], 0, 50 ) . '...' : $item['description'];
$description .= '</span>';
return $description;
break;
default:
return '';
}
}
/**
* Render the bulk edit checkbox
*
* @param array $item
*
* @return string
*/
public function column_cb( $item ) {
return sprintf(
'<input type="checkbox" name="lists[]" value="%s" />',
$item['id']
);
}
/**
* Method for name column
*
* @param array $item an array of DB data
*
* @return string
*/
public function column_name( $item ) {
$list_nonce = wp_create_nonce( 'es_list' );
$list_id = (int) $item['id'];
$title = '<strong>' . $item['name'] . '</strong>';
$page = ig_es_get_request_data( 'page' );
$actions = array(
'edit' => '<a href="?page=' . esc_attr( $page ) . '&action=edit&list=' . absint( $item['id'] ) . '&_wpnonce=' . $list_nonce . '" class="text-indigo-600">' . esc_html__( 'Edit', 'email-subscribers' ) . '</a>',
);
// We consider list with id 1 as a Master list and don't allow its deletion.
if ( 1 !== $list_id ) {
$actions['delete'] = '<a href="?page=' . esc_attr( $page ) . '&action=delete&list=' . absint( $item['id'] ) . '&_wpnonce=' . $list_nonce . '" onclick="return checkDelete()">' . esc_html__( 'Delete', 'email-subscribers' ) . '</a>';
}
return $title . $this->row_actions( $actions );
}
/**
* Associative array of columns
*
* @return array
*/
public function get_columns() {
$allowedtags = ig_es_allowed_html_tags_in_esc();
$columns = array(
'cb' => '<input type="checkbox" />',
'name' => __( 'Name', 'email-subscribers' ),
'description' => __( 'Description', 'email-subscribers' ),
'subscribed' => __( 'Subscribed', 'email-subscribers' ),
'unsubscribed' => __( 'Unsubscribed', 'email-subscribers' ),
'unconfirmed' => __( 'Unconfirmed', 'email-subscribers' ),
'all_contacts' => __( 'All contacts', 'email-subscribers' ),
'export' => __( 'Export', 'email-subscribers' ),
);
return apply_filters( 'ig_es_lists_columns', $columns );
}
/**
* Columns to make sortable.
*
* @return array
*/
public function get_sortable_columns() {
$sortable_columns = array(
'name' => array( 'name', true ),
'created_at' => array( 'created_at', true ),
);
return $sortable_columns;
}
/**
* Returns an associative array containing the bulk action
*
* @return array
*/
public function get_bulk_actions() {
$actions = array(
'bulk_delete' => __( 'Delete', 'email-subscribers' ),
);
return $actions;
}
/**
* Prepare search box
*
* @param string $text
* @param string $input_id
*
* @since 4.0.0
* @since 4.3.4 Added esc_attr()
*/
public function search_box( $text = '', $input_id = '' ) {
?>
<p class="search-box">
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_attr( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
<?php submit_button( __( 'Search lists', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
</p>
<?php
}
/**
* Handles data query and filter, sorting, and pagination.
*/
public function prepare_items() {
$this->_column_headers = $this->get_column_info();
/** Process bulk action */
$this->process_bulk_action();
$this->search_box( ig_es_get_request_data( 's' ), 'list-search-input' );
$per_page = $this->get_items_per_page( self::$option_per_page, 25 );
$current_page = $this->get_pagenum();
$total_items = $this->get_lists( 0, 0, true );
$this->set_pagination_args(
array(
'total_items' => $total_items, // WE have to calculate the total number of items.
'per_page' => $per_page, // WE have to determine how many items to show on a page.
)
);
$this->items = $this->get_lists( $per_page, $current_page );
}
public function process_bulk_action() {
// Detect when a bulk action is being triggered...
if ( 'edit' === $this->current_action() ) {
// In our file that handles the request, verify the nonce.
$nonce = esc_attr( ig_es_get_request_data( '_wpnonce' ) );
if ( ! wp_verify_nonce( $nonce, 'es_list' ) ) {
$message = __( 'You do not have permission to edit list', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
} else {
$this->edit_list( absint( ig_es_get_request_data( 'list' ) ) );
$message = __( 'List updated successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
}
}
if ( 'delete' === $this->current_action() ) {
// In our file that handles the request, verify the nonce.
$nonce = esc_attr( ig_es_get_request_data( '_wpnonce' ) );
if ( ! wp_verify_nonce( $nonce, 'es_list' ) ) {
$message = __( 'You do not have permission to delete list', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
} else {
$list = ig_es_get_request_data( 'list' );
if ( 1 != $list ) {
$list = ig_es_get_request_data( 'list' );
$this->db->delete_lists( array( $list ) );
$message = __( 'List deleted successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
}
}
}
$action = ig_es_get_request_data( 'action' );
$action2 = ig_es_get_request_data( 'action2' );
// If the delete bulk action is triggered
if ( ( 'bulk_delete' === $action ) || ( 'bulk_delete' === $action2 ) ) {
$lists = ig_es_get_request_data( 'lists' );
if ( ! empty( $lists ) > 0 ) {
$this->db->delete_lists( $lists );
$message = __( 'List(s) deleted successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
} else {
$message = __( 'Please select list', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
return;
}
}
}
public function status_label_map( $status ) {
$statuses = array(
'enable' => __( 'Enable', 'email-subscribers' ),
'disable' => __( 'Disable', 'email-subscribers' ),
);
if ( ! in_array( $status, array_keys( $statuses ) ) ) {
return '';
}
return $statuses[ $status ];
}
/** Text displayed when no list data is available */
public function no_items() {
esc_html_e( 'No lists avaliable.', 'email-subscribers' );
}
}

View File

@@ -0,0 +1,145 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Mailchimp_API {
private $domain = 'api.mailchimp.com';
private $version = '3.0';
private $total_items = null;
public function __construct( $apikey ) {
$this->apikey = $apikey;
$this->dc = preg_replace( '/^([a-f0-9]+)-([a-z0-9]+)$/', '$2', $apikey );
$this->url = trailingslashit( 'https://' . $this->dc . '.' . $this->domain . '/' . $this->version );
}
public function mailchimp_api_call( $action, $args = array() ) {
$response = $this->get( $action, $args );
if ( is_wp_error( $response ) ) {
wp_send_json_error( array( 'error' => $response->get_error_message() ), $response->get_error_code() );
}
return $response;
}
/**
* Get total items
*
* @since 4.6.14
*/
public function get_total_items() {
return $this->total_items;
}
/**
* Verify API Key
*
* @since 4.6.14
*/
public function ping() {
return $this->mailchimp_api_call( 'ping' );
}
/**
* Get list of audience lists
*
* @since 4.6.14
*/
public function lists( $args = array() ) {
$result = $this->mailchimp_api_call( 'lists', $args );
return isset( $result->lists ) ? $result->lists : array();
}
/**
* Get specific audience list
*
* @since 4.6.14
*/
public function get_list( $list_id, $args = array() ) {
return $this->mailchimp_api_call( 'lists/' . $list_id, $args );
}
/**
* Get contacts from specific list
*
* @param list_id
*
* @since 4.6.14
*/
public function members( $list_id, $args = array() ) {
$result = $this->mailchimp_api_call( 'lists/' . $list_id . '/members', $args );
return isset( $result->members ) ? $result->members : array();
}
public function get( $action, $args = array(), $timeout = 15 ) {
return $this->do_call( 'GET', $action, $args, $timeout );
}
public function post( $action, $args = array(), $timeout = 15 ) {
return $this->do_call( 'POST', $action, $args, $timeout );
}
/**
* Get data from Mailchimp API (Lists, contacts)
*
* @since 4.6.14
*/
private function do_call( $method, $action, $args = array(), $timeout = 15 ) {
$url = $this->url . $action;
$headers = array(
'Authorization' => 'apikey ' . $this->apikey,
);
$body = null;
if ( 'GET' == $method ) {
$url = add_query_arg( $args, $url );
} elseif ( 'POST' == $method ) {
$body = $args;
} else {
return new WP_Error( 'method_not_allowed', 'This method is not allowed' );
}
$this->total_items = null;
$response = wp_remote_request(
$url,
array(
'method' => $method,
'headers' => $headers,
'timeout' => $timeout,
'body' => $body,
)
);
if ( is_wp_error( $response ) ) {
return $response;
}
$code = wp_remote_retrieve_response_code( $response );
$body = json_decode( wp_remote_retrieve_body( $response ) );
if ( 200 != $code ) {
return new WP_Error( $body->status, $body->title . ': ' . $body->detail, $body );
}
if ( isset( $body->total_items ) ) {
$this->total_items = $body->total_items;
}
return $body;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,123 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_Message' ) ) {
/**
* Class ES_Message
*
* @since 4.3.2
*/
class ES_Message {
/**
* To email
*
* @var string
*
* @since 4.3.2
*/
public $to = '';
/**
* To name
*
* @var string
*
* @since 4.3.2
*/
public $to_name = '';
/**
* Message headers
*
* @var array
*
* @since 4.3.2
*/
public $headers = array();
/**
* Message errors
*
* @var string
*
* @since 4.3.2
*/
public $error = '';
/**
* Message subject
*
* @var string
*
* @since 4.3.2
*/
public $subject = '';
/**
* Message body
*
* @var string
*
* @since 4.3.2
*/
public $body = '';
/**
* Message text
*
* @var string
*
* @since 4.3.2
*/
public $body_text = '';
/**
* Message From
*
* @var
*
* @sinc 4.3.2
*/
public $from;
/**
* Message from name
*
* @var string
*
* @since 4.3.2
*/
public $from_name = '';
/**
* Attachments for email
*
* @since 4.6.7
*/
public $attachments = array();
/**
* Reply to email
*
* @since 4.6.7
*/
public $reply_to_email = '';
/**
* Character set
*
* @since 4.6.7
*/
public $charset = '';
public function __construct() {
}
}
}

View File

@@ -0,0 +1,121 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Old_Widget extends WP_Widget {
public function __construct() {
$widget_ops = array(
'classname' => 'widget_text elp-widget',
'description' => __( 'Icegram Express', 'email-subscribers' ),
);
parent::__construct( 'email-subscribers', __( 'Icegram Express ', 'email-subscribers' ), $widget_ops );
}
public function widget( $args, $instance ) {
$title = apply_filters( 'widget_title', $instance['es_title'] );
echo wp_kses_post( $args['before_widget'] );
if ( ! empty( $title ) ) {
echo wp_kses_post( sprintf( '%s %s %s', $args['before_title'], $title, $args['after_title'] ) );
}
$display_name = isset( $instance['es_name'] ) ? esc_attr( $instance['es_name'] ) : '';
$subscribers_group = isset( $instance['es_group'] ) ? esc_attr( $instance['es_group'] ) : '';
$desc = isset( $instance['es_desc'] ) ? esc_attr( $instance['es_desc'] ) : '';
$name = strtolower( $display_name ) != 'no' ? 'yes' : '';
$list = ES()->lists_db->get_list_by_name( $subscribers_group );
if ( ! empty( $list ) ) {
$list_id = $list['id'];
}
$data['name_visible'] = $name;
$data['list_visible'] = 'no';
$data['lists'] = array();
$data['form_id'] = 0;
$data['list'] = $list_id;
$data['desc'] = $desc;
ES_Shortcode::render_form( $data );
echo wp_kses_post( $args['after_widget'] );
}
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['es_title'] = ( ! empty( $new_instance['es_title'] ) ) ? strip_tags( $new_instance['es_title'] ) : '';
$instance['es_desc'] = ( ! empty( $new_instance['es_desc'] ) ) ? strip_tags( $new_instance['es_desc'] ) : '';
$instance['es_name'] = ( ! empty( $new_instance['es_name'] ) ) ? strip_tags( $new_instance['es_name'] ) : '';
$instance['es_group'] = ( ! empty( $new_instance['es_group'] ) ) ? strip_tags( $new_instance['es_group'] ) : '';
return $instance;
}
public function form( $instance ) {
$defaults = array(
'es_title' => '',
'es_desc' => '',
'es_name' => '',
'es_group' => '',
);
$instance = wp_parse_args( (array) $instance, $defaults );
$es_title = $instance['es_title'];
$es_desc = $instance['es_desc'];
$es_name = $instance['es_name'];
$es_group = $instance['es_group'];
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'es_title' ) ); ?>"><?php echo esc_html__( 'Widget Title', 'email-subscribers' ); ?></label>
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'es_title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'es_title' ) ); ?>" type="text" value="<?php echo esc_html( $es_title ); ?>"/>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'es_desc' ) ); ?>"><?php echo esc_html__( 'Short description about subscription form', 'email-subscribers' ); ?></label>
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'es_desc' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'es_desc' ) ); ?>" type="text" value="<?php echo esc_html( $es_desc ); ?>"/>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'es_name' ) ); ?>"><?php echo esc_html__( 'Display Name Field', 'email-subscribers' ); ?></label>
<select class="widefat" id="<?php echo esc_attr( $$this->get_field_id( 'es_name' ) ); ?>" name="<?php echo esc_attr( $$this->get_field_name( 'es_name' ) ); ?>">
<option value="YES" <?php $this->es_selected( 'YES' == $es_name ); ?>><?php echo esc_html__( 'YES', 'email-subscribers' ); ?></option>
<option value="NO" <?php $this->es_selected( 'NO' == $es_name ); ?>><?php echo esc_html__( 'NO', 'email-subscribers' ); ?></option>
</select>
</p>
<p>
<label for="<?php echo esc_attr( $$this->get_field_id( 'es_group' ) ); ?>"><?php echo esc_html__( 'Subscriber Group', 'email-subscribers' ); ?></label>
<select class="widefat" name="<?php echo esc_attr( $$this->get_field_name( 'es_group' ) ); ?>" id="<?php echo esc_attr( $$this->get_field_id( 'es_group' ) ); ?>">
<?php
$groups = ES()->lists_db->get_list_id_name_map();
if ( count( $groups ) > 0 ) {
$i = 1;
foreach ( $groups as $group ) {
?>
<option value="<?php echo esc_attr( stripslashes( $group ) ); ?>"
<?php
if ( stripslashes( $es_group ) == $group ) {
echo 'selected="selected"';
}
?>
>
<?php echo esc_html( stripslashes( $group ) ); ?>
</option>
<?php
}
}
?>
</select>
</p>
<?php
}
public function es_selected( $var ) {
if ( 1 == $var || true == $var ) {
echo 'selected="selected"';
}
}
}

View File

@@ -0,0 +1,827 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Post_Notifications_Table {
public static $instance;
public function __construct() {
$this->init();
}
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
public function init() {
$this->register_hooks();
}
public function register_hooks() {
add_action( 'ig_es_' . IG_CAMPAIGN_TYPE_POST_NOTIFICATION . '_content_settings', array( $this, 'show_post_notification_content_settings' ) );
add_action( 'ig_es_' . IG_CAMPAIGN_TYPE_POST_DIGEST . '_content_settings', array( $this, 'show_post_notification_content_settings' ) );
add_action( 'ig_es_show_' . IG_CAMPAIGN_TYPE_POST_NOTIFICATION . '_campaign_summary_action_buttons', array( $this, 'show_summary_actions_buttons' ) );
add_action( 'ig_es_show_' . IG_CAMPAIGN_TYPE_POST_DIGEST . '_campaign_summary_action_buttons', array( $this, 'show_summary_actions_buttons' ) );
add_action( 'ig_es_' . IG_CAMPAIGN_TYPE_POST_NOTIFICATION . '_default_subject', array( $this, 'get_post_notification_default_subject' ) );
add_action( 'ig_es_' . IG_CAMPAIGN_TYPE_POST_NOTIFICATION . '_default_content', array( $this, 'get_post_notification_default_content' ) );
}
public function es_notifications_callback() {
$action = ig_es_get_request_data( 'action' );
?>
<div class="wrap pt-4 font-sans">
<?php
if ( 'edit' === $action ) {
$list = ig_es_get_request_data( 'list' );
$this->edit_list( absint( $list ) );
} else {
$this->es_newnotification_callback();
}
?>
</div>
<?php
}
public function es_newnotification_callback() {
$submitted = ig_es_get_request_data( 'submitted' );
if ( 'submitted' === $submitted ) {
// Get nonce field value.
$nonce = ig_es_get_request_data( '_wpnonce' );
// Verify nonce.
if ( wp_verify_nonce( $nonce, 'es_post_notification' ) ) {
$list_id = ig_es_get_request_data( 'list_id' );
$template_id = ig_es_get_request_data( 'template_id' );
$cat = ig_es_get_request_data( 'es_note_cat' );
$es_note_cat_parent = ig_es_get_request_data( 'es_note_cat_parent' );
$cat = ( ! empty( $es_note_cat_parent ) && in_array( $es_note_cat_parent, array( '{a}All{a}', '{a}None{a}' ), true ) ) ? array( $es_note_cat_parent ) : $cat;
if ( empty( $list_id ) ) {
$message = __( 'Please select list.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
$this->prepare_post_notification_form();
return;
}
if ( empty( $cat ) ) {
$message = __( 'Please select categories.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
$this->prepare_post_notification_form();
return;
}
$type = 'post_notification';
$title = get_the_title( $template_id );
$data = array(
'categories' => ES_Common::convert_categories_array_to_string( $cat ),
'list_ids' => $list_id,
'base_template_id' => $template_id,
'status' => 1,
'type' => $type,
'name' => $title,
'slug' => sanitize_title( $title ),
);
$data = apply_filters( 'ig_es_post_notification_data', $data );
if ( empty( $data['base_template_id'] ) ) {
$message = __( 'Please select template.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
$this->prepare_post_notification_form();
return;
}
$this->save_list( $data );
$type = ucwords( str_replace( '_', ' ', $data['type'] ) );
/* translators: %s: Campaign Type */
$message = sprintf( __( '%s added successfully!', 'email-subscribers' ), $type );
ES_Common::show_message( $message, 'success' );
} else {
$message = __( 'Sorry, you are not allowed to add post notification.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
}
}
$this->prepare_post_notification_form();
}
public function custom_admin_notice() {
$es_note_cate = ig_es_get_request_data( 'es_note_cate' );
if ( $es_note_cate ) {
echo '<div class="updated"><p>Notification Added Successfully!</p></div>';
}
}
public function update_list( $id ) {
global $wpdb;
$cat = ig_es_get_request_data( 'es_note_cat' );
$data = array(
'categories' => ES_Common::convert_categories_array_to_string( $cat ),
'list_ids' => ig_es_get_request_data( 'list_id' ),
'base_template_id' => ig_es_get_request_data( 'template_id' ),
'status' => 'active',
);
$wpdb->update( IG_CAMPAIGNS_TABLE, $data, array( 'id' => $id ) );
}
public function save_list( $data, $id = null ) {
return ES()->campaigns_db->save_campaign( $data, $id );
}
/**
* Retrieve lists data from the database
*
* @param int $per_page
* @param int $page_number
*
* @return mixed
*/
public static function get_lists( $per_page = 5, $page_number = 1 ) {
global $wpdb, $wpbd;
$order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
$order = ig_es_get_request_data( 'order' );
$search = ig_es_get_request_data( 's' );
$add_where_clause = false;
$sql = 'SELECT * FROM ' . IG_CAMPAIGNS_TABLE;
$args = array();
$query = array();
if ( ! empty( $search ) ) {
$add_where_clause = true;
$query[] = ' name LIKE %s ';
$args[] = '%' . $wpdb->esc_like( $search ) . '%';
}
if ( $add_where_clause ) {
$sql .= ' WHERE ';
if ( count( $query ) > 0 ) {
$sql .= implode( ' AND ', $query );
$sql = $wpbd->prepare( $sql, $args );
}
}
// Prepare Order by clause
$order_by_clause = '';
if ( ! empty( $order_by ) ) {
$order_by_clause = ' ORDER BY ' . esc_sql( $order_by );
$order_by_clause .= ! empty( $order ) ? ' ' . esc_sql( $order ) : ' ASC';
}
$sql .= $order_by_clause;
$sql .= " LIMIT $per_page";
$sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
$result = $wpbd->get_results( $sql, 'ARRAY_A' );
return $result;
}
public function edit_list( $id ) {
global $wpdb;
$notification_query = $wpdb->prepare( ' id = %d LIMIT 0, 1', $id );
$notifications = ES()->campaigns_db->get_by_conditions( $notification_query );
$data = array();
$submitted = ig_es_get_request_data( 'submitted' );
if ( 'submitted' === $submitted ) {
// Get nonce field value.
$nonce = ig_es_get_request_data( '_wpnonce' );
// Verify nonce.
if ( wp_verify_nonce( $nonce, 'es_post_notification' ) ) {
$categories = ig_es_get_request_data( 'es_note_cat', array() );
// all categories selected
$parent_category_option = ig_es_get_request_data( 'es_note_cat_parent' );
if ( in_array( $parent_category_option, array( '{a}All{a}', '{a}None{a}' ), true ) ) {
array_unshift( $categories, $parent_category_option );
}
$data = array(
'categories' => ES_Common::convert_categories_array_to_string( $categories ),
'list_ids' => ig_es_get_request_data( 'list_id' ),
'base_template_id' => ig_es_get_request_data( 'template_id' ),
'status' => ig_es_get_request_data( 'status' ),
);
$title = '';
if ( ! empty( $data['base_template_id'] ) ) {
$title = get_the_title( $data['base_template_id'] );
}
$data['name'] = $title;
$data = apply_filters( 'ig_es_post_notification_data', $data );
$data['type'] = ! empty( $data['type'] ) ? $data['type'] : 'post_notification';
// check tempalte id
if ( empty( $data['base_template_id'] ) ) {
$message = __( 'Please select template.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
$this->prepare_post_notification_form( $id, $data );
return;
}
// check categories
if ( empty( $categories ) ) {
$message = __( 'Please select Categories.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
$this->prepare_post_notification_form( $id, $data );
return;
}
$this->save_list( $data, $id );
$data['categories'] = ES_Common::convert_categories_string_to_array( $data['categories'], true );
$type = ucwords( str_replace( '_', ' ', $data['type'] ) );
/* translators: %s: Campaign type */
$message = sprintf( __( '%s updated successfully!', 'email-subscribers' ), $type );
ES_Common::show_message( $message, 'success' );
} else {
$message = __( 'Sorry, you are not allowed to update post notification.', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
}
} else {
$notification = array_shift( $notifications );
$id = $notification['id'];
$categories_str = ! empty( $notification['categories'] ) ? $notification['categories'] : '';
$categories = ES_Common::convert_categories_string_to_array( $categories_str, true );
$data = array(
'categories' => $categories,
'list_ids' => $notification['list_ids'],
'base_template_id' => $notification['base_template_id'],
'status' => $notification['status'],
);
}
$this->prepare_post_notification_form( $id, $data );
}
public static function prepare_post_notification_form( $id = '', $data = array() ) {
$is_new = empty( $id ) ? 1 : 0;
$action = 'new';
$heading = __( ' New Post Notification', 'email-subscribers' );
if ( ! $is_new ) {
$action = 'edit';
$heading = __( ' Edit Post Notification', 'email-subscribers' );
}
$cat = isset( $data['categories'] ) ? $data['categories'] : '';
$list_id = isset( $data['list_ids'] ) ? $data['list_ids'] : '';
$template_id = isset( $data['base_template_id'] ) ? $data['base_template_id'] : '';
$status = isset( $data['status'] ) ? $data['status'] : 0;
$nonce = wp_create_nonce( 'es_post_notification' );
$select_list_attr = ES()->is_pro() ? 'multiple="multiple"' : '';
$select_list_name = ES()->is_pro() ? 'list_id[]' : 'list_id';
$select_list_class = ES()->is_pro() ? 'ig-es-form-multiselect' : 'form-select';
$allowedtags = ig_es_allowed_html_tags_in_esc();
?>
<div class="max-w-full -mt-3 font-sans">
<header class="wp-heading-inline">
<div class="md:flex md:items-center md:justify-between justify-center">
<div class="flex-1 min-w-0">
<nav class="text-gray-400 my-0" aria-label="Breadcrumb">
<ol class="list-none p-0 inline-flex">
<li class="flex items-center text-sm tracking-wide">
<a class="hover:underline" href="admin.php?page=es_campaigns"><?php esc_html_e( 'Campaigns ', 'email-subscribers' ); ?></a>
<svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
</li>
</ol>
</nav>
<h2 class="-mt-1 text-2xl font-medium text-gray-700 sm:leading-7 sm:truncate">
<?php echo esc_html( $heading ); ?>
</h2>
</div>
<div class="flex md:mt-0">
<?php if ( 'edit' === $action ) { ?>
<a href="admin.php?page=es_notifications&action=new" class="ig-es-title-button py-1.5 mx-2"><?php esc_html_e( 'Add New', 'email-subscribers' ); ?></a>
<?php } ?>
<a href="edit.php?post_type=es_template" class="ig-es-imp-button px-3 py-1"><?php esc_html_e( 'Manage Templates', 'email-subscribers' ); ?></a>
</div>
</div>
</header>
<div class="">
<hr class="wp-header-end">
</div>
<div class="bg-white shadow-md rounded-lg mt-8">
<form id="ig-es-post-notification-form" class="ml-5 mr-4 text-left pt-4 mt-2 item-center" method="post" action="admin.php?page=es_notifications&action=<?php echo esc_attr( $action ); ?>&list=<?php echo esc_attr( $id ); ?>&_wpnonce=<?php echo esc_attr( $nonce ); ?>">
<table class="max-w-full form-table">
<tbody>
<?php if ( ! $is_new ) { ?>
<tr class="border-b border-gray-100">
<th scope="row" class="w-3/12 pt-3 pb-8 text-left">
<label for="tag-link"><span class="block ml-6 pr-4 pt-2 text-sm font-medium text-gray-600 pb-2">
<?php esc_html_e( 'Enable/Disable campaign', 'email-subscribers' ); ?>
</label>
</th>
<td class="w-9/12 py-3">
<label for="status" class="ml-12 inline-flex items-center cursor-pointer"><span class="relative">
<input id="status" type="checkbox" class="absolute es-check-toggle opacity-0 w-0 h-0"
name="status" value="1" <?php checked( $status, '1' ); ?> />
<span class="es-mail-toggle-line"></span>
<span class="es-mail-toggle-dot"></span>
</span></label>
</td>
</tr>
<?php } ?>
<?php do_action( 'es_before_post_notification_settings', $id ); ?>
<tr class="border-b border-gray-100">
<th scope="row" class="w-3/12 pt-3 pb-8 text-left">
<label for="tag-link"><span class="block ml-6 pr-4 text-sm font-medium text-gray-600 pb-2">
<?php esc_html_e( 'Select list', 'email-subscribers' ); ?></span>
<p class="italic text-xs font-normal text-gray-400 mt-2 ml-6 leading-snug"><?php esc_html_e( 'Contacts from the selected list will be notified about new post notification.', 'email-subscribers' ); ?></p></label>
</th>
<td class="w-9/12 pb-3 ">
<div class="flex">
<div class="w-2/4 inline-flex ml-12 relative">
<select <?php echo esc_attr( $select_list_attr ); ?> class="absolute shadow-sm border border-gray-400 w-2/3 <?php echo esc_attr( $select_list_class ); ?>" name="<?php echo esc_attr( $select_list_name ); ?>" id="ig_es_post_notification_list_ids">
<?php
$lists_dropdown = ES_Common::prepare_list_dropdown_options( $list_id );
echo wp_kses( $lists_dropdown, $allowedtags );
?>
</select>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<?php do_action( 'ig_es_add_multilist_options' ); ?>
<table class="max-w-full form-table">
<tbody>
<tr class="border-b border-gray-100">
<th scope="row" class="w-3/12 pt-3 pb-8 text-left">
<label for="tag-link"><span class="block ml-6 pr-4 text-sm font-medium text-gray-600 pb-2">
<?php esc_html_e( 'Select template', 'email-subscribers' ); ?></span>
<p class="italic text-xs font-normal text-gray-400 mt-2 ml-6 leading-snug"><?php esc_html_e( 'Content of the selected template will be sent out as post notification.', 'email-subscribers' ); ?></p>
</label>
</th>
<td class="w-9/12 pb-3">
<select class="relative form-select shadow-sm border border-gray-400 w-1/3 ml-12" name="template_id" id="base_template_id">
<?php
$templates = ES_Common::prepare_templates_dropdown_options( 'post_notification', $template_id );
echo wp_kses( $templates, $allowedtags );
?>
</select>
<div class="es-preview" style="float: right;width: 25%;">
<div class="es-templ-img"></div>
</div>
</td>
</tr>
<?php do_action( 'es_after_post_notification_template', $id ); ?>
<tr class="border-b border-gray-100">
<th scope="row" class="pt-3 pb-8 w-3/12 text-left">
<label for="tag-link"><span class="block ml-6 pr-4 text-sm font-medium text-gray-600 pb-2"><?php esc_html_e( 'Select post category', 'email-subscribers' ); ?></span>
<p class="italic text-xs font-normal text-gray-400 mt-2 ml-6 leading-snug"><?php esc_html_e( 'Notification will be sent out when any post from selected categories will be published.', 'email-subscribers' ); ?></p></label>
</th>
<td class="pt-3 w-9/12" style="vertical-align: top;">
<table border="0" cellspacing="0" class="ml-4 pt-3">
<tbody>
<?php
$categories_lists = ES_Common::prepare_categories_html( $cat );
echo wp_kses( $categories_lists, $allowedtags );
?>
</tbody>
</table>
</td>
</tr>
<tr class="border-b border-gray-100">
<th scope="row" class="pt-3 pb-8 w-3/12 text-left">
<label for="tag-link"><span class="block ml-6 pr-4 text-sm font-medium text-gray-600 pb-2">
<?php esc_html_e( 'Select custom post type(s)', 'email-subscribers' ); ?></span>
<p class="italic text-xs font-normal text-gray-400 mt-2 ml-6 leading-snug"><?php esc_html_e( '(Optional) Select custom post type for which you want to send notification.', 'email-subscribers' ); ?></p></label>
</th>
<td class="w-9/12 pt-3 pb-8">
<table border="0" cellspacing="0">
<tbody>
<?php
$custom_post_type = '';
$custom_post_type_list = ES_Common::prepare_custom_post_type_checkbox( $cat );
echo wp_kses( $custom_post_type_list, $allowedtags );
?>
</tbody>
</table>
</td>
</tr>
<?php do_action( 'es_after_post_notification_settings', $id ); ?>
<tr>
<td><input type="hidden" name="submitted" value="submitted"></td>
</tr>
</tbody>
</table>
<div>
<?php
$submit_button_text = $is_new ? __( 'Save Campaign', 'email-subscribers' ) : __( 'Save Changes', 'email-subscribers' );
?>
<p class="submit"><input type="submit" name="submit" id="ig_es_campaign_post_notification_submit_button" class="cursor-pointer align-middle ig-es-primary-button px-4 py-2 ml-6 mr-2" value="<?php echo esc_attr( $submit_button_text ); ?>"/>
<a href="admin.php?page=es_campaigns" class="cursor-pointer align-middle rounded-md border border-indigo-600 hover:shadow-md focus:outline-none focus:shadow-outline-indigo text-sm leading-5 font-medium transition ease-in-out duration-150 px-4 my-2 py-2 mx-2 "><?php esc_html_e( 'Cancel', 'email-subscribers' ); ?></a></p>
</div>
</form>
</div>
</div>
<?php
}
/**
* Returns an associative array containing the bulk action
*
* @return array
*/
public function get_bulk_actions() {
$actions = array(
'bulk_delete' => 'Delete',
);
return $actions;
}
public function search_box( $text, $input_id ) {
?>
<p class="search-box">
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_html( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
<?php submit_button( 'Search Notifications', 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
</p>
<?php
}
public function show_summary_actions_buttons( $campaign_data ) {
$campaign_status = ! empty( $campaign_data['status'] ) ? (int) $campaign_data['status'] : IG_ES_CAMPAIGN_STATUS_IN_ACTIVE;
$is_campaign_inactive = IG_ES_CAMPAIGN_STATUS_IN_ACTIVE === $campaign_status;
if ( $is_campaign_inactive ) {
?>
<button type="button" id="activate_campaign_btn" name="ig_es_campaign_action" class="ig-es-inline-loader w-24 inline-flex justify-center py-1.5 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-transparent rounded-md md:px-2 lg:px-3 xl:px-4 md:ml-2 hover:bg-indigo-500 hover:text-white"
value="activate">
<span>
<?php
echo esc_html__( 'Activate', 'email-subscribers' );
?>
</span>
<svg class="es-btn-loader animate-spin h-4 w-4 text-indigo"
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"
stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</button>
<?php
}
}
public function show_post_notification_content_settings( $campaign_data ) {
$campaign_id = ! empty( $campaign_data['id'] ) ? $campaign_data['id'] : 0;
$campaign_type = ! empty( $campaign_data['type'] ) ? $campaign_data['type'] : '';
$editor_type = ! empty( $campaign_data['meta']['editor_type'] ) ? $campaign_data['meta']['editor_type'] : IG_ES_DRAG_AND_DROP_EDITOR;
if ( IG_ES_DRAG_AND_DROP_EDITOR === $editor_type ) {
$sidebar_id = 'sidebar_campaign_settings_' . $campaign_id;
?>
<div id="ig-es-post-notification-settings-popup" class="ig-es-post-notification-settings my-2 block pt-2 pb-4 mx-4 border-b border-gray-200" data-campaign-id="<?php echo esc_attr( $campaign_id ); ?>" data-campaign-type="<?php echo esc_attr( $campaign_type ); ?>" x-data="{ <?php echo esc_attr( $sidebar_id ); ?>: false }">
<h2 class="text-sm font-normal text-gray-600">
<span class=""><?php echo esc_html__( 'Posts settings:' ); ?></span>
</h2>
<p class="clear">
<a class="block edit-conditions rounded-md border text-indigo-600 border-indigo-500 text-sm leading-5 font-medium transition ease-in-out duration-150 select-none inline-flex justify-center hover:text-indigo-500 hover:border-indigo-600 hover:shadow-md focus:outline-none focus:shadow-outline-indigo focus:shadow-lg mt-1 px-1.5 py-1 mr-1 cursor-pointer" x-on:click="<?php echo esc_attr( $sidebar_id ); ?>=true">
<?php esc_html_e( 'Change posts settings', 'email-subscribers' ); ?>
</a>
</p>
<div class="fixed inset-0 overflow-hidden z-50" id='ig-es-post-notification-settings-<?php echo esc_attr( $sidebar_id ); ?>' style="display: none;" x-show="<?php echo esc_attr( $sidebar_id ); ?>">
<div class="absolute inset-0 overflow-hidden">
<div class="absolute inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
<section class="absolute inset-y-0 right-0 pl-10 max-w-full flex" aria-labelledby="slide-over-heading">
<div class="relative w-screen max-w-3xl mt-8"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0 -translate-x-full"
x-transition:enter-end="opacity-100 translate-x-0"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100 translate-x-0"
x-transition:leave-end="opacity-0 -translate-x-full">
<div class="h-full flex flex-col bg-gray-50 shadow-xl overflow-y-auto">
<div class="flex py-5 px-6 bg-gray-100 shadow-sm sticky">
<div class="w-9/12">
<span id="slide-over-heading" class="text-xl font-medium text-gray-600">
<?php echo esc_html__( 'Posts Settings', 'email-subscribers' ); ?>
</span>
</div>
<div class="w-3/12 text-right">
<span class="es_spinner_image_admin inline-block align-middle -mt-1 mr-1" id="spinner-image" style="display:none"><img src="<?php echo esc_url( ES_PLUGIN_URL . 'lite/public/images/spinner.gif' ); ?>" alt="<?php echo esc_attr__( 'Loading...', 'email-subscribers' ); ?>"/></span>
<a class="-mt-1 mr-2 px-3 py-0.5 ig-es-primary-button cursor-pointer close-conditions" x-on:click=" <?php echo esc_attr( $sidebar_id ); ?> = false"><?php esc_html_e( 'Save', 'email-subscribers' ); ?></a>
<a x-on:click=" <?php echo esc_attr( $sidebar_id ); ?> = false" class="-mt-1 rounded-md text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-white cursor-pointer">
<span class="sr-only"><?php echo esc_html__( 'Close panel', 'email-subscribers' ); ?></span>
<!-- Heroicon name: outline/x -->
<svg class="h-6 w-6 inline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</a>
</div>
</div>
<div class="mt-3 px-6 pb-6 relative flex-1 w-full">
<?php
$this->show_post_notification_fields( $campaign_data );
?>
</div>
</div>
</section>
</div>
</div>
</div>
<?php
} else {
$this->show_post_notification_fields( $campaign_data );
}
}
/**
* Show post notification related fields
*
* Post categories etc.
*
* @since 5.1.0
*
* @param array $campaign_data
*/
public function show_post_notification_fields( $campaign_data ) {
// We are storing both post categories and CPTs in one column 'categories'.
$categories = isset( $campaign_data['categories'] ) ? $campaign_data['categories'] : '';
$campaign_id = ! empty( $campaign_data['id'] ) ? $campaign_data['id'] : 0;
$selected_post_types = array();
$using_new_category_format = ES_Campaign_Controller::is_using_new_category_format( $campaign_id );
if ( $using_new_category_format ) {
$cat_cpts = array();
$categories_str = trim( trim( $categories ), '##' );
$categories_array = explode( '##', $categories_str );
if ( ! empty( $categories_array ) ) {
foreach ( $categories_array as $category ) {
$cpt_categories = explode( '|', $category );
foreach ( $cpt_categories as $cpt_category ) {
if ( false !== strpos( $cpt_category, ':' ) ) {
list( $post_type, $post_type_categories ) = explode( ':', $cpt_category );
if ( 'post' === $post_type ) {
$cat_cpts = explode( ',', $post_type_categories );
}
$selected_post_types[] = $post_type;
}
}
}
}
} else {
$cat_cpts = ES_Common::convert_categories_string_to_array( $categories, true );
}
$allowedtags = ig_es_allowed_html_tags_in_esc();
$campaign_type = ! empty( $campaign_data['type'] ) ? $campaign_data['type'] : '';
$editor_type = ! empty( $campaign_data['meta']['editor_type'] ) ? $campaign_data['meta']['editor_type'] : IG_ES_DRAG_AND_DROP_EDITOR;
?>
<div class="ig-es-campaign-categories-wrapper block mx-4 border-b border-gray-200 pt-4 pb-4">
<div scope="row" class="pb-1 text-left">
<label for="tag-link"><span class="block text-sm font-medium text-gray-600"><?php esc_html_e( 'Select post category', 'email-subscribers' ); ?></span></label>
</div>
<div style="vertical-align: top;">
<table border="0" cellspacing="0" class="pt-3">
<tbody>
<?php
$categories_lists = ES_Common::prepare_categories_html( $cat_cpts );
echo wp_kses( $categories_lists, $allowedtags );
?>
</tbody>
</table>
</div>
</div>
<div class="ig-es-campaign-custom-post-type-wrapper border-b border-gray-100 mx-4 pt-4 pb-2">
<div scope="row" class="text-left">
<label for="tag-link"><span class="block pb-1 text-sm font-medium text-gray-600 pb-2">
<?php esc_html_e( 'Select post type(s)', 'email-subscribers' ); ?></span>
</label>
</div>
<div class="ig-es-cpt-filters">
<table border="0" cellspacing="0">
<tbody>
<?php
if ( ! $using_new_category_format ) {
if ( ! empty( $cat_cpts ) ) {
foreach ( $cat_cpts as $cat_cpt ) {
// CPTs are stored in the 'categories' column with {T} prefix/suffix.
$is_post_type = strpos( $cat_cpt, '{T}' ) !== false;
if ( $is_post_type ) {
$selected_post_types[] = str_replace( '{T}', '', $cat_cpt );
}
}
}
}
$custom_post_types = ES_Common::get_custom_post_types();
$default_post_types = ES_Common::get_default_post_types();
$post_types = array_merge( $custom_post_types, $default_post_types );
if ( ! empty( $post_types ) ) {
foreach ( $post_types as $post_type ) {
$is_cpt_selected = in_array( $post_type, $selected_post_types, true );
if ( $is_cpt_selected ) {
$checked = 'checked="checked"';
} else {
$checked = '';
}
$post_type_object = get_post_type_object( $post_type );
$post_type__name = $post_type_object->labels->singular_name;
?>
<tr class="es-post-types-row<?php echo $is_cpt_selected ? ' checked' : ''; ?>">
<td style="padding-top:4px;padding-bottom:4px;padding-right:10px;">
<span class="block pr-4 text-sm font-medium text-gray-600 pb-2">
<input
type="checkbox"
id="es_custom_post_type_<?php echo esc_attr( $post_type ); ?>" name="data[es_note_cpt][]"
value="<?php echo '{T}' . esc_html( $post_type ) . '{T}'; ?>"
<?php echo esc_attr( $checked ); ?>
class="es_custom_post_type form-checkbox"
>
<label for="es_custom_post_type_<?php echo esc_attr( $post_type ); ?>">
<?php echo esc_html( $post_type__name ); ?>
</label>
</span>
<?php
do_action( 'ig_es_after_post_type_checkbox', $post_type, $campaign_data );
?>
</td>
</tr>
<?php
}
} else {
?>
<tr>
<span class="block pr-4 text-sm font-normal text-gray-600 pb-2">
<?php echo esc_html__( 'No Custom Post Types Available', 'email-subscribers' ); ?>
</span>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</div>
<?php
if ( IG_ES_DRAG_AND_DROP_EDITOR === $editor_type ) {
do_action( 'ig_es_show_' . $campaign_type . '_fields', $campaign_data );
}
}
/**
* Get default subject for post notification campaign
*
* @param string $subject
* @return string $subject
*
* @since 5.3.2
*/
public function get_post_notification_default_subject( $subject ) {
if ( empty( $subject ) ) {
$subject = __( 'New Post Published - {{post.title}}', 'email-subscribers' );
}
return $subject;
}
public function get_post_notification_default_content( $content_data ) {
if ( empty( $content_data ) ) {
$dnd_editor_content = $this->get_dnd_editor_default_content();
$classic_editor_content = wpautop( $this->get_classic_editor_default_content() );
$content_data = array(
IG_ES_CLASSIC_EDITOR => $classic_editor_content,
IG_ES_DRAG_AND_DROP_EDITOR => $dnd_editor_content
);
}
return $content_data;
}
public function get_classic_editor_default_content() {
$default_content = __( "Hello {{subscriber.name | fallback='there'}},", 'email-subscribers' ) . "\r\n\r\n";
$default_content .= __( 'We have published a new blog article on our website.', 'email-subscribers' ) . "\r\n";
$default_content .= "{{campaign.posts}}\r\n{{post.title}}\r\n {{post.image}}\r\n\r\n";
$default_content .= "{{post.link}}\r\n{{/campaign.posts}}\r\n\r\n";
$default_content .= __( 'Thanks & Regards', 'email-subscribers' ) . ",\r\n";
$default_content .= __( 'Admin', 'email-subscribers' ) . "\r\n\r\n";
$default_content .= __( 'You received this email because in the past you have provided us your email address : {{subscriber.email}} to receive notifications when new updates are posted.', 'email-subscribers' );
return $default_content;
}
public function get_dnd_editor_default_content() {
$default_content = '<mjml>
<mj-body>
<mj-section background-color="#FFFFFF">
<mj-column width="100%">
<mj-image src="https://webstockreview.net/images/sample-png-images-14.png" height="70px"
width="140px"/>
</mj-column>
</mj-section>
<mj-section background-color="#FFFFFF">
<mj-column width="100%">
<mj-text line-height="26px">' . __( "Hello {{subscriber.name | fallback='there'}},", 'email-subscribers' ) . '</mj-text>
<mj-text line-height="26px">' . __( 'We have published a new post on our site.', 'email-subscribers' ) . '</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#FFFFFF">
<mj-column width="100%">
<div class="es-posts">
<span style="visibility:hidden;font-size:3px">{{campaign.posts}}</span>
<mj-section class="post-format-content" background-color="#ffffff" padding-top="0px" padding-bottom="0px">
<mj-group>
<mj-column width="100%">
<mj-text line-height="26px">
<font size="4">{{post.title}}</font>
</mj-text>
<mj-text line-height="26px" font-size="14px">
{{post.excerpt}}
</mj-text>
<mj-button border-radius="5px 5px 5px 5px" align="left" href="{{post.link_only}}" container-background-color="#ffffff" background-color="#e69626" id="ikaqh">
Read More
</mj-button>
</mj-column>
</mj-group>
</mj-section>
<span style="visibility:hidden;font-size:3px">{{/campaign.posts}}</span>
</div>
</mj-column>
</mj-section>
<mj-section background-color="#f3f3f3">
<mj-column width="100%">
<mj-text align="center" line-height="26px">@2022,' . __( 'Your Brand Name', 'email-subscribers' ) . '.</mj-text>
<mj-text align="center" line-height="26px">' . __( 'You received this email because in the past you have provided us your email address : {{subscriber.email}} to receive notifications when new updates are posted.', 'email-subscribers' ) . __( 'If you wish to unsubscribe from our newsletter, click', 'email-subscribers' ) . ' <a data-gjs-type="link" href="{{UNSUBSCRIBE-LINK}}" >' . __( 'here', 'email-subscribers' ) . '</a>
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml> ';
return $default_content;
}
}
ES_Post_Notifications_Table::get_instance();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,644 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_Reports_Data' ) ) {
/**
* Get Reports Data
* Class ES_Reports_Data
*
* @since 4.3.2
*/
class ES_Reports_Data {
/**
* Get total Contacts
*
* @since 4.3.2
*/
public static function get_total_contacts() {
return ES()->contacts_db->get_total_contacts();
}
/**
* Get total subscribed contacts in last $days
*
* @param int $days
*
* @return int
*
* @since 4.3.2
* @since 4.3.5 Modified ES_DB_Lists_Contacts::get_total_subscribed_contacts to
* ES()->lists_contacts_db->get_total_subscribed_contacts
* @since 4.3.6 Modified function name from get_subscribed_contacts_count to get_subscribed_contacts_count
*/
public static function get_total_subscribed_contacts( $args = array() ) {
$distinct = true;
$list_id = ! empty( $args['list_id'] ) ? $args['list_id'] : 0;
$days = ! empty( $args['days'] ) ? $args['days'] : 0;
return ES()->lists_contacts_db->get_contacts( 'subscribed', $list_id, $days, true, $distinct );
}
/**
* Get total unsubscribed contacts in last $days
*
* @param int $days
*
* @return int
*
* @since 4.3.2
* @since 4.3.5 Modified ES_DB_Lists_Contacts::get_total_unsubscribed_contacts to
* ES()->lists_contacts_db->get_total_unsubscribed_contacts
* @since 4.3.6 Modified function name from get_total_unsubscribed_contacts to get_unsubscribed_contacts_count
*/
public static function get_total_unsubscribed_contacts( $args = array() ) {
$days = ! empty( $args['days'] ) ? $args['days'] : 0;
return ES()->lists_contacts_db->get_unsubscribed_contacts_count( $days );
}
/**
* Get total unconfiremed contacts in last $days
*
* @param int $days
*
* @return int
*
* @since 4.5.7
*/
public static function get_total_unconfirmed_contacts( $args = array() ) {
$days = ! empty( $args['days'] ) ? $args['days'] : 0;
return ES()->lists_contacts_db->get_unconfirmed_contacts_count( $days );
}
/**
* Get total contacts have opened emails in last $days
*
* @param int $days
*
* @return int
*
* @since 4.3.2
*
* @modify 5.5.5 Used ES()->actions_db->get_count() function to get type
*/
public static function get_total_contacts_opened_emails( $args = array(), $distinct = true ) {
$args['type'] = IG_MESSAGE_OPEN;
return ES()->actions_db->get_count( $args, $distinct );
}
/**
* Get total contacts have clicked on links in emails in last $days
*
* @param int $days
*
* @return int
*
* @since 4.3.2
*
* @modify 5.5.5 Used ES()->actions_db->get_count() function to get type
*/
public static function get_total_contacts_clicks_links( $args = array(), $distinct = true ) {
$args['type'] = IG_LINK_CLICK;
return ES()->actions_db->get_count( $args, $distinct );
}
/**
* Get total emails sent in last $days
*
* @param int $days
*
* @return int
*
* @modify 5.5.5 Used ES()->actions_db->get_count() function to get type
*/
public static function get_total_emails_sent( $args = array(), $distinct = true ) {
$args['type'] = IG_MESSAGE_SENT;
return ES()->actions_db->get_count( $args, $distinct );
}
/**
* Get total contacts lost in last $days
*
* @param int $days
*
* @return int
*
* @modify 5.5.5 Used ES()->actions_db->get_count() function to get type
*/
public static function get_total_contact_unsubscribed( $args = array(), $distinct = true ) {
$args['type'] = IG_CONTACT_UNSUBSCRIBE;
return ES()->actions_db->get_count( $args, $distinct );
}
/**
* Get contacts growth
*
* @param int $days
*
* @return array
*
* @since 4.4.0
*/
public static function get_contacts_growth( $days = 60 ) {
$contacts = ES()->contacts_db->get_total_contacts_by_date();
$total = ES()->contacts_db->get_total_subscribed_contacts_before_days( $days );
$data = array();
for ( $i = $days; $i >= 0; $i -- ) {
$date = gmdate( 'Y-m-d', strtotime( '-' . $i . ' days' ) );
$count = isset( $contacts[ $date ] ) ? $contacts[ $date ] : 0;
$total += $count;
$data[ $date ] = $total;
}
return $data;
}
/**
* Get contacts growth percentage
*
* @param int $days
*
* @return float|integer
*
* @since 4.8.0
*/
public static function get_contacts_growth_percentage( $args = array() ) {
$days = ! empty( $args['days'] ) ? $args['days'] : 60;
//For example, It will get last 60'days subscribers count
$present_subscribers_count = ES()->lists_contacts_db->get_subscribed_contacts_count( $days );
//For example, It will get last 120'days subscribers count
$past_to_present_subscribers_count = ES()->lists_contacts_db->get_subscribed_contacts_count( $days * 2 );
//For example, It will get last 60-120'days subscribers count
$past_subscribers_count = intval( $past_to_present_subscribers_count ) - intval( $present_subscribers_count );
if ( 0 === $past_subscribers_count ) {
return 0;
} else {
return round( ( $present_subscribers_count - $past_subscribers_count ) / $past_subscribers_count * 100, 2 );
}
}
/**
* Collect dashboard reports data
*
* @return array
*
* @since 4.4.0
*/
public static function get_dashboard_reports_data( $page, $override_cache = false, $args = array(), $campaign_count = 3 ) {
/**
* - Get Total Contacts
* - Get Total Forms
* - Get Total Lists
* - Get Total Campaigns
* - Get Last 3 months contacts data
* - Total Email Opened in last 60 days
* - Total Message Sent in last 60 days
* - Avg. Email Click rate
*/
$cache_key = 'dashboard_reports_data';
if ( ! $override_cache ) {
$cached_data = ES_Cache::get_transient( $cache_key );
if ( ! empty( $cached_data ) ) {
return $cached_data;
}
}
$total_subscribed = self::get_total_subscribed_contacts( $args );
$action_types = ES()->get_action_types();
$args['types'] = $action_types;
$actions_counts = ES()->actions_db->get_actions_count( $args );
$total_email_opens = $actions_counts['opened'];
$total_links_clicks = $actions_counts['clicked'];
$total_message_sent = $actions_counts['sent'];
$total_unsubscribed = $actions_counts['unsubscribed'];
$contacts_growth = self::get_contacts_growth();
$avg_open_rate = 0;
if ( $total_message_sent > 0 ) {
$avg_open_rate = ( $total_email_opens * 100 ) / $total_message_sent;
}
$avg_click_rate = 0;
if ( $total_message_sent > 0 ) {
$avg_click_rate = ( $total_links_clicks * 100 ) / $total_message_sent;
}
$avg_unsubscribe_rate = 0;
if ( $total_message_sent > 0 ) {
$avg_unsubscribe_rate = ( $total_unsubscribed * 100 ) / $total_message_sent;
}
/**
* - Get recent 10 campaigns
* - Get total open (3)
* - Get total clicks (4)
* - Get total unsubscribe (5)
*/
$data = array();
if ( 'es_dashboard' === $page || 'wp_dashboard' === $page ) {
$data = self::get_campaign_stats( $campaign_count );
}
$reports_data = array(
'total_subscribed' => number_format( $total_subscribed ),
'total_email_opens' => number_format( $total_email_opens ),
'total_links_clicks' => number_format( $total_links_clicks ),
'total_message_sent' => number_format( $total_message_sent ),
'total_unsubscribed' => number_format( $total_unsubscribed ),
'avg_open_rate' => number_format( $avg_open_rate, 2 ),
'avg_click_rate' => number_format( $avg_click_rate, 2 ),
'avg_unsubscribe_rate' => number_format( $avg_unsubscribe_rate, 2 ),
'contacts_growth' => $contacts_growth,
);
$include_average_campaigns_stats = 'es_dashboard' === $page || 'es_campaigns' === $page;
if ( $include_average_campaigns_stats ) {
$comp_args = $args;
$comp_args['days'] = $args['days'] * 2;
$last_four_months_actions_count = ES()->actions_db->get_actions_count( $comp_args );
$last_four_months_sent = $last_four_months_actions_count['sent'];
$sent_before_two_months = $last_four_months_sent - $total_message_sent;
if ( $sent_before_two_months > 0 ) {
$sent_percentage_growth = ( ( $total_message_sent - $sent_before_two_months ) / $sent_before_two_months ) * 100;
} else {
$sent_percentage_growth = 0;
}
$last_four_months_opens = $last_four_months_actions_count['opened'];
$open_before_two_months = $last_four_months_opens - $total_email_opens;
if ( $open_before_two_months > 0 ) {
$open_percentage_growth = ( ( $total_email_opens - $open_before_two_months ) / $open_before_two_months ) * 100;
} else {
$open_percentage_growth = 0;
}
$last_four_months_clicks = $last_four_months_actions_count['clicked'];
$click_before_two_months = $last_four_months_clicks - $total_links_clicks;
if ( $click_before_two_months > 0 ) {
$click_percentage_growth = ( ( $total_links_clicks - $click_before_two_months ) / $click_before_two_months ) * 100;
} else {
$click_percentage_growth = 0;
}
$last_four_months_unsubscribes = $last_four_months_actions_count['unsubscribed'];
$unsubscribes_before_two_months = $last_four_months_unsubscribes - $total_unsubscribed;
if ( $unsubscribes_before_two_months > 0 ) {
$unsubscribes_percentage_growth = ( ( $total_unsubscribed - $unsubscribes_before_two_months ) / $unsubscribes_before_two_months ) * 100;
} else {
$unsubscribes_percentage_growth = 0;
}
if ( isset( $actions_counts['hard_bounced'] ) ) {
$total_hard_bounces = $actions_counts['hard_bounced'];
$last_four_months_hard_bounces = $last_four_months_actions_count['hard_bounced'];
$hard_bounces_before_two_months = $last_four_months_hard_bounces - $total_hard_bounces;
if ( $hard_bounces_before_two_months > 0 ) {
$hard_bounces_percentage_growth = ( ( $total_hard_bounces - $hard_bounces_before_two_months ) / $hard_bounces_before_two_months ) * 100;
} else {
$hard_bounces_percentage_growth = 0;
}
if ( $total_message_sent > 0 ) {
$avg_bounce_rate = ( $total_hard_bounces * 100 ) / $total_message_sent;
$reports_data['avg_bounce_rate'] = $avg_bounce_rate ? number_format_i18n( $avg_bounce_rate, 2 ) : 0;
}
$reports_data['total_hard_bounced_contacts'] = number_format_i18n( $total_hard_bounces );
$reports_data['hard_bounces_before_two_months'] = number_format_i18n( $hard_bounces_before_two_months );
$reports_data['hard_bounces_percentage_growth'] = 0 !== $hard_bounces_percentage_growth ? number_format_i18n( $hard_bounces_percentage_growth, 2 ) : 0;
}
$reports_data['sent_percentage_growth'] = 0 !== $sent_percentage_growth ? number_format_i18n( $sent_percentage_growth, 2 ) : 0;
$reports_data['sent_before_two_months'] = number_format_i18n( $sent_before_two_months );
$reports_data['open_percentage_growth'] = 0 !== $open_percentage_growth ? number_format_i18n( $open_percentage_growth, 2 ) : 0;
$reports_data['open_before_two_months'] = number_format_i18n( $open_before_two_months );
$reports_data['click_percentage_growth'] = 0 !== $click_percentage_growth ? number_format_i18n( $click_percentage_growth, 2 ) : 0;
$reports_data['click_before_two_months'] = number_format_i18n( $click_before_two_months );
$reports_data['unsubscribe_percentage_growth'] = 0 !== $unsubscribes_percentage_growth ? number_format_i18n( $unsubscribes_percentage_growth, 2 ) : 0;
$reports_data['unsubscribe_before_two_months'] = number_format_i18n( $unsubscribes_before_two_months );
}
$data = array_merge( $data, $reports_data );
ES_Cache::set_transient( $cache_key, $data, 1 * HOUR_IN_SECONDS );
return $data;
}
/**
* Get Campaigns Stats
*
* @return array
*
* @since 4.7.8
*/
public static function get_campaign_stats( $total_campaigns = 5 ) {
global $wpdb;
$campaigns = ES_DB_Mailing_Queue::get_recent_campaigns( $total_campaigns );
$campaigns_data = array();
if ( ! empty( $campaigns ) && count( $campaigns ) > 0 ) {
foreach ( $campaigns as $key => $campaign ) {
$message_id = $campaign['id'];
$campaign_id = $campaign['campaign_id'];
if ( 0 === $campaign_id ) {
continue;
}
$results = $wpdb->get_results( $wpdb->prepare( "SELECT type, count(DISTINCT (contact_id) ) as total FROM {$wpdb->prefix}ig_actions WHERE message_id = %d AND campaign_id = %d GROUP BY type", $message_id, $campaign_id ), ARRAY_A );
$stats = array();
$type = '';
$type_text = '';
if ( count( $results ) > 0 ) {
foreach ( $results as $result ) {
$type = $result['type'];
$total = $result['total'];
switch ( $type ) {
case IG_MESSAGE_SENT:
$type_text = 'total_sent';
break;
case IG_MESSAGE_OPEN:
$type_text = 'total_opens';
break;
case IG_LINK_CLICK:
$type_text = 'total_clicks';
break;
case IG_CONTACT_UNSUBSCRIBE:
$type_text = 'total_unsubscribe';
break;
}
$stats[ $type_text ] = $total;
}
}
$stats = wp_parse_args(
$stats,
array(
'total_sent' => 0,
'total_opens' => 0,
'total_clicks' => 0,
'total_unsubscribe' => 0,
)
);
if ( 0 != $stats['total_sent'] ) {
$campaign_opens_rate = ( $stats['total_opens'] * 100 ) / $stats['total_sent'];
$campaign_clicks_rate = ( $stats['total_clicks'] * 100 ) / $stats['total_sent'];
$campaign_losts_rate = ( $stats['total_unsubscribe'] * 100 ) / $stats['total_sent'];
} else {
$campaign_opens_rate = 0;
$campaign_clicks_rate = 0;
$campaign_losts_rate = 0;
}
$campaign_type = ES()->campaigns_db->get_column( 'type', $campaign_id );
if ( 'newsletter' === $campaign_type ) {
$type = __( 'Broadcast', 'email-subscribers' );
} elseif ( 'post_notification' === $campaign_type ) {
$type = __( 'Post Notification', 'email-subscribers' );
} elseif ( 'post_digest' === $campaign_type ) {
$type = __( 'Post Digest', 'email-subscribers' );
}
$start_at = gmdate( 'd F', strtotime( $campaign['start_at'] ) );
$finish_at = gmdate( 'd F', strtotime( $campaign['finish_at'] ) );
$campaigns_data[ $key ] = $stats;
$campaigns_data[ $key ]['title'] = $campaign['subject'];
$campaigns_data[ $key ]['hash'] = $campaign['hash'];
$campaigns_data[ $key ]['status'] = $campaign['status'];
$campaigns_data[ $key ]['campaign_type'] = $campaign_type;
$campaigns_data[ $key ]['type'] = $type;
$campaigns_data[ $key ]['total_sent'] = $stats['total_sent'];
$campaigns_data[ $key ]['campaign_opens_rate'] = round( $campaign_opens_rate );
$campaigns_data[ $key ]['campaign_clicks_rate'] = round( $campaign_clicks_rate );
$campaigns_data[ $key ]['campaign_losts_rate'] = round( $campaign_losts_rate );
$campaigns_data[ $key ]['start_at'] = $start_at;
$campaigns_data[ $key ]['finish_at'] = $finish_at;
}
}
$data['campaigns'] = $campaigns_data;
return $data;
}
public static function can_show_campaign_stats( $source = '' ) {
if ( 'es_dashboard' === $source && ! ES()->is_pro() ) {
return false;
}
return true;
}
public static function get_top_performing_campaigns( $start_time, $campaign_count = 3 ) {
global $wpdb;
$top_campaigns = $wpdb->get_results(
$wpdb->prepare(
"SELECT campaign_id,message_id, SUM( IF( `type` = 2, 1, 0 ) ) AS 'sent',SUM(IF( `type` = 3, 1, 0 )) AS 'opens_count', (SUM(IF( `type` = 3, 1, 0 ))/SUM( IF( `type` = 2, 1, 0 ))) * 100 AS opened_percentage FROM `{$wpdb->prefix}ig_actions` WHERE campaign_id IS NOT NULL AND message_id IS NOT NULL AND message_id != 0 AND updated_at > %d GROUP BY campaign_id, message_id ORDER BY `opened_percentage` DESC LIMIT %d",
$start_time,
$campaign_count
),
ARRAY_A
);
return $top_campaigns;
}
public static function show_device_opens_stats( $device_opens_data ) {
//Graph for Device Opens
$device_opened = array();
$device_label = array();
ob_start();
if ( ! empty( $device_opens_data ) && ! empty( array_filter( $device_opens_data ) ) ) {
$device_label = array_map( 'ucfirst' , array_keys( $device_opens_data ) );
$device_opened = array_values( $device_opens_data );
?>
<div class="relative bg-white mt-2" id="device_open_graph"></div>
<?php
} else {
?>
<div class="mt-2 bg-white text-sm text-gray-500 py-3 px-6 tracking-wide">
<?php echo esc_html__( 'No device data found', 'email-subscribers' ); ?>
</div>
<?php
}
$stats_html = ob_get_clean();
$allowedtags = ig_es_allowed_html_tags_in_esc();
//$stats_html = ES_Common::get_tooltip_html( $stats_html );
echo wp_kses( $stats_html, $allowedtags );
?>
<script type="text/javascript">
jQuery(document).ready(function ($) {
let device_data = {
labels: <?php echo json_encode( $device_label ); ?>,
datasets: [
{
name: "device",
type: "pie",
values: <?php echo json_encode( $device_opened ); ?>,
}
]
}
const device_chart = new frappe.Chart("#device_open_graph", {
title: "",
data: device_data,
type: 'pie',
colors: ['#743ee2', '#5DADE2', '#F6608B'],
height: 30,
width:30,
maxSlices: 3,
});
});
</script>
<?php
}
public static function show_sources_stats( $subscriber_source_counts ) {
//Graph for Device Opens
$source_opened = array();
$source_label = array();
ob_start();
if ( ! empty( $subscriber_source_counts ) && ! empty( array_filter( $subscriber_source_counts ) ) ) {
$source_label = array_map( 'ucfirst' , array_keys( $subscriber_source_counts ) );
$source_opened = array_values( $subscriber_source_counts );
?>
<div class="bg-white mt-2" id="sources_graph"></div>
<?php
} else {
?>
<div class="mt-2 bg-white text-sm text-gray-500 py-3 px-6">
<?php echo esc_html__( 'No source data found', 'email-subscribers' ); ?>
</div>
<?php
}
$stats_html = ob_get_clean();
$allowedtags = ig_es_allowed_html_tags_in_esc();
//$stats_html = ES_Common::get_tooltip_html( $stats_html );
echo wp_kses( $stats_html, $allowedtags );
?>
<script type="text/javascript">
jQuery(document).ready(function ($) {
let source_data = {
labels: <?php echo json_encode( $source_label ); ?>,
datasets: [
{
name: "source",
type: "percentage",
values: <?php echo json_encode( $source_opened ); ?>,
}
]
}
const source_chart = new frappe.Chart("#sources_graph", {
title: "",
data: source_data,
type: 'percentage',
colors: ['#743ee2', '#5DADE2', '#F6608B'],
height: 80,
maxSlices: 3,
});
});
</script>
<?php
}
public static function show_unsubscribe_feedback_percentage_stats( $feedback_percentages ) {
//Graph for Device Opens
$unsubscribe_feedback_opened = array();
$unsubscribe_feedback_label = array();
ob_start();
if ( ! empty( $feedback_percentages ) && ! empty( array_filter( $feedback_percentages ) ) ) {
$unsubscribe_feedback_label = array_map( 'ucfirst' , array_keys( $feedback_percentages ) );
$unsubscribe_feedback_opened = array_values( $feedback_percentages );
?>
<div class="relative bg-white mt-2 rounded-md shadow" id="unsubscribe_feedbacks_graph"></div>
<?php
} else {
?>
<div class="mt-2 bg-white text-sm text-gray-500 rounded-md shadow py-3 px-6 tracking-wide">
<?php echo esc_html__( 'No data found', 'email-subscribers' ); ?>
</div>
<?php
}
$stats_html = ob_get_clean();
$allowedtags = ig_es_allowed_html_tags_in_esc();
$stats_html = ES_Common::get_tooltip_html( $stats_html );
echo wp_kses( $stats_html, $allowedtags );
?>
<script type="text/javascript">
jQuery(document).ready(function ($) {
let unsubscribe_feedback_data = {
labels: <?php echo json_encode( $unsubscribe_feedback_label ); ?>,
datasets: [
{
name: "unsubscribe_feedback",
type: "pie",
values: <?php echo json_encode( $unsubscribe_feedback_opened ); ?>,
}
]
}
const unsubscribe_feedback_chart = new frappe.Chart("#unsubscribe_feedbacks_graph", {
title: "",
data: unsubscribe_feedback_data,
type: 'pie',
colors: ['#743ee2', '#5DADE2', '#F6608B'],
height: 280,
maxSlices: 3,
});
});
</script>
<?php
}
}
}

View File

@@ -0,0 +1,675 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Reports_Table extends ES_List_Table {
public static $instance;
public function __construct() {
parent::__construct(
array(
'singular' => __( 'Report', 'email-subscribers' ), // singular name of the listed records
'plural' => __( 'Reports', 'email-subscribers' ), // plural name of the listed records
'ajax' => false, // does this table support ajax?,
'screen' => 'es_reports',
)
);
add_action( 'admin_footer', array( $this, 'display_preview_email' ), 10 );
}
public function es_reports_callback() {
$campaign_id = ig_es_get_request_data( 'campaign_id' );
$campaign_type = '';
// Since, currently we are not passing campaign_id with broadcast $campaign_type will remain empty for broadcast
if ( ! empty( $campaign_id ) ) {
$campaign_type = ES()->campaigns_db->get_campaign_type_by_id( $campaign_id );
}
$campaign_types = array( 'sequence', 'sequence_message', 'workflow', 'workflow_email' );
// Only if it is sequence then control will transfer to Sequence Reports class.
if ( ! empty( $campaign_type ) && in_array( $campaign_type, $campaign_types, true ) ) {
if ( ES()->is_pro() ) {
$reports = ES_Pro_Sequence_Reports::get_instance();
$reports->es_sequence_reports_callback();
} else {
do_action( 'ig_es_view_report_data' );
}
} else {
$action = ig_es_get_request_data( 'action' );
if ( 'view' === $action ) {
$view_report = new ES_Campaign_Report();
$view_report->es_campaign_report_callback();
} else {
?>
<div class="wrap pt-4 font-sans">
<header class="wp-heading-inline">
<div class="flex">
<div class="flex-1 min-w-0">
<h2 class="text-3xl font-bold leading-9 text-gray-700 sm:truncate"><?php esc_html_e( 'Reports', 'email-subscribers' ); ?>
</h2>
</div>
<?php
$emails_to_be_sent = ES_DB_Sending_Queue::get_total_emails_to_be_sent();
if ( $emails_to_be_sent > 0 ) {
$cron_url = ES()->cron->url( true );
/* translators: %s: Cron url */
$content = '<a href="' . esc_url( $cron_url ) . '" class="px-3 py-2 ig-es-imp-button">' . esc_html__( 'Send Queued Emails Now', 'email-subscribers' ) . '</a>';
} else {
$content = '<span class="ig-es-send-queue-emails px-3 button-disabled">' . esc_html__( 'Send Queued Emails Now', 'email-subscribers' ) . '</span>';
$content .= '<br /><span class="es-helper pl-6">' . esc_html__( 'No emails found in queue', 'email-subscribers' ) . '</span>';
}
?>
<div class="flex flex-row">
<div>
<span class="ig-es-process-queue"><?php echo wp_kses_post( $content ); ?></span>
</div>
</div>
</div>
</header>
<?php
$show_campaign_notice = $emails_to_be_sent > 0 && ES()->is_starter();
if ( $show_campaign_notice ) {
?>
<style>
#ig-es-edit-campaign-notice p {
margin: 0.2em 0;
}
</style>
<div id="ig-es-edit-campaign-notice" class="px-5 py-2 notice notice-info">
<p>
<?php
/* translators: 1. Pause icon HTML 2. Resume icon HTML */
echo sprintf( esc_html__( 'While the campaign is still sending, you can pause %1$s it anytime and update the campaign. Once you are done, resume %2$s the campaign.', 'email-subscribers' ), '<svg fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor" viewBox="0 0 24 24" class="h-6 w-6 text-gray-500 ml-1 inline">
<path d="M10 9v6m4-6v6m7-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>',
'<svg fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor" viewBox="0 0 24 24" class="h-6 w-6 text-blue-500 inline">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>' );
?>
</p>
<p>
<strong>
<?php
echo esc_html__( 'Note: ', 'email-subscribers' );
?>
</strong>
<?php
echo esc_html__( 'Changes will reflect from the next sending batch.', 'email-subscribers' );
?>
</p>
</div>
<?php
}
?>
<div>
<hr class="wp-header-end">
</div>
<div id="poststuff" class="es-items-lists">
<div id="post-body" class="metabox-holder column-1">
<div id="post-body-content">
<div class="meta-box-sortables ui-sortable">
<form method="get">
<input type="hidden" name="page" value="es_reports"/>
<?php
// Display search field and other available filter fields.
$this->prepare_items();
?>
</form>
<form method="post">
<?php
// Display bulk action fields, pagination and list items.
$this->display();
?>
</form>
</div>
</div>
</div>
<br class="clear">
</div>
</div>
<?php
}
}
}
public function screen_option() {
$option = 'per_page';
$args = array(
'label' => __( 'Reports', 'email-subscribers' ),
'default' => 10,
'option' => 'reports_per_page',
);
add_screen_option( $option, $args );
}
/** Text displayed when no list data is available */
public function no_items() {
esc_html_e( 'No Reports avaliable.', 'email-subscribers' );
}
/**
* Generates content for a single row of the table.
* Overrides WP_List_Table class single_row function.
*
* @since 4.7.8
*
* @param object|array $item The current item
*/
public function single_row( $item ) {
echo '<tr data-status="' . esc_attr( strtolower( $item['status'] ) ) . '">';
$this->single_row_columns( $item );
echo '</tr>';
}
/**
* Render a column when no column specific method exist.
*
* @param array $item
* @param string $column_name
*
* @return mixed
*/
public function column_default( $item, $column_name ) {
global $wpdb;
switch ( $column_name ) {
case 'start_at':
case 'finish_at':
return ig_es_format_date_time( $item[ $column_name ] );
case 'type':
if ( empty( $item['campaign_id'] ) ) {
$type = __( 'Post Notification', 'email-subscribers' );
} else {
$type = ES()->campaigns_db->get_campaign_type_by_id( $item['campaign_id'] );
$type = strtolower( $type );
$type = ( 'newsletter' === $type ) ? __( 'Broadcast', 'email-subscribers' ) : $type;
}
$type = ucwords( str_replace( '_', ' ', $type ) );
return $type;
case 'subject':
// case 'type':
// return ucwords($item[ $column_name ]);
case 'count':
return $item[ $column_name ];
case 'total_sent':
$total_emails_sent = ES()->actions_db->get_count_based_on_id_type( $item['campaign_id'], $item['id'], IG_MESSAGE_SENT );
return number_format_i18n( $total_emails_sent );
case 'total_opened':
$total_emails_sent = ES()->actions_db->get_count_based_on_id_type( $item['campaign_id'], $item['id'], IG_MESSAGE_SENT );
$total_emails_opened = ES()->actions_db->get_count_based_on_id_type( $item['campaign_id'], $item['id'], IG_MESSAGE_OPEN );
$open_rate = ! empty( $total_emails_sent) ? number_format_i18n( ( ( $total_emails_opened * 100 ) / $total_emails_sent ), 2 ) : 0;
return number_format_i18n( $total_emails_opened ) . esc_html( ' (' . $open_rate . '%)' );
default:
$column_data = isset( $item[ $column_name ] ) ? $item[ $column_name ] : '-';
return $column_data;
}
}
public function column_status( $item ) {
$report_status = $item['status'];
$status_html = '';
if ( IG_ES_MAILING_QUEUE_STATUS_SENT === $report_status ) {
$status_html = sprintf(
'<svg class="flex-shrink-0 h-6 w-6 text-green-400" fill="currentColor" viewBox="0 0 20 20">
<title>%s</title>
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
</svg>',
__( 'Sent', 'email-subscribers' )
);
} else {
if ( IG_ES_MAILING_QUEUE_STATUS_SENDING === $report_status ) {
$status_html = sprintf(
'<svg class="flex-shrink-0 h-6 w-6 text-yellow-400 inline" fill="currentColor" viewBox="0 0 20 20">
<title>%s</title>
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-8.707l-3-3a1 1 0 00-1.414 1.414L10.586 9H7a1 1 0 100 2h3.586l-1.293 1.293a1 1 0 101.414 1.414l3-3a1 1 0 000-1.414z" clip-rule="evenodd"/>
</svg>',
__( 'Sending', 'email-subscribers' )
);
} elseif ( IG_ES_MAILING_QUEUE_STATUS_PAUSED === $report_status ) {
$status_html = sprintf(
'<svg xmlns="http://www.w3.org/2000/svg" class="flex-shrink-0 h-6 w-6 inline text-gray-500" viewBox="0 0 20 20" fill="currentColor">
<title>%s</title>
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>',
__( 'Paused', 'email-subscribers' )
);
} elseif ( IG_ES_MAILING_QUEUE_STATUS_QUEUED === $report_status ) {
$status_html = sprintf(
'<svg class="flex-shrink-0 h-6 w-6 inline text-orange-400" fill="currentColor" viewBox="0 0 20 20">
<title>%s</title>
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/>
</svg>',
__( 'Scheduled', 'email-subscribers' )
);
} elseif ( IG_ES_MAILING_QUEUE_STATUS_FAILED === $report_status ) {
$status_html = sprintf(
'<svg class="flex-shrink-0 h-6 w-6 inline text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<title>%s</title>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>',
__( 'Failed', 'email-subscribers' )
);
}
$actions = array();
if ( in_array( $report_status, array( IG_ES_MAILING_QUEUE_STATUS_QUEUED, IG_ES_MAILING_QUEUE_STATUS_SENDING, IG_ES_MAILING_QUEUE_STATUS_FAILED ), true ) ) {
$actions['send_now'] = $this->prepare_send_now_url( $item );
}
$actions = apply_filters( 'ig_es_report_row_actions', $actions, $item );
$status_html = $status_html . $this->row_actions( $actions, true );
}
return $status_html;
}
/**
* Render the bulk edit checkbox
*
* @param array $item
*
* @return string
*/
public function column_cb( $item ) {
return sprintf(
'<input type="checkbox" name="bulk_delete[]" value="%s" />',
$item['id']
);
}
/**
* Method for name column
*
* @param array $item an array of DB data
*
* @return string
*/
public function column_subject( $item ) {
$es_nonce = wp_create_nonce( 'es_notification' );
$page = ig_es_get_request_data( 'page' );
$title = '<strong>' . $item['subject'] . '</strong>';
$actions = array(
'view' => sprintf( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s" class="text-indigo-600">%s</a>', esc_attr( $page ), 'view', $item['hash'], $es_nonce, __( 'View', 'email-subscribers' ) ),
'delete' => sprintf( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s" onclick="return checkDelete()">%s</a>', esc_attr( $page ), 'delete', absint( $item['id'] ), $es_nonce, __( 'Delete', 'email-subscribers' ) ),
'preview_email' => sprintf( '<a href="#" data-campaign-id="%s" class="es-preview-report text-indigo-600">%s</a><img class="es-preview-loader inline-flex align-middle pl-2 h-5 w-7" src="%s" style="display:none;"/>', absint( $item['id'] ), __( 'Preview', 'email-subscribers' ), esc_url( ES_PLUGIN_URL ) . 'lite/admin/images/spinner-2x.gif' ),
);
return $title . $this->row_actions( $actions );
}
/**
* Associative array of columns
*
* @return array
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'subject' => __( 'Subject', 'email-subscribers' ),
'type' => __( 'Type', 'email-subscribers' ),
'status' => __( 'Status', 'email-subscribers' ),
'start_at' => __( 'Start Date', 'email-subscribers' ),
'finish_at' => __( 'End Date', 'email-subscribers' ),
'count' => __( 'Total contacts', 'email-subscribers' ),
'total_sent' => __( 'Total sent', 'email-subscribers' ),
'total_opened' => __( 'Total Opened', 'email-subscribers' ),
);
return $columns;
}
public function column_count( $item ) {
$campaign_hash = $item['hash'];
$total_emails_sent = $item['count'];
$total_emails_to_be_sent = $item['count'];
// if ( ! empty( $campaign_hash ) ) {
// $total_emails_sent = ES_DB_Sending_Queue::get_total_emails_sent_by_hash( $campaign_hash );
// }
// $content = $total_emails_sent . "/" . $total_emails_to_be_sent;
return number_format_i18n( $total_emails_to_be_sent );
}
public function prepare_send_now_url( $item ) {
$campaign_hash = $item['hash'];
$cron_url = '';
if ( ! empty( $campaign_hash ) ) {
$cron_url = ES()->cron->url( true, false, $campaign_hash );
}
$content = '';
if ( ! empty( $cron_url ) ) {
/* translators: %s: Cron url */
$content = sprintf(
'<a href="%s" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 inline text-yellow-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<title>%s</title>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg></a>',
$cron_url,
__( 'Send now', 'email-subscribers' )
);
}
return $content;
}
/**
* Columns to make sortable.
*
* @return array
*/
public function get_sortable_columns() {
$sortable_columns = array(
'subject' => array( 'subject', true ),
'status' => array( 'status', true ),
'start_at' => array( 'start_at', true ),
'finish_at' => array( 'finish_at', true ),
'count' => array( 'count', true ),
);
return $sortable_columns;
}
/**
* Returns an associative array containing the bulk action
*
* @return array
*/
public function get_bulk_actions() {
$actions = array(
'bulk_delete' => __( 'Delete', 'email-subscribers' ),
);
return $actions;
}
/**
* Handles data query and filter, sorting, and pagination.
*/
public function prepare_items() {
$this->_column_headers = $this->get_column_info();
/** Process bulk action */
$this->process_bulk_action();
// Search box
$search = ig_es_get_request_data( 's' );
$this->search_box( $search, 'reports-search-input' );
$per_page = $this->get_items_per_page( 'reports_per_page', 20 );
$current_page = $this->get_pagenum();
$total_items = $this->get_notifications( 0, 0, true );
$this->set_pagination_args(
array(
'total_items' => $total_items, // WE have to calculate the total number of items
'per_page' => $per_page, // WE have to determine how many items to show on a page
)
);
$this->items = $this->get_notifications( $per_page, $current_page, false );
}
public function get_notifications( $per_page = 5, $page_number = 1, $do_count_only = false ) {
global $wpdb, $wpbd;
$order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
$order = ig_es_get_request_data( 'order' );
$campaign_id = ig_es_get_request_data( 'campaign_id' );
$search = ig_es_get_request_data( 's' );
$filter_reports_by_campaign_status = ig_es_get_request_data( 'filter_reports_by_status' );
$filter_reports_by_campaign_type = ig_es_get_request_data( 'filter_reports_by_campaign_type' );
$filter_reports_by_month_year = ig_es_get_request_data( 'filter_reports_by_date' );
$ig_mailing_queue_table = IG_MAILING_QUEUE_TABLE;
if ( $do_count_only ) {
$sql = "SELECT count(*) as total FROM {$ig_mailing_queue_table}";
} else {
$sql = "SELECT * FROM {$ig_mailing_queue_table}";
}
$where_columns = array();
$where_args = array();
$add_where_clause = true;
if ( ! empty( $campaign_id ) && is_numeric( $campaign_id ) ) {
$where_columns[] = 'campaign_id = %d';
$where_args[] = $campaign_id;
}
if ( ! empty( $filter_reports_by_month_year ) ) {
if ( preg_match('/^[0-9]{6}$/', $filter_reports_by_month_year) ) {
$year_val = substr($filter_reports_by_month_year, 0, 4);
$month_val = substr($filter_reports_by_month_year, 4 );
$date_string = $year_val . '-' . $month_val;
$date = new DateTime($date_string);
$start_date = $date->format('Y-m-01 H:i:s') ;
$end_date = $date->format('Y-m-t H:i:s');
array_push( $where_columns, 'start_at >= %s', 'start_at <= %s' );
array_push($where_args, $start_date, $end_date);
}
}
$where_query = '';
if ( ! empty( $where_columns ) ) {
$where_query = implode( ' AND ', $where_columns );
$where_query = $wpbd->prepare( $where_query, $where_args );
}
if ( ! empty( $where_query ) ) {
$sql .= ' WHERE ' . $where_query;
$add_where_clause = false;
}
if ( ! empty( $filter_reports_by_campaign_status ) || ( '0' === $filter_reports_by_campaign_status ) ) {
if ( ! $add_where_clause ) {
$sql .= $wpdb->prepare( ' AND status = %s', $filter_reports_by_campaign_status );
} else {
$sql .= $wpdb->prepare( ' WHERE status = %s', $filter_reports_by_campaign_status );
$add_where_clause = false;
}
}
if ( ! empty( $filter_reports_by_campaign_type ) ) {
if ( ! $add_where_clause ) {
$sql .= $wpdb->prepare( ' AND meta LIKE %s', '%' . $wpdb->esc_like( $filter_reports_by_campaign_type ) . '%' );
} else {
$sql .= $wpdb->prepare( ' WHERE meta LIKE %s', '%' . $wpdb->esc_like( $filter_reports_by_campaign_type ) . '%' );
}
}
if ( ! $do_count_only ) {
// Prepare Order by clause
$order = ! empty( $order ) ? strtolower( $order ) : 'desc';
$expected_order_values = array( 'asc', 'desc' );
if ( ! in_array( $order, $expected_order_values ) ) {
$order = 'desc';
}
$default_order_by = esc_sql( 'created_at' );
$expected_order_by_values = array( 'subject', 'type', 'status', 'start_at', 'count', 'created_at' );
if ( ! in_array( $order_by, $expected_order_by_values ) ) {
$order_by_clause = " ORDER BY {$default_order_by} DESC";
} else {
$order_by = esc_sql( $order_by );
$order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
}
$sql .= $order_by_clause;
$sql .= " LIMIT $per_page";
$sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
$result = $wpbd->get_results( $sql, 'ARRAY_A' );
} else {
$result = $wpbd->get_var( $sql );
}
return $result;
}
public function process_bulk_action() {
$allowedtags = ig_es_allowed_html_tags_in_esc();
// Detect when a bulk action is being triggered...
if ( 'view' === $this->current_action() ) {
// In our file that handles the request, verify the nonce.
$nonce = ig_es_get_request_data( '_wpnonce' );
if ( ! wp_verify_nonce( $nonce, 'es_notification' ) ) {
$message = __( 'You do not have permission to view notification', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
}
} elseif ( 'delete' === $this->current_action() ) {
// In our file that handles the request, verify the nonce.
$nonce = ig_es_get_request_data( '_wpnonce' );
if ( ! wp_verify_nonce( $nonce, 'es_notification' ) ) {
$message = __( 'You do not have permission to delete notification', 'email-subscribers' );
ES_Common::show_message( $message, 'error' );
} else {
$notification_ids = absint( ig_es_get_request_data( 'list' ) );
ES_DB_Mailing_Queue::delete_notifications( array( $notification_ids ) );
ES_DB_Sending_Queue::delete_by_mailing_queue_id( array( $notification_ids ) );
$message = __( 'Report deleted successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
}
}
$action = ig_es_get_request_data( 'action' );
$action2 = ig_es_get_request_data( 'action2' );
// If the delete bulk action is triggered
if ( ( 'bulk_delete' === $action ) || ( 'bulk_delete' === $action2 ) ) {
$notification_ids = ig_es_get_request_data( 'bulk_delete' );
if ( count( $notification_ids ) > 0 ) {
ES_DB_Mailing_Queue::delete_notifications( $notification_ids );
ES_DB_Sending_Queue::delete_by_mailing_queue_id( $notification_ids );
$message = __( 'Reports deleted successfully!', 'email-subscribers' );
ES_Common::show_message( $message, 'success' );
}
}
}
/*
* Display the preview of the email content
*/
public function display_preview_email() {
?>
<div class="hidden" id="report_preview_template">
<div class="fixed top-0 left-0 z-50 flex items-center justify-center w-full h-full" style="background-color: rgba(0,0,0,.5);">
<div style="height:485px" class="absolute h-auto p-4 ml-16 mr-4 text-left bg-white rounded shadow-xl z-80 md:max-w-5xl md:p-6 lg:p-8 ">
<h3 class="text-2xl text-center"><?php echo esc_html__( 'Template Preview', 'email-subscribers' ); ?></h3>
<p class="m-4 text-center"><?php echo esc_html__( 'There could be a slight variation on how your customer will view the email content.', 'email-subscribers' ); ?></p>
<div class="m-4 list-decimal report_preview_container">
</div>
<div class="flex justify-center mt-8">
<button id="es_close_preview" class="px-4 py-2 text-sm font-medium tracking-wide text-gray-700 border rounded select-none no-outline focus:outline-none focus:shadow-outline-red hover:border-red-400 active:shadow-lg "><?php echo esc_html__( 'Close', 'email-subscribers' ); ?></button>
</div>
</div>
</div>
</div>
<?php
}
/**
* Prepare search box
*
* @param string $text
* @param string $input_id
*
* @since 4.6.5
*/
public function search_box( $text = '', $input_id = '' ) {
?>
<p class="search-box">
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_attr( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
<?php submit_button( __( 'Search Reports', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
</p>
<p class="search-box search-group-box box-ma10">
<?php
$filter_by_status = ig_es_get_request_data( 'filter_reports_by_status' );
?>
<select name="filter_reports_by_status" id="ig_es_filter_report_by_status">
<?php
$allowedtags = ig_es_allowed_html_tags_in_esc();
add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
$statuses = array(
'Sent' => __( 'Completed', 'email-subscribers' ),
'In Queue' => __( 'In Queue', 'email-subscribers' ),
'Sending' => __( 'Sending', 'email-subscribers' ),
);
$campaign_report_status = ES_Common::prepare_campaign_report_statuses_dropdown_options( $statuses, $filter_by_status, __( 'All Status', 'email-subscribers' ) );
echo wp_kses( $campaign_report_status, $allowedtags );
?>
</select>
</p>
<p class="search-box search-group-box box-ma10">
<?php $filter_by_campaign_type = ig_es_get_request_data( 'filter_reports_by_campaign_type' ); ?>
<select name="filter_reports_by_campaign_type" id="ig_es_filter_reports_by_campaign_type">
<?php
$campaign_report_type = ES_Common::prepare_campaign_type_dropdown_options( $filter_by_campaign_type, __( 'All Type', 'email-subscribers' ) );
echo wp_kses( $campaign_report_type, $allowedtags );
?>
</select>
</p>
<p class="search-box search-group-box box-ma10">
<?php $filter_by_date = ig_es_get_request_data( 'filter_reports_by_date' ); ?>
<select name = "filter_reports_by_date" id="ig_es_filter_report_by_date">
<?php
$filter_by_monthyear = ES_COMMON::prepare_datefilter_dropdown_options( $filter_by_date , __('All Dates', 'email-subscribers'));
echo wp_kses( $filter_by_monthyear, $allowedtags);
?>
</select>
</p>
<?php
}
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}

View File

@@ -0,0 +1,88 @@
<?php
if ( ! class_exists( 'ES_Router' ) ) {
/**
* Class to handle single campaign options
*
* @class ES_Router
*/
class ES_Router {
// class instance
public static $instance;
// class constructor
public function __construct() {
$this->init();
}
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
public function init() {
$this->register_hooks();
}
public function register_hooks() {
add_action( 'wp_ajax_icegram-express', array( $this, 'handle_ajax_request' ) );
/* Dev code */
add_action( 'wp_ajax_nopriv_icegram-express', array( $this, 'handle_ajax_request' ) );
}
/**
* Method to draft a campaign
*
* @return $response Broadcast response.
*
* @since 4.4.7
*/
public function handle_ajax_request() {
$response = array();
if ( ! defined( 'IG_ES_DEV_MODE' ) || ! IG_ES_DEV_MODE ) {
check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' );
}
$request = $_REQUEST;
$handler = ig_es_get_data( $request, 'handler' );
$handler_class = 'ES_' . ucfirst( $handler ) . '_Controller';
if ( empty( $handler ) || ! class_exists( $handler_class ) ) {
$response = array(
'message' => __( 'No request handler found.', 'email-subscribers' ),
);
wp_send_json_error( $response );
}
$method = ig_es_get_data( $request, 'method' );
if ( ! method_exists( $handler_class, $method ) || ! is_callable( array( $handler_class, $method ) ) ) {
$response = array(
'message' => __( 'No request method found.', 'email-subscribers' ),
);
wp_send_json_error( $response );
}
$data = ig_es_get_request_data( 'data', array(), false );
$result = call_user_func( array( $handler_class, $method ), $data );
if ( $result ) {
$response['success'] = true;
$response['data'] = $result;
} else {
$response['success'] = false;
}
wp_send_json( $response );
}
}
}
ES_Router::get_instance();

View File

@@ -0,0 +1,74 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Subscription_Throttling {
public static function throttle() {
global $wpdb;
if ( ! ( is_user_logged_in() && is_super_admin() ) ) {
$subscriber_ip = ig_es_get_ip();
$whitelist_ips = array();
$whitelist_ips = apply_filters( 'ig_es_whitelist_ips', $whitelist_ips );
$blacklist_ips = array();
$blacklist_ips = apply_filters( 'ig_es_blacklist_ips', $blacklist_ips );
if ( ! ( empty( $subscriber_ip ) || ( is_array( $whitelist_ips ) && count( $whitelist_ips ) > 0 && in_array( $subscriber_ip, $whitelist_ips ) ) ) ) {
if ( is_array( $blacklist_ips ) && count( $blacklist_ips ) > 0 && in_array( $subscriber_ip, $blacklist_ips ) ) {
return MINUTE_IN_SECONDS * 10;
}
$subscribers = $wpdb->get_var(
$wpdb->prepare(
"SELECT count(*) as count from {$wpdb->prefix}ig_contacts_ips WHERE ip = %s AND ( `created_on` >= NOW() - INTERVAL %s SECOND )",
$subscriber_ip,
DAY_IN_SECONDS
)
);
if ( $subscribers > 0 ) {
$timeout = MINUTE_IN_SECONDS * pow( 2, $subscribers - 1 );
$subscribers = $wpdb->get_var(
$wpdb->prepare(
"SELECT count(*) as count from {$wpdb->prefix}ig_contacts_ips WHERE ip = %s AND ( `created_on` >= NOW() - INTERVAL %s SECOND ) LIMIT 1",
$subscriber_ip,
$timeout
)
);
if ( $subscribers > 0 ) {
return $timeout;
}
}
// Add IP Address.
$wpdb->query(
$wpdb->prepare(
"INSERT INTO {$wpdb->prefix}ig_contacts_ips (`ip`) VALUES ( %s )",
$subscriber_ip
)
);
// Delete older entries
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->prefix}ig_contacts_ips WHERE (`created_on` < NOW() - INTERVAL %s SECOND )",
DAY_IN_SECONDS
)
);
}
}
return false;
}
}

View File

@@ -0,0 +1,310 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Templates_Table {
public static $instance;
public function __construct() {
add_action( 'add_meta_boxes', array( $this, 'es_template_meta_box_add' ) );
add_action( 'save_post', array( $this, 'es_template_meta_save' ), 10, 2 );
add_action( 'post_submitbox_misc_actions', array( $this, 'preview_button' ) );
add_filter( 'manage_edit-es_template_columns', array( $this, 'add_new_columns' ), 10, 1 );
add_action( 'manage_posts_custom_column', array( $this, 'custom_columns' ) );
add_action( 'admin_footer', array( $this, 'add_custom_button' ) );
add_action( 'edit_form_after_title', array( $this, 'add_template_type' ) );
// duplicate template
add_filter( 'post_row_actions', array( &$this, 'add_template_action' ), 10, 2 );
add_action( 'admin_init', array( &$this, 'duplicate_template' ), 10, 1 );
add_action( 'admin_footer', array( $this, 'es_template_preview_callback' ), 10 );
add_action( 'parse_query', array( $this, 'exclude_dnd_templates' ) );
}
public function add_template_type() {
global $post;
if ( ! ( is_object( $post ) && 'es_template' === $post->post_type ) ) {
return;
}
$values = get_post_custom( $post->ID );
$selected = isset( $values['es_template_type'] ) ? esc_attr( $values['es_template_type'][0] ) : '';
$template_type = ES_Common::get_campaign_types( array( 'sequence' ) );
?>
<p class="mt-3">
<label for="es_template_type"><span class="font-semibold text-sm text-gray-700"><?php esc_html_e( 'Select template type', 'email-subscribers' ); ?></span></label><br/>
<select style="margin: 0.20rem 0;" name="es_template_type" id="es_template_type">
<?php
if ( ! empty( $template_type ) ) {
foreach ( $template_type as $key => $value ) {
echo '<option value=' . esc_attr( $key ) . ' ' . selected( $selected, $key, false ) . '>' . esc_html( $value ) . '</option>';
}
}
?>
</select>
</p>
<?php
}
public function es_template_meta_box_add() {
add_meta_box( 'es_template_meta_box', __( 'Available Keywords', 'email-subscribers' ), array( $this, 'es_template_type_meta_box' ), 'es_template', 'normal', 'high' );
}
public function es_template_type_meta_box( $post ) {
if ( ! ( is_object( $post ) && 'es_template' === $post->post_type ) ) {
return;
}
?>
<!-- Start-IG-Code -->
<p id="post_notification">
<a href="https://www.icegram.com/documentation/what-keywords-can-be-used-while-designing-the-campaign/?utm_source=es&amp;utm_medium=in_app&amp;utm_campaign=view_docs_help_page" target="_blank"><?php esc_html_e( 'Available Keywords', 'email-subscribers' ); ?></a> <?php esc_html_e( 'for Post Notification: ', 'email-subsribers' ); ?> {{subscriber.first_name | fallback:'there'}},
{{subscriber.last_name}}, {{subscriber.name}}, {{subscriber.email}},
{{post.date}}, {{post.title}}, {{post.image}}, {{post.excerpt}}, {{post.description}},
{{post.author}}, {{post.author_avatar}}, {{post.author_avatar_url}}, {{post.link}}, {{post.link_with_title}}, {{post.link_only}}, {{post.full}} </p>
<!-- End-IG-Code -->
<p id="newsletter">
<a href="https://www.icegram.com/documentation/what-keywords-can-be-used-while-designing-the-campaign/?utm_source=es&amp;utm_medium=in_app&amp;utm_campaign=view_docs_help_page" target="_blank"><?php esc_html_e( 'Available Keywords', 'email-subscribers' ); ?></a> <?php esc_html_e( 'for Broadcast:', 'email-subscribers' ); ?> {{subscriber.first_name | fallback:'there'}}, {{subscriber.last_name}}, {{subscriber.name}},
{{subscriber.email}} </p>
<!-- Start-IG-Code -->
<div id="post_digest">
<span style="font-size: 0.8em; margin-left: 0.3em; padding: 2px; background: #e66060; color: #fff; border-radius: 2px; ">Pro</span>&nbsp;
<a href="https://www.icegram.com/send-post-digest-using-email-subscribers-plugin/?utm_source=es&amp;utm_medium=in_app&amp;utm_campaign=view_post_digest_post" target="_blank"><?php esc_html_e( 'Available Keywords', 'email-subscribers' ); ?></a> <?php esc_html_e( 'for Post Digest:', 'email-subscribers' ); ?>
{{subscriber.first_name | fallback:'there'}}, {{subscriber.last_name}}, {{subscriber.name}}<div class="post_digest_block"> {{post.digest}} <br/><?php esc_html_e( 'Any keywords related Post Notification', 'email-subscribers' ); ?> <br/>{{/post.digest}} </div>
</div>
<!-- End-IG-Code -->
<?php
}
public function es_template_meta_save( $post_id, $post ) {
if ( empty( $post_id ) || empty( $post ) ) {
return;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( is_int( wp_is_post_revision( $post ) ) ) {
return;
}
if ( is_int( wp_is_post_autosave( $post ) ) ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( 'es_template' != $post->post_type ) {
return;
}
if ( ! empty( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-post_' . $post_id ) ) {
$es_template_type = ig_es_get_data( $_POST, 'es_template_type', '', true );
if ( ! empty( $es_template_type ) ) {
update_post_meta( $post_id, 'es_template_type', $es_template_type );
}
}
}
public function preview_button( $post ) {
if ( is_object( $post ) && 'es_template' === $post->post_type ) {
$post_id = $post->ID;
?>
<div class="misc-pub-section">
<div id="" class="es_preview_button" style="display: block;">
<a style="padding-top: 3px; margin-bottom: 0.2rem;" href="#" data-post-id="<?php echo esc_attr( $post_id ); ?>" class="button button-primary es_template_preview"><?php esc_html_e( 'Preview template', 'email-subscribers' ); ?></a><img class="es-template-preview-loader inline-flex align-middle pl-2 h-5 w-7" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/spinner-2x.gif" style="display:none;"/>
<div class="clear"></div>
</div>
</div>
<?php
}
}
public function add_custom_button() {
$screen = get_current_screen();
if ( 'es_template' == $screen->post_type ) {
?>
<script type="text/javascript">
jQuery('<a style="top:-3px;position: relative" href="admin.php?page=es_campaigns" class="ig-es-title-button ml-2 mb-3">Campaigns</a>').insertBefore(".wp-header-end");
</script>
<?php
}
}
public function es_template_preview_callback() {
?>
<div class="hidden" id="es_preview_template">
<div class="fixed top-0 left-0 z-50 flex items-center justify-center w-full h-full" style="background-color: rgba(0,0,0,.5);">
<div style="height:485px" class="absolute h-auto p-4 ml-16 mr-4 text-left bg-white rounded shadow-xl z-80 md:max-w-5xl md:p-6 lg:p-8 ">
<h3 class="text-2xl text-center"><?php echo esc_html__( 'Template Preview', 'email-subscribers' ); ?></h3>
<p class="m-4 text-center"><?php echo esc_html__( 'There could be a slight variation on how your customer will view the email content.', 'email-subscribers' ); ?></p>
<div class="m-4 list-decimal template_preview_container">
</div>
<div class="flex justify-center mt-8">
<button id="es_close_template_preview" class="px-4 py-2 text-sm font-medium tracking-wide text-gray-700 border rounded select-none no-outline focus:outline-none focus:shadow-outline-red hover:border-red-400 active:shadow-lg "><?php echo esc_html__( 'Close', 'email-subscribers' ); ?></button>
</div>
</div>
</div>
</div>
<?php
}
public function add_new_columns( $existing_columns ) {
$date = $existing_columns['date'];
unset( $existing_columns['date'] );
$existing_columns['es_template_type'] = __( 'Template type', 'email-subscribers' );
$existing_columns['es_template_thumbnail'] = __( 'Thumbnail', 'email-subscribers' );
$existing_columns['date'] = $date;
return $existing_columns;
}
public function custom_columns( $column ) {
global $post;
$es_template_thumbnail = get_the_post_thumbnail( $post->ID, array( '200', '200' ) );
$default_template_thumbnail = '<img src="' . ES_PLUGIN_URL . 'lite/admin/images/envelope.png" />';
$es_template_thumbnail = apply_filters( 'ig_es_template_thumbnail', $es_template_thumbnail );
$es_template_thumbnail = ( ! empty( $es_template_thumbnail ) ) ? $es_template_thumbnail : $default_template_thumbnail;
switch ( $column ) {
case 'es_template_type':
$type = get_post_meta( $post->ID, 'es_template_type', true );
$type = sanitize_text_field( strtolower( $type ) );
$type = ( 'newsletter' === $type ) ? __( 'Broadcast', 'email-subscribers' ) : $type;
$type = ucwords( str_replace( '_', ' ', $type ) );
echo esc_html( $type );
break;
case 'es_template_thumbnail':
echo wp_kses_post( $es_template_thumbnail );
break;
default:
break;
}
return $column;
}
public function add_template_action( $actions, $post ) {
if ( 'es_template' !== $post->post_type ) {
return $actions;
}
$nonce = wp_create_nonce( 'ig_es_duplicate_template_nonce' );
$actions['duplicate_template'] = '<a class="es-duplicate-template" href="post.php?template_id=' . $post->ID . '&action=duplicate-template&_wpnonce=' . $nonce . '" >' . __( 'Duplicate', 'email-subscribers' ) . '</a>';
return $actions;
}
public function duplicate_template() {
$action = ig_es_get_request_data( 'action' );
$template_id = ig_es_get_request_data( 'template_id' );
if ( ! empty( $template_id ) && 'duplicate-template' === $action ) {
check_admin_referer( 'ig_es_duplicate_template_nonce' );
// duplicate tempalte
$this->duplicate_in_db( $template_id );
// $location = admin_url( 'post.php?post='.$duplicate_template_id.'&action=edit');
$location = admin_url( 'edit.php?post_type=es_template' );
wp_safe_redirect( $location );
exit;
}
}
public function duplicate_in_db( $original_id ) {
// Get access to the database
global $wpdb;
// Get the post as an array
$duplicate = get_post( $original_id, 'ARRAY_A' );
// Modify some of the elements
$duplicate['post_title'] = $duplicate['post_title'] . ' ' . __( 'Copy', 'email-subscribers' );
$duplicate['post_status'] = 'draft';
// Set the post date
$timestamp = current_time( 'timestamp', 0 );
$duplicate['post_date'] = gmdate( 'Y-m-d H:i:s', $timestamp );
// Remove some of the keys
unset( $duplicate['ID'] );
unset( $duplicate['guid'] );
unset( $duplicate['comment_count'] );
$current_user_id = get_current_user_id();
if ( ! empty( $current_user_id ) ) {
// Set post author to current logged in author.
$duplicate['post_author'] = $current_user_id;
}
// Insert the post into the database
$duplicate_id = wp_insert_post( $duplicate );
// Duplicate all taxonomies/terms
$taxonomies = get_object_taxonomies( $duplicate['post_type'] );
foreach ( $taxonomies as $taxonomy ) {
$terms = wp_get_post_terms( $original_id, $taxonomy, array( 'fields' => 'names' ) );
wp_set_object_terms( $duplicate_id, $terms, $taxonomy );
}
// Duplicate all custom fields
$custom_fields = get_post_custom( $original_id );
foreach ( $custom_fields as $key => $value ) {
add_post_meta( $duplicate_id, $key, maybe_unserialize( $value[0] ) );
}
return $duplicate_id;
}
/**
* Exclude DND Templates from template list
*
* @since 4.5.3
*/
public static function exclude_dnd_templates( $wp_query ) {
global $pagenow;
if ( 'edit.php' !== $pagenow || empty( $wp_query->query_vars['post_type'] ) ||'es_template' !== $wp_query->query_vars['post_type'] ) {
return;
}
$wp_query->query_vars['meta_query'] = array(
'relation' => 'OR',
array(
'key' => 'es_editor_type',
'value' => IG_ES_CLASSIC_EDITOR,
'compare' => '=',
),
array(
'key' => 'es_editor_type',
'compare' => 'NOT EXISTS', // if key doesn't exists, then template is created using Classic editor
),
);
}
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}

View File

@@ -0,0 +1,107 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The admin-specific functionality of the plugin.
*
* Admin Settings
*
* @package Email_Subscribers
* @subpackage Email_Subscribers/admin
*/
class ES_Tools {
// class instance
public static $instance;
public function __construct() {
// Allow only to send test email to user who have Settings & Campaigns permission
$accessible_sub_menus = ES_Common::ig_es_get_accessible_sub_menus();
if ( defined( 'DOING_AJAX' ) && ( in_array( 'settings', $accessible_sub_menus ) || in_array( 'campaigns', $accessible_sub_menus ) ) ) {
add_action( 'wp_ajax_es_send_test_email', array( $this, 'send_test_email' ) );
}
}
/**
* Send Test Email
*
* @since 4.0.0
* @since 4.3.2 Call ES()->mailer->send_test_email() method to send test email
*/
public function send_test_email() {
check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' );
$response = array();
$email = sanitize_email( ig_es_get_request_data( 'es_test_email' ) );
$campaign_id = ig_es_get_data( $_POST, 'campaign_id', 0, true );
$campaign_type = ig_es_get_data( $_POST, 'campaign_type', '', true );
$template_id = ig_es_get_data( $_POST, 'template_id', 0, true );
$subject = ig_es_get_data( $_POST, 'subject', '', true );
$content = ig_es_get_request_data( 'content', '', false );
$attachments = ig_es_get_data( $_POST, 'attachments', array(), true );
$preheader = ig_es_get_data( $_POST, 'preheader', array(), true );
if ( ! empty( $email ) ) {
$merge_tags = array( 'attachments' => $attachments );
if ( ! empty( $campaign_id ) ) {
$campaign_data = array(
'id' => $campaign_id,
'type' => $campaign_type,
'base_template_id' => $template_id,
'subject' => $subject,
'body' => $content,
);
if ( IG_CAMPAIGN_TYPE_POST_NOTIFICATION === $campaign_type ) {
$campaign_data = ES_Campaign_Admin::replace_post_notification_merge_tags_with_sample_post( $campaign_data );
} elseif ( IG_CAMPAIGN_TYPE_POST_DIGEST === $campaign_type ) {
$campaign_data = ES_Campaign_Admin::replace_post_digest_merge_tags_with_sample_posts( $campaign_data );
}
$merge_tags['campaign_id'] = $campaign_id;
$merge_tags['preheader'] = $preheader;
$subject = $campaign_data['subject'];
$content = $campaign_data['body'];
}
$content = ES_Common::es_process_template_body( $content, $template_id, $campaign_id );
$response = ES()->mailer->send_test_email( $email, $subject, $content, $merge_tags );
if ( $response && 'SUCCESS' === $response['status'] ) {
$response['message'] = __( 'Email has been sent. Please check your inbox', 'email-subscribers' );
} else {
$can_promote_ess = ES_Service_Email_Sending::can_promote_ess();
if ( $can_promote_ess ) {
$promotion_message_html = ES_Service_Email_Sending::get_ess_promotion_message_html();
if ( is_array( $response['message'] ) ) {
$response['message'][] = $promotion_message_html;
} else {
$response['message'] .= $promotion_message_html;
}
}
}
}
echo json_encode( $response );
exit;
}
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}

View File

@@ -0,0 +1,39 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_Tracking' ) ) {
/**
* Class ES_Tracking
*
* Track Activities like Subscribe, Open, Click, Unsubscribe
*
* @since 4.2.0
*/
class ES_Tracking {
/**
* ES_Actions constructor.
*
* @since 4.2.0
*/
public function __construct() {
add_action( 'init', array( $this, 'init' ), 1 );
}
/**
* Track user interaction
*
* @since 4.2.0
*/
public function init() {
}
}
}

View File

@@ -0,0 +1,94 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ES_Widget extends WP_Widget {
public function __construct() {
parent::__construct( 'email_subscriber_widget', __( 'Icegram Express Widget', 'email-subscribers' ), array( 'description' => __( 'Icegram Express', 'email-subscribers' ) ) );
}
public function widget( $args, $instance ) {
$title = apply_filters( 'widget_title', $instance['title'] );
echo wp_kses_post( $args['before_widget'] );
if ( ! empty( $title ) ) {
echo wp_kses_post( sprintf( '%s %s %s', $args['before_title'] . $title . $args['after_title'] ) );
}
$display_name = isset( $instance['display_name'] ) ? esc_attr( $instance['display_name'] ) : '';
$subscribers_group = isset( $instance['subscribers_group'] ) ? esc_attr( $instance['subscribers_group'] ) : '';
$desc = isset( $instance['short_desc'] ) ? esc_attr( $instance['short_desc'] ) : '';
$name = strtolower( $display_name ) != 'no' ? 'yes' : '';
$data['name_visible'] = $name;
$data['list_visible'] = 'no';
$data['lists'] = array();
$data['form_id'] = 0;
$data['list'] = $subscribers_group;
$data['desc'] = $desc;
ES_Shortcode::render_form( $data );
echo wp_kses_post( $args['after_widget'] );
}
public function form( $instance ) {
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
$short_desc = isset( $instance['short_desc'] ) ? esc_attr( $instance['short_desc'] ) : '';
$display_name = isset( $instance['display_name'] ) ? esc_attr( $instance['display_name'] ) : '';
$subscribers_group = isset( $instance['subscribers_group'] ) ? esc_attr( $instance['subscribers_group'] ) : '';
$display_names = array(
'yes' => __( 'Yes', 'email-subscribers' ),
'no' => __( 'No', 'email-subscribers' ),
);
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Widget Title:' ); ?></label>
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'short_desc' ) ); ?>"><?php esc_html_e( 'Short description' ); ?></label>
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'short_desc' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'short_desc' ) ); ?>" type="text" value="<?php echo esc_attr( $short_desc ); ?>">
</p>
<p>
<label for="widget-email-subscribers-2-es_name"><?php esc_html_e( 'Display Name Field' ); ?></label>
<select id="<?php echo esc_attr( $this->get_field_id( 'display_name' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'display_name' ) ); ?>" class="widefat" style="width:100%;">
<?php foreach ( $display_names as $name ) { ?>
<option <?php selected( $display_name, $name ); ?> value="<?php echo esc_attr( $name ); ?>"><?php echo esc_html( $name ); ?></option>
<?php } ?>
</select>
</p>
<p>
<label for="widget-email-subscribers-2-es_group"><?php esc_html_e( 'Subscriber List' ); ?></label>
<select id="<?php echo esc_attr( $this->get_field_id( 'subscribers_group' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'subscribers_group' ) ); ?>" class="widefat" style="width:100%;">
<?php
$lists_dropdown = ES_Common::prepare_list_dropdown_options( $subscribers_group );
$allowedtags = ig_es_allowed_html_tags_in_esc();
echo wp_kses( $lists_dropdown, $allowedtags );
?>
</select>
</p>
<?php
}
public function update( $new_instance, $old_instance ) {
$instance = array();
$instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
$instance['short_desc'] = ( ! empty( $new_instance['short_desc'] ) ) ? strip_tags( $new_instance['short_desc'] ) : '';
$instance['display_name'] = ( ! empty( $new_instance['display_name'] ) ) ? strip_tags( $new_instance['display_name'] ) : '';
$instance['subscribers_group'] = ( ! empty( $new_instance['subscribers_group'] ) ) ? strip_tags( $new_instance['subscribers_group'] ) : '';
return $instance;
}
}

View File

@@ -0,0 +1,265 @@
<?php
/**
* Helper class for background processing
*
* @since 4.6.3
* @version 1.0.0
*
* @package Email Subscribers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
/**
* IG_ES_Background_Process_Helper Class.
*/
class IG_ES_Background_Process_Helper {
/**
* Identifier
*
* @var mixed
*/
protected static $identifier;
/**
* Variable to hold instance of IG_ES_Background_Process_Helper
*
* @var $instance
*/
private static $instance = null;
/**
* Contructor
*
* @since 4.6.3
*/
private function __construct() {
self::$identifier = 'ig_es_background_process';
}
/**
* Get single instance of IG_ES_Background_Process_Helper
*
* @return IG_ES_Background_Process_Helper Singleton object of IG_ES_Background_Process_Helper
*
* @since 4.6.3
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Memory exceeded
*
* Ensures the batch process never exceeds 90%
* of the maximum WordPress memory.
*
* @return bool
*
* @since 4.6.3
*/
public static function memory_exceeded() {
$memory_limit = self::get_memory_limit() * 0.9; // 90% of max memory
$current_memory = memory_get_usage( true );
if ( $current_memory >= $memory_limit ) {
return true;
}
return false;
}
/**
* Get memory limit.
*
* @return int
*
* @since 4.6.3
*/
public static function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
// Sensible default.
$memory_limit = '128M';
}
if ( ! $memory_limit || -1 === intval( $memory_limit ) ) {
// Unlimited, set to 32GB.
$memory_limit = '32G';
}
return wp_convert_hr_to_bytes( $memory_limit );
}
/**
* Time exceeded.
*
* Ensures the batch never exceeds a sensible time limit.
* A timeout limit of 30s is common on shared hosting.
*
* @param string $start_time start timestamp.
* @param float $fraction Time fraction.
*
* @return bool
*
* @since 4.6.3
*
* @since Added $fraction parameter
*/
public static function time_exceeded( $start_time = 0, $fraction = 0.6 ) {
$finish = $start_time + ( self::get_time_limit() * $fraction );
$return = false;
if ( time() >= $finish ) {
$return = true;
}
return apply_filters( self::$identifier . '_time_exceeded', $return );
}
/**
* Method to get Server time limit
*
* @return int $time_limit Server time limit.
*
* @since 4.6.3
*/
public static function get_time_limit() {
if ( function_exists( 'ini_get' ) ) {
$time_limit = ini_get( 'max_execution_time' );
} else {
// Sensible default.
$time_limit = apply_filters( self::$identifier . '_default_time_limit', 20 );
}
$time_limit = (int) $time_limit;
return $time_limit;
}
/**
* Method to add new action scheduler task. Task added by this function are called by Action Scheduler library when execution time comes.
*
* @param string $action Action name.
* @param array $action_args Action arguements.
* @param bool $process_asynchronously Should process action asynchronously.
* @param bool $should_wait Should wait before making asynchronous request to process the action.
*
* @return int|bool $action_id Action ID on success or false on failure.
*
* @since 4.6.3
*/
public static function add_action_scheduler_task( $action = '', $action_args = array(), $process_asynchronously = true, $should_wait = false, $time = 0 ) {
if ( empty( $action ) ) {
return false;
}
if ( function_exists( 'as_schedule_single_action' ) ) {
$time = ! empty( $time ) ? $time : time();
$action_id = as_schedule_single_action( $time, $action, array( $action_args ), 'email-subscribers' );
if ( ! empty( $action_id ) ) {
if ( $process_asynchronously ) {
$request_args = array(
'action' => 'ig_es_run_action_scheduler_task',
'action_id' => $action_id,
);
self::send_async_ajax_request( $request_args, $should_wait );
}
return $action_id;
}
}
return false;
}
/**
* Method to trigger immediate processing of action scheduler task.
*
* @since 4.6.3
*/
public static function run_action_scheduler_task() {
$action_id = ig_es_get_request_data( 'action_id' );
if ( ! empty( $action_id ) ) {
if ( class_exists( 'ActionScheduler_QueueRunner' ) ) {
$queue_runner = ActionScheduler_QueueRunner::instance();
$queue_runner->process_action( $action_id, 'email-subscribers' );
}
}
}
/**
* Method to get required waiting time in seconds before making async request.
* Chaining async requests can crash MySQL. A brief waiting period in PHP helps in preventing that.
*
* @return int Waiting time in seconds.
*
* @since 4.6.3
*/
public static function get_wait_seconds() {
return apply_filters( 'ig_es_async_request_wait_seconds', 3 );
}
/**
* Method to send asynchronous background request to admin-ajax.
*
* @param array $request_args Async request's arguments.
* @param bool $should_wait Should wait before making this async request.
*
* @return array $response Async request's response.
*
* @since 4.6.3
*/
public static function send_async_ajax_request( $request_args = array(), $should_wait = false ) {
$response = array();
if ( empty( $request_args ) ) {
return $response;
}
// Should wait before making async request.
if ( $should_wait ) {
$wait_seconds = self::get_wait_seconds();
if ( $wait_seconds ) {
// Sleep to prevent crashing of MYSQL due to chaining of async request.
sleep( $wait_seconds );
}
}
$admin_ajax_url = admin_url( 'admin-ajax.php' );
$admin_ajax_url = add_query_arg( $request_args, $admin_ajax_url );
$args = array(
'timeout' => 0.01,
'blocking' => false,
'cookies' => $_COOKIE,
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
);
$args = apply_filters( 'ig_es_async_request_args', $args );
// Make a asynchronous request.
$response = wp_remote_get( esc_url_raw( $admin_ajax_url ), $args );
return $response;
}
}
}

View File

@@ -0,0 +1,707 @@
<?php
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class IG_ES_Subscribers_Query {
private $last_result;
private $last_error;
private $last_query;
private $args = array();
private $defaults = array(
'select' => null,
'join' => null,
'status' => null,
'status__not_in' => null,
'where' => null,
'having' => null,
'orderby' => null,
'order' => null,
'groupby' => null,
'limit' => null,
'offset' => null,
'return_ids' => false,
'return_count' => false,
'return_sql' => false,
'operator' => null,
'conditions' => null,
'include' => null,
'exclude' => null,
'wp_include' => null,
'wp_exclude' => null,
'fields' => null,
'meta' => null,
'lists' => false,
'lists__in' => null,
'lists__not_in' => null,
'unsubscribe' => null,
'unsubscribe__not_in' => null,
'queue' => false,
'queue__not_in' => false,
's' => null,
'search_fields' => false,
'strict' => false,
'sentence' => false,
'calc_found_rows' => false,
'signup_after' => null,
'signup_before' => null,
'confirm_after' => null,
'confirm_before' => null,
'sent' => null,
'sent__not_in' => null,
'sent_before' => null,
'sent_after' => null,
'open' => null,
'open__not_in' => null,
'open_before' => null,
'open_after' => null,
'click' => null,
'click__not_in' => null,
'click_before' => null,
'click_after' => null,
'click_link' => null,
'click_link__not_in' => null,
'sub_query_limit' => false,
);
private $fields = array(
'id',
'email',
'wp_user_id',
'country_code',
);
private $action_fields = array(
'_sent',
'_sent__not_in',
'_sent_before',
'_sent_after',
'_open',
'_open__not_in',
'_open_before',
'_open_after',
'_click',
'_click__not_in',
'_click_before',
'_click_after',
'_click_link',
'_click_link__not_in',
'_lists__in',
'_lists__not_in',
'_subscribed_before',
);
private $custom_fields = array();
private static $_instance = null;
public function __construct( $args = null, $campaign_id = null ) {
if ( ! is_null( $args ) ) {
return $this->run( $args, $campaign_id );
}
}
public function __destruct() {}
public static function get_instance( $args = null, $campaign_id = null ) {
if ( ! isset( self::$_instance ) ) {
self::$_instance = new self( $args, $campaign_id );
}
return self::$_instance;
}
public function run( $args = array(), $campaign_id = null ) {
global $wpbd;
$this->args = wp_parse_args( $args, $this->defaults );
$joins = array();
$wheres = array();
if ( $this->args['return_ids'] ) {
$this->args['select'] = array( 'subscribers.id' );
} elseif ( $this->args['return_count'] ) {
$this->args['select'] = array( 'COUNT(DISTINCT subscribers.id)' );
$this->args['fields'] = null;
$this->args['meta'] = null;
} elseif ( is_null( $this->args['select'] ) ) {
$this->args['select'] = array();
}
if ( !empty( $this->args['status'] ) && ! is_null( $this->args['status'] ) && !is_array( $this->args['status'] ) ) {
$this->args['status'] = explode( ',', $this->args['status'] );
}
if ( false !== $this->args['status__not_in'] && ! is_null( $this->args['status__not_in'] ) && ! is_array( $this->args['status__not_in'] ) ) {
$this->args['status__not_in'] = explode( ',', $this->args['status__not_in'] );
}
if ( ! empty( $this->args['lists'] ) && is_string( $this->args['lists'] ) ) {
$this->args['lists'] = explode( ',', $this->args['lists'] );
}
if ( $this->args['sent__not_in'] ) {
$this->add_condition( '_sent__not_in', '=', $this->id_parse( $this->args['sent__not_in'] ) );
}
$this->args = apply_filters( 'ig_es_subscriber_query_args', $this->args );
if ( ! empty( $this->args['queue__not_in'] ) ) {
$join = "LEFT JOIN {$wpbd->prefix}ig_queue AS queue ON subscribers.id = queue.contact_id";
if ( ! empty( $this->args['queue__not_in'] ) ) {
$join .= ' AND queue.campaign_id IN (' . implode( ',', array_filter( $this->args['queue__not_in'], 'is_numeric' ) ) . ')';
}
$joins[] = $join;
}
if ( $this->args['conditions'] ) {
$cond = array();
foreach ( $this->args['conditions'] as $i => $and_conditions ) {
if ( ! empty( $and_conditions ) ) {
foreach ( $and_conditions as $j => $condition ) {
$field = isset( $condition['field'] ) ? $condition['field'] : ( isset( $condition[0] ) ? $condition[0] : null );
$operator = isset( $condition['operator'] ) ? $condition['operator'] : ( isset( $condition[1] ) ? $condition[1] : null );
$value = isset( $condition['value'] ) ? $condition['value'] : ( isset( $condition[2] ) ? $condition[2] : null );
// something is not set => skip
if ( is_null( $field ) || is_null( $operator ) ) {
unset( $this->args['conditions'][ $i ][ $j ] );
continue;
}
// requires campaign to be sent
if ( in_array( $field, array( '_open__not_in', '_click__not_in' ) ) ) {
$this->add_condition( '_sent', '=', $value );
}
}
}
}
}
if ( ! empty( $this->args['conditions'] ) ) {
foreach ( $this->args['conditions'] as $i => $and_conditions ) {
$sub_cond = array();
if ( ! empty( $and_conditions ) ) {
foreach ( $and_conditions as $j => $condition ) {
$field = isset( $condition['field'] ) ? $condition['field'] : ( isset( $condition[0] ) ? $condition[0] : null );
$operator = isset( $condition['operator'] ) ? $condition['operator'] : ( isset( $condition[1] ) ? $condition[1] : null );
$value = isset( $condition['value'] ) ? $condition['value'] : ( isset( $condition[2] ) ? $condition[2] : null );
if ( ! in_array( $field, $this->action_fields, true ) ) {
$sub_cond[] = $this->get_condition( $field, $operator, $value );
} else {
if ( '_sent_before' !== $field ) {
$value = $this->remove_empty_values( $value );
}
$alias = 'actions' . $field . '_' . $i . '_' . $j;
if ( '_lists__in' === $field ) {
if ( $value ) {
$sub_cond[] = "lists_subscribers.contact_id IN ( SELECT contact_id FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id IN (" . implode( ',', array_filter( $value, 'is_numeric' ) ) . ") AND status IN( 'subscribed', 'confirmed' ) )";
}
} elseif ( '_lists__not_in' === $field ) {
if ( $value ) {
$sub_cond[] = "lists_subscribers.contact_id NOT IN ( SELECT contact_id FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id IN (" . implode( ',', array_filter( $value, 'is_numeric' ) ) . ') )';
} else {
$sub_cond[] = "lists_subscribers.contact_id NOT IN ( SELECT contact_id FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id <> 0 )";
}
} elseif ( 0 === strpos( $field, '_sent' ) ) {
$join = "LEFT JOIN {$wpbd->prefix}ig_actions AS $alias ON $alias.type = " . IG_MESSAGE_SENT . " AND subscribers.id = $alias.contact_id";
if ( ( '_sent' === $field || '_sent__not_in' === $field ) ) {
if ( $value ) {
$join .= " AND $alias.campaign_id IN (" . implode( ',', array_filter( $value, 'is_numeric' ) ) . ')';
} else {
$join .= " AND $alias.campaign_id IS NOT NULL AND $alias.campaign_id <> 0";
}
}
if ( '_sent' === $field ) {
$sub_cond[] = "$alias.contact_id IS NOT NULL";
} elseif ( '_sent__not_in' === $field ) {
$sub_cond[] = "$alias.contact_id IS NULL";
} elseif ( '_sent_before' === $field ) {
$sub_cond[] = "$alias.created_at <= " . $this->get_timestamp( $value );
} elseif ( '_sent_after' === $field ) {
$sub_cond[] = "$alias.created_at >= " . $this->get_timestamp( $value );
}
$joins[] = $join;
} elseif ( 0 === strpos( $field, '_open' ) ) {
$join = "LEFT JOIN {$wpbd->prefix}ig_actions AS $alias ON $alias.type = " . IG_MESSAGE_OPEN . " AND subscribers.id = $alias.contact_id";
if ( ( '_open' === $field || '_open__not_in' === $field ) ) {
if ( $value ) {
$join .= " AND $alias.campaign_id IN (" . implode( ',', array_filter( $value, 'is_numeric' ) ) . ')';
} else {
$join .= " AND $alias.campaign_id IS NOT NULL AND $alias.campaign_id <> 0";
}
}
if ( '_open' === $field ) {
$sub_cond[] = "$alias.contact_id IS NOT NULL";
} elseif ( '_open__not_in' === $field ) {
$sub_cond[] = "$alias.contact_id IS NULL";
} elseif ( '_open_before' === $field ) {
$sub_cond[] = "$alias.timestamp <= " . $this->get_timestamp( $value );
} elseif ( '_open_after' === $field ) {
$sub_cond[] = "$alias.timestamp >= " . $this->get_timestamp( $value );
}
$joins[] = $join;
} elseif ( 0 === strpos( $field, '_click' ) ) {
$join = "LEFT JOIN {$wpbd->prefix}ig_actions AS $alias ON $alias.type = " . IG_LINK_CLICK . " AND subscribers.id = $alias.contact_id";
if ( ( '_click' === $field || '_click__not_in' === $field ) ) {
if ( $value ) {
$join .= " AND $alias.campaign_id IN (" . implode( ',', array_filter( $value, 'is_numeric' ) ) . ')';
} else {
$join .= " AND $alias.campaign_id IS NOT NULL AND $alias.campaign_id <> 0";
}
} elseif ( '_click_link' === $field || '_click_link__not_in' === $field ) {
$join .= " AND $alias.link_id = {$alias}{$field}.ID";
$campaigns = array();
foreach ( $value as $k => $v ) {
if ( is_numeric( $v ) ) {
$campaigns[] = $v;
unset( $value[ $k ] );
}
}
$campaigns = array_filter( $campaigns );
if ( ! empty( $campaigns ) ) {
$join .= " AND $alias.campaign_id IN (" . implode( ',', array_filter( $campaigns, 'is_numeric' ) ) . ')';
}
$joins[] = "LEFT JOIN {$wpbd->prefix}ig_links AS {$alias}{$field} ON {$alias}{$field}.link IN ('" . implode( "','", $value ) . "')";
}
if ( '_click' === $field ) {
$sub_cond[] = "$alias.contact_id IS NOT NULL";
} elseif ( '_click__not_in' === $field ) {
$sub_cond[] = "$alias.contact_id IS NULL";
} elseif ( '_click_before' === $field ) {
$sub_cond[] = "$alias.timestamp <= " . $this->get_timestamp( $value );
} elseif ( '_click_after' === $field ) {
$sub_cond[] = "$alias.timestamp >= " . $this->get_timestamp( $value );
} elseif ( '_click_link' === $field ) {
$sub_cond[] = "$alias.contact_id IS NOT NULL";
} elseif ( '_click_link__not_in' === $field ) {
$sub_cond[] = "$alias.contact_id IS NULL";
}
$joins[] = $join;
}
}
}
}
$sub_cond = array_filter( $sub_cond );
if ( ! empty( $sub_cond ) ) {
$cond[] = '( ' . implode( ' OR ', $sub_cond ) . ' )';
}
}
}
if ( ! empty( $cond ) ) {
$wheres[] = 'AND ( ' . implode( ' AND ', $cond ) . ' )';
}
$joins[] = "LEFT JOIN {$wpbd->prefix}ig_lists_contacts AS lists_subscribers ON subscribers.id = lists_subscribers.contact_id";
// Added where clause for including status if only sent in parameters
if ( !empty( $this->args['status']) ) {
$wheres[] = "AND lists_subscribers.status IN( '" . implode("', '", esc_sql( $this->args['status'] ) ) . "' ) ";
}
if ( ! empty( $this->args['subscriber_status'] ) ) {
$wheres[] = "AND subscribers.status IN( '" . implode("', '", esc_sql( $this->args['subscriber_status'] ) ) . "' )";
}
if ( ! is_bool( $this->args['lists'] ) ) {
// unassigned members if NULL
if ( is_array( $this->args['lists'] ) ) {
$this->args['lists'] = array_filter( $this->args['lists'], 'is_numeric' );
if ( empty( $this->args['lists'] ) ) {
$wheres[] = 'AND lists_subscribers.list_id = 0';
} else {
$wheres[] = 'AND lists_subscribers.list_id IN (' . implode( ',', esc_sql( $this->args['lists'] ) ) . ')';
}
$wheres[] = "AND lists_subscribers.status IN( 'subscribed', 'confirmed' )";
// not in any list
} elseif ( -1 == $this->args['lists'] ) {
$wheres[] = 'AND lists_subscribers.list_id IS NULL';
// ignore lists
}
}
if ( ! empty( $this->args['queue__not_in'] ) ) {
$wheres[] = 'AND queue.contact_id IS NULL';
}
if ( $this->args['where'] ) {
$wheres[] = 'AND ( ' . implode( ' AND ', array_unique( $this->args['where'] ) ) . " )\n";
}
if ( $this->args['orderby'] && ! $this->args['return_count'] ) {
$ordering = isset( $this->args['order'][0] ) ? strtoupper( $this->args['order'][0] ) : 'ASC';
$orders = array();
foreach ( $this->args['orderby'] as $i => $orderby ) {
$ordering = isset( $this->args['order'][ $i ] ) ? strtoupper( $this->args['order'][ $i ] ) : $ordering;
if ( in_array( $orderby, $this->fields ) ) {
$orders[] = "subscribers.$orderby $ordering";
} else {
$orders[] = "$orderby $ordering";
}
}
}
$select = 'SELECT';
$select .= ' ' . implode( ', ', $this->args['select'] );
$from = "FROM {$wpbd->prefix}ig_contacts AS subscribers";
$join = '';
if ( ! empty( $joins ) ) {
$join = implode( "\n ", array_unique( $joins ) );
}
$where = '';
if ( ! empty( $wheres ) ) {
$where = 'WHERE 1=1 ' . implode( "\n ", array_unique( $wheres ) );
}
$groupby = '';
if ( ! empty( $this->args['groupby'] ) ) {
$groupby = 'GROUP BY ' . $this->args['groupby'] . '';
}
$having = '';
if ( ! empty( $this->args['having'] ) ) {
$having = 'HAVING ' . implode( ' AND ', array_unique( $this->args['having'] ) );
}
$order = '';
if ( ! empty( $orders ) ) {
$order = 'ORDER BY ' . implode( ', ', array_unique( $orders ) );
}
$sql = apply_filters( 'ig_es_subscriber_query_sql_select', $select, $this->args, $campaign_id ) . "\n";
$sql .= ' ' . apply_filters( 'ig_es_subscriber_query_sql_from', $from, $this->args, $campaign_id ) . "\n";
$sql .= ' ' . apply_filters( 'ig_es_subscriber_query_sql_join', $join, $this->args, $campaign_id ) . "\n";
$sql .= ' ' . apply_filters( 'ig_es_subscriber_query_sql_where', $where, $this->args, $campaign_id ) . "\n";
$sql .= ' ' . apply_filters( 'ig_es_subscriber_query_sql_groupby', $groupby, $this->args, $campaign_id ) . "\n";
$sql .= ' ' . apply_filters( 'ig_es_subscriber_query_sql_having', $having, $this->args, $campaign_id ) . "\n";
$sql .= ' ' . apply_filters( 'ig_es_subscriber_query_sql_order', $order, $this->args, $campaign_id ) . "\n";
$sql = trim( $sql );
$sql = apply_filters( 'ig_es_subscriber_query_sql', $sql, $this->args, $campaign_id );
if ( $this->args['return_sql'] ) {
$result = $sql;
$this->last_query = $sql;
$this->last_error = null;
$this->last_result = null;
} else {
if ( $this->args['return_count'] ) {
$result = (int) $wpbd->get_var( $sql );
} else {
$sub_query_limit = $this->args['sub_query_limit'] ? (int) $this->args['sub_query_limit'] : false;
$sub_query_offset = 0;
$limit_sql = '';
$result = array();
$round = 0;
do {
// limit is not set explicitly => do sub queries
if ( $sub_query_limit && ! $this->args['limit'] ) {
$sub_query_offset = $sub_query_limit * ( $round++ );
$limit_sql = ' LIMIT ' . $sub_query_offset . ', ' . $sub_query_limit;
}
// get sub query
if ( $this->args['return_ids'] ) {
$sub_result = $wpbd->get_col( $sql . $limit_sql );
} else {
$sub_result = $wpbd->get_results( $sql . $limit_sql );
}
$result = array_merge( $result, $sub_result );
if ( ! $sub_query_limit || ! $this->args['limit'] && count( $sub_result ) < $sub_query_limit ) {
break;
}
} while ( ! empty( $sub_result ) );
unset( $sub_result );
}
$this->last_query = $sql;
$this->last_error = $wpbd->last_error;
$this->last_result = $result;
}
return $result;
}
private function get_condition( $field, $operator, $value ) {
if ( is_array( $value ) ) {
$x = array();
foreach ( $value as $entry ) {
$x[] = $this->get_condition( $field, $operator, $entry );
}
return '(' . implode( ' OR ', array_unique( $x ) ) . ')';
}
// sanitation
$field = esc_sql( $field );
$value = addslashes( stripslashes( esc_sql( $value ) ) );
$operator = $this->get_field_operator( $operator );
$is_empty = '' === $value;
$extra = '';
$positive = false;
$f = false;
switch ( $operator ) {
case '=':
case 'is':
$positive = true;
// no break
case '!=':
case 'is_not':
$f = "subscribers.$field";
$c = $f . ' ' . ( $positive ? '=' : '!=' ) . " '$value'";
if ( $is_empty && $positive || ! $positive ) {
$c = '( ' . $c . ' OR ' . $f . ' IS NULL )';
}
return $c;
break;
case '<>':
case 'contains':
$positive = true;
// no break
case '!<>':
case 'contains_not':
$value = addcslashes( $value, '_%\\' );
$value = "'%$value%'";
$f = "subscribers.$field";
$c = $f . ' ' . ( $positive ? 'LIKE' : 'NOT LIKE' ) . " $value";
if ( $is_empty && $positive || ! $positive ) {
$c = '( ' . $c . ' OR ' . $f . ' IS NULL )';
}
return $c;
break;
case '^':
case 'begin_with':
$value = addcslashes( $value, '_%\\' );
$value = "'$value%'";
$f = "subscribers.$field";
$c = $f . " LIKE $value";
return $c;
break;
case '$':
case 'end_with':
$value = addcslashes( $value, '_%\\' );
$value = "'%$value'";
$f = "subscribers.$field";
$c = $f . " LIKE $value";
return $c;
break;
case '>=':
case 'is_greater_equal':
case '<=':
case 'is_smaller_equal':
$extra = '=';
// no break
case '>':
case 'is_greater':
case '<':
case 'is_smaller':
$f = "subscribers.$field";
$is_numeric = is_numeric( $value );
if ( $is_numeric ) {
$value = (float) $value;
} else {
$value = ! empty( $value ) ? "'$value'" : '';
}
$c = $f . ' ' . ( in_array( $operator, array( 'is_greater', 'is_greater_equal', '>', '>=' ) ) ? '>' . $extra : '<' . $extra ) . " $value";
return $c;
break;
case '%':
case 'pattern':
$positive = true;
// no break
case '!%':
case 'not_pattern':
$f = "subscribers.$field";
if ( $is_empty ) {
$value = '.';
}
if ( ! $positive ) {
$extra = 'NOT ';
}
$c = $f . ' ' . $extra . "REGEXP '$value'";
if ( $is_empty && $positive || ! $positive ) {
$c = '( ' . $c . ' OR ' . $f . ' IS NULL )';
}
return $c;
break;
}
}
private function get_field_operator( $operator ) {
switch ( $operator ) {
case '=':
return 'is';
case '!=':
return 'is_not';
case '<>':
return 'contains';
case '!<>':
return 'contains_not';
case '^':
return 'begin_with';
case '$':
return 'end_with';
case '>=':
return 'is_greater_equal';
case '<=':
return 'is_smaller_equal';
case '>':
return 'is_greater';
case '<':
return 'is_smaller';
case '%':
return 'pattern';
case '!%':
return 'not_pattern';
}
return $operator;
}
private function add_condition( $field, $operator, $value ) {
$condition = array(
'field' => $field,
'operator' => $operator,
'value' => $value,
);
if ( ! $this->args['conditions'] ) {
$this->args['conditions'] = array();
}
array_unshift( $this->args['conditions'], array( $condition ) );
}
private function remove_empty_values( $value ) {
if ( ! is_array( $value ) ) {
$value = explode( ',', $value );
}
$campaign_ids = array_filter( array_unique( $value ) );
return $campaign_ids;
}
private function get_timestamp( $value, $format = null ) {
$timestamp = is_numeric( $value ) ? strtotime( '@' . $value ) : strtotime( '' . $value );
if ( is_numeric( $value ) ) {
$timestamp = (int) $value;
} else {
return false;
}
if ( is_null( $format ) ) {
return $timestamp;
}
return gmdate( $format, $timestamp );
}
private function id_parse( $ids ) {
if ( empty( $ids ) ) {
return $ids;
}
if ( ! is_array( $ids ) ) {
$ids = array( $ids );
}
$return = array();
foreach ( $ids as $id ) {
if ( is_numeric( $id ) ) {
$return[] = $id;
} elseif ( false !== strpos( $id, '-' ) ) {
$splitted = explode( '-', $id );
$min = min( $splitted );
$max = max( $splitted );
for ( $i = $min; $i <= $max; $i++ ) {
$return[] = $i;
}
}
}
return array_values( array_unique( $return ) );
}
}

View File

@@ -0,0 +1,413 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The trial-specific functionality of the plugin.
*/
class IG_ES_Trial {
/**
* Class instance.
*
* @var IG_ES_Trial $instance
*/
public static $instance;
/**
* Initialize the class.
*
* @since 4.6.2
*/
public function __construct() {
add_action( 'admin_init', array( $this, 'show_trial_notices' ) );
add_action( 'wp_ajax_ig_es_trial_optin', array( $this, 'handle_trial_optin' ) );
}
/**
* Get class instance.
*
* @since 4.6.2
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Method to get if user has opted for trial or not.
*
* @return bool
*
* @since 4.6.0
*/
public function is_trial() {
$is_trial = get_option( 'ig_es_is_trial', '' );
if ( 'yes' === $is_trial ) {
return true;
} else {
return false;
}
}
/**
* Get trial start date
*
* @return false|mixed|void
*
* @since 4.6.6
*/
public function get_trial_start_date() {
return get_option( 'ig_es_trial_started_at', '' );
}
/**
* Method to get if trial has expired or not.
*
* @return bool
*
* @since 4.6.1
*/
public function is_trial_expired() {
$is_trial_expired = false;
$is_trial = get_option( 'ig_es_is_trial', '' );
if ( 'yes' === $is_trial ) {
$trial_started_at = get_option( 'ig_es_trial_started_at' );
if ( ! empty( $trial_started_at ) ) {
// Get current timestamp.
$current_time = time();
// Get the timestamp when trial will expire.
$trial_expires_at = $trial_started_at + ES()->trial->get_trial_period();
// Check if current time is greater than expiry time.
if ( $current_time > $trial_expires_at ) {
$is_trial_expired = true;
}
}
}
return $is_trial_expired;
}
/**
* Method to check if trial is valid.
*
* @return bool $is_trial_valid Is trial valid
*
* @since 4.6.1
*/
public function is_trial_valid() {
// Check if user has opted for trial and it has not yet expired.
return $this->is_trial() && ! $this->is_trial_expired();
}
/**
* Method to get trial period
*
* @param string $period_in Period unit.
*
* @return int Trial period in second.
*
* @since 4.6.2
*/
public function get_trial_period( $period_in = 'in_seconds' ) {
$trial_period = 0;
switch ( $period_in ) {
case 'in_days':
$trial_period = IG_ES_TRIAL_PERIOD_IN_DAYS;
break;
case 'in_seconds':
default:
$trial_period = IG_ES_TRIAL_PERIOD_IN_DAYS * DAY_IN_SECONDS;
}
return $trial_period;
}
/**
* Method to add trial related data.
*
* @param string $is_trial.
*
* @return int $trial_started_at
*
* @since 4.6.1
*/
public function add_trial_data( $is_trial = '', $trial_started_at = 0 ) {
$is_trial = ! empty( $is_trial ) ? $is_trial : 'yes';
update_option( 'ig_es_is_trial', $is_trial, false );
if ( 'yes' === $is_trial ) {
$trial_started_at = ! empty( $trial_started_at ) ? $trial_started_at : time();
update_option( 'ig_es_trial_started_at', $trial_started_at, false );
}
}
/**
* Method to get total days since trial start date/time
*
* @return int $trial_time_in_days Trial period passed in days.
*
* @since 4.6.2
*/
public function get_days_since_trial_started() {
$current_time = time();
$trial_time_in_days = 0;
$trial_started_at = get_option( 'ig_es_trial_started_at' );
if ( ! empty( $trial_started_at ) ) {
$trial_time_in_seconds = $current_time - $trial_started_at;
$trial_time_in_days = floor( $trial_time_in_seconds / DAY_IN_SECONDS );
}
return $trial_time_in_days;
}
/**
* Method to get total remaining days in trial expiration.
*
* @return int $remaining_trial_days Remaining trial days.
*
* @since 4.6.2
*/
public function get_remaining_trial_days() {
$total_days_since_trial = $this->get_days_since_trial_started();
$trial_period_in_days = $this->get_trial_period( 'in_days' );
$remaining_trial_days = $trial_period_in_days - $total_days_since_trial;
return $remaining_trial_days;
}
/**
* Method to get trial expiry date
*
* @param string $date_format Date formate
*
* @return string $trial_expriy_date Trial expiry date.
*
* @since 4.6.2
*/
public function get_trial_expiry_date( $date_format = 'Y-m-d H:i:s' ) {
$trial_expriy_date = '';
$trial_started_at = $this->get_trial_started_at();
if ( ! empty( $trial_started_at ) ) {
$trial_expires_at = $trial_started_at + $this->get_trial_period();
$trial_expriy_date = gmdate( $date_format, $trial_expires_at );
}
return $trial_expriy_date;
}
/**
* Method to get trial started at timestamp.
*
* @return int $trial_started_at Trial started at timestamp.
*
* @since 4.6.2
*/
public function get_trial_started_at() {
$trial_started_at = get_option( 'ig_es_trial_started_at', 0 );
return $trial_started_at;
}
/**
* Method to show trial related notices to user.
*
* @since 4.6.2
*/
public function show_trial_notices() {
// Don't show trial notices untill onboarding is completed.
if ( ! IG_ES_Onboarding::is_onboarding_completed() ) {
return;
}
$is_trial = ES()->trial->is_trial();
$is_premium = ES()->is_premium();
$is_premium_installed = ES()->is_premium_installed();
$current_page = ig_es_get_request_data( 'page' );
$show_offer_notice = false;
// Add upgrade to premium nudging notice if currently isn't any offer going on, user has opted for trial and is not a premium user and premium plugin is not installed on site and is not dashboard page.
if ( ! ES()->is_offer_period() && $is_trial && ! $is_premium && ! $is_premium_installed && 'es_dashboard' !== $current_page ) {
// Start nudging the user on following days before trial expiration.
$nudging_days = array( 1, 3, 5 );
$min_nudging_day = min( $nudging_days );
$max_nudging_day = max( $nudging_days );
// Current day's number from start of trial.
$remaining_trial_days = ES()->trial->get_remaining_trial_days();
// User is in nudging period if remaining trial days are between minmum and maximum nudging days.
$is_in_nudging_period = $remaining_trial_days >= $min_nudging_day && $remaining_trial_days <= $max_nudging_day ? true : false;
// Start nudging the user if peried fall into nudging period.
if ( $is_in_nudging_period ) {
$current_nudging_day = 0;
foreach ( $nudging_days as $day ) {
if ( $remaining_trial_days <= $day ) {
// Get current nudging day i.e. 1 or 3 or 5
$current_nudging_day = $day;
break;
}
}
// Check if we have a nudging day.
if ( ! empty( $current_nudging_day ) ) {
$notice_last_dismiss_date = get_option( 'ig_es_trial_to_premium_notice_date' );
// Always show notice if not already dismissed before.
if ( empty( $notice_last_dismiss_date ) ) {
$show_offer_notice = true;
} else {
$trial_expiry_date = ES()->trial->get_trial_expiry_date();
$date_diff_in_seconds = strtotime( $trial_expiry_date ) - strtotime( $notice_last_dismiss_date );
// Ceil function is used to round off to nearest upper limit integer, 4.1 would be 5.
$date_diff_in_days = ceil( $date_diff_in_seconds / DAY_IN_SECONDS );
// Check if current nudging day is after last dismissed date.
if ( $current_nudging_day < $date_diff_in_days ) {
$show_offer_notice = true;
}
}
}
}
}
if ( $show_offer_notice ) {
$notice_args = array(
'include' => ES_PLUGIN_DIR . 'lite/includes/notices/views/trial-to-premium-offer.php',
);
ES_Admin_Notices::add_custom_notice( 'trial_to_premium', $notice_args );
} else {
ES_Admin_Notices::remove_notice( 'trial_to_premium' );
}
}
/**
* Method to get ES trial list hash
*
* @return string $trial_list_hash Get hash for Trial list
*
* @since 5.3.12
*/
public function get_es_trial_list_hash() {
$trial_list_hash = 'f114244b3819';
return $trial_list_hash;
}
/**
* Method to handle trial optin on dashboard page.
*/
public function handle_trial_optin() {
check_ajax_referer( 'ig-es-trial-optin-nonce', 'security' );
$name = ig_es_get_request_data( 'name', '' );
$email = ig_es_get_request_data( 'email', '' );
$trial_list_hash = $this->get_es_trial_list_hash();
$sign_up_data = array(
'name' => $name,
'email' => $email,
'list' => $trial_list_hash,
);
$response = $this->send_ig_sign_up_request( $sign_up_data );
$ig_signup_successfull = 'success' === $response['status'];
if ( $ig_signup_successfull ) {
$is_trial = 'yes';
$trial_started_at = time();
$this->add_trial_data( $is_trial, $trial_started_at );
wp_send_json_success( $response );
} else {
wp_send_json_error( $response );
}
}
/**
* Send a sign up request to ES installed on IG site.
*
* @since 5.3.12
*
* @param array $request_data
*/
public function send_ig_sign_up_request( $request_data = array() ) {
$response = array(
'status' => 'error',
);
$name = ! empty( $request_data['name'] ) ? $request_data['name'] : '';
$email = ! empty( $request_data['email'] ) ? $request_data['email']: '';
$lists = ! empty( $request_data['lists'] ) ? $request_data['lists']: array();
$list = ! empty( $request_data['list'] ) ? $request_data['list'] : '';
if ( is_email( $email ) ) {
$url_params = array(
'ig_es_external_action' => 'subscribe',
'name' => $name,
'email' => $email,
);
if ( ! empty( $lists ) ) {
$url_params['lists'] = $lists;
}
if ( ! empty( $list ) ) {
$url_params['list'] = $list;
}
$ip_address = ig_es_get_ip();
if ( ! empty( $ip_address ) && 'UNKNOWN' !== $ip_address ) {
$url_params['ip_address'] = $ip_address;
}
$ig_es_url = 'https://www.icegram.com/';
$ig_es_url = add_query_arg( $url_params, $ig_es_url );
// Make a get request.
$api_response = wp_remote_get( $ig_es_url );
if ( ! is_wp_error( $api_response ) ) {
$body = ! empty( $api_response['body'] ) && ES_Common::is_valid_json( $api_response['body'] ) ? json_decode( $api_response['body'], true ) : '';
if ( ! empty( $body ) ) {
// If we have received an id in response then email is successfully queued at mailgun server.
if ( ! empty( $body['status'] ) && 'SUCCESS' === $body['status'] ) {
$response['status'] = 'success';
} elseif ( ! empty( $body['status'] ) && 'ERROR' === $body['status'] ) {
$response['status'] = 'error';
$response['message'] = $body['message'];
$response['message_text'] = $body['message_text'];
}
} else {
$response['status'] = 'success';
}
} else {
$response['status'] = 'error';
}
}
return $response;
}
}

View File

@@ -0,0 +1,304 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Tracks logged out customers via cookies.
*
* @class IG_ES_WC_Session_Tracker
*/
class IG_ES_WC_Session_Tracker {
/**
* Tracking cookie expiry
*
* @var int (days)
**/
private static $tracking_cookie_expiry;
/**
* Tracking cookie name
*
* @var string - cookie name
**/
private static $tracking_key_cookie_name;
/**
* Tracking key
*
* @var string - This key WILL BE saved
**/
private static $tracking_key_to_set = '';
/**
* Returns true if a session tracking cookie has been set.
*
* Note: Includes any changes to the cookie in the current request.
*
* @since 4.6.5
*
* @return bool
*/
public static function is_tracking_cookie_set() {
return (bool) IG_ES_WC_Cookies::get( self::$tracking_key_cookie_name );
}
/**
* Returns true if a session tracking cookie has been set.
*
* Note: Includes any changes to the cookie in the current request.
*
* @since 4.2
*
* @return bool
*/
public static function is_session_started_cookie_set() {
return (bool) IG_ES_WC_Cookies::get( 'wp_ig_es_session_started' );
}
/**
* Returns the tracking key as currently stored in the cookie.
*
* @since 4.3
*
* @return string
*/
public static function get_tracking_cookie() {
return ES_Clean::string( IG_ES_WC_Cookies::get( self::$tracking_key_cookie_name ) );
}
/**
* This method doesn't actually set the cookie, rather it initiates the cookie setting.
* Cookies are set only on 'wp', 'shutdown' or 'ig_es/ajax/before_send_json'.
*
* @since 4.3
*
* @param string $tracking_key
*
* @return bool
*/
public static function set_tracking_key_to_be_set( $tracking_key ) {
if ( headers_sent() ) {
return false; // cookies can't be set
}
self::$tracking_key_to_set = $tracking_key;
return true;
}
/**
* Get current session key
*
* @return string|false
*/
public static function get_current_tracking_key() {
if ( ! self::session_tracking_enabled() ) {
return false;
}
// If a new tracking key will be set in the request, use that in favour of current cookie value
if ( self::$tracking_key_to_set && ! headers_sent() ) {
return self::$tracking_key_to_set;
}
return self::get_tracking_cookie();
}
/**
* Returns the current user ID factoring in any session cookies.
*
* @return int
*/
public static function get_detected_user_id() {
if ( is_user_logged_in() ) {
return get_current_user_id();
}
return 0;
}
/**
* Returns the current guest from tracking cookie.
*
* @return IG_ES_Guest|bool
*/
public static function get_current_guest() {
if ( ! self::session_tracking_enabled() ) {
return false;
}
if ( is_user_logged_in() ) {
return false;
}
global $woocommerce;
// Can't look up the guest in this situation.
if ( ! isset( $woocommerce->session ) ) {
return false;
}
$tracking_key = $woocommerce->session->get_customer_id();
if ( $tracking_key ) {
$guest = IG_ES_Guest_Factory::get_by_key( $tracking_key );
return $guest;
}
return false;
}
/**
* Updates the current session based on the customer's email.
*
* Create the customer for the email if needed and contains logic to handle when a customers email changes.
*
* Cases to handle:
*
* - Registered user is logged in or remembered via cookie = bail
* - Email matches existing customer
* - Cookie customer exists
* - Cookie and matched customer are the same = do nothing
* - Cookie and matched customer are different = cookie must be changed, clear cart from previous key to avoid duplicates
* - No cookie customer = Set new cookie to matched customer key
* - Email is new
* - Cookie customer exists
* - Customer data is locked = create new customer, change cookie, clear cart from previous key to avoid duplicates
* - Customer data is not locked = update customer email
* - No cookie customer = Set new cookie to matched customer key
*
* @param string $new_email
* @param string $language
*
* @return IG_ES_Customer|false
*/
public static function set_session_by_captured_email( $new_email, $language = '' ) {
if ( ! is_email( $new_email ) || headers_sent() || ! self::session_tracking_enabled() ) {
// must have a valid email, be able to set cookies, have session tracking enabled
return false;
}
$new_email = ES_Clean::email( $new_email );
$existing_session_customer = self::get_session_customer(); // existing session customer from cookie
$customer_matching_email = IG_ES_Customer_Factory::get_by_email( $new_email, false ); // important! don't create new customer
$email_is_new = false === $customer_matching_email;
if ( $existing_session_customer && $existing_session_customer->is_registered() ) {
return $existing_session_customer; // bail if a registered user is already being tracked
}
// Check if a customer already exists matching the supplied email
if ( $customer_matching_email ) {
if ( ! ( $existing_session_customer && $new_email === $existing_session_customer->get_email() ) ) {
// Customer has changed so delete the cart for the existing customer
// To avoid duplicate abandoned cart emails
if ( $existing_session_customer ) {
$existing_session_customer->delete_cart();
}
}
// Set the matched customer as the new customer
$new_customer = $customer_matching_email;
} else {
// Is there an existing session customer
if ( $existing_session_customer ) {
// Check if existing and new emails are the same
// This is actually impossible considering the previous logic but it's probably more confusing to omit this
if ( $existing_session_customer->get_email() === $new_email ) {
// Nothing to do
$new_customer = $existing_session_customer;
} else {
$guest = $existing_session_customer->get_guest(); // customer can not be a registered user at this point
if ( $guest->is_locked() ) {
// email has changed and guest is locked so we must create a new guest
// first clear the old guests cart, to avoid duplicate abandoned cart emails
$guest->delete_cart();
$new_customer = IG_ES_Customer_Factory::get_by_email( $new_email );
} else {
// Guest is not locked so we can simply update guest email
$guest->set_email( $new_email );
$guest->save();
// Set the new customer to the existing session customer
$new_customer = $existing_session_customer;
}
}
} else {
// There is no session customer, so create one
$new_customer = IG_ES_Customer_Factory::get_by_email( $new_email );
}
}
// init the new customer tracking, also saves/updates the language
// if ( $new_customer ) {
// self::set_session_customer( $new_customer, $language );
// }
// update the stored cart
if ( IG_ES_Abandoned_Cart_Options::is_cart_tracking_enabled() ) {
IG_ES_WC_Carts::update_stored_customer_cart( $new_customer );
}
return $new_customer;
}
/**
* Returns the current session customer and takes into account session tracking cookies.
*
* @return Customer|false
*/
public static function get_session_customer() {
global $woocommerce;
if ( is_user_logged_in() ) {
return ig_es_get_logged_in_customer();
}
if ( ! self::session_tracking_enabled() ) {
return false;
}
// Can't look up the customer in this situation.
if ( ! isset( $woocommerce->session ) ) {
return '';
}
$tracking_key = $woocommerce->session->get_customer_id();
// uses the newly set key if it exists and can be set
if ( $tracking_key ) {
$guest = IG_ES_Guest_Factory::get_by_key( $tracking_key );
if ( $guest instanceof IG_ES_Guest ) {
$customer = new IG_ES_Customer();
$customer->set_prop( 'guest_id', $guest->get_id() );
$customer->exists = true;
return $customer;
}
}
return false;
}
/**
* Check if we can track user session
*/
public static function session_tracking_enabled() {
if ( isset( $_COOKIE['ig_es_session_tracking_disabled'] ) ) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,54 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class IG_ES_WC_Cookies
*
* @since 4.6.5
*/
class IG_ES_WC_Cookies {
/**
* Sets a cookie and also updates the $_COOKIE array.
*
* @param string $name
* @param string $value
* @param int $expire timestamp
*
* @return bool
*/
public static function set( $name, $value, $expire = 0 ) {
wc_setcookie( $name, $value, $expire );
$_COOKIE[ $name ] = $value;
return true;
}
/**
* Gets a cookie
*
* @param $name
* @return mixed
*/
public static function get( $name ) {
return isset( $_COOKIE[ $name ] ) ? sanitize_title( sanitize_text_field( $_COOKIE[ $name ] ) ) : false;
}
/**
* Clear a cookie and also updates the $_COOKIE array.
*
* @param $name
*/
public static function clear( $name ) {
if ( isset( $_COOKIE[ $name ] ) ) {
wc_setcookie( $name, '', time() - HOUR_IN_SECONDS );
unset( $_COOKIE[ $name ] );
}
}
}