robotstxt-smtp-newsletter/admin/class-statistics-page.php
2026-02-18 15:24:59 +00:00

255 lines
8.2 KiB
PHP

<?php
/**
* Statistics Admin Page
*
* Displays campaign performance metrics and historical data.
*
* @package ROBOTSTXT_SMTP_Newsletter
* @since 2.2.0
*/
namespace Robotstxt_SMTP_Newsletter\Admin;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Statistics Page class.
*
* Provides admin UI for viewing campaign statistics and performance metrics.
*/
class Statistics_Page {
/**
* Register admin page hooks.
*
* @return void
*/
public static function register() {
add_submenu_page(
'newsletter_main_main',
__( 'Email Statistics', 'robotstxt-smtp-newsletter' ),
__( 'Statistics', 'robotstxt-smtp-newsletter' ),
'manage_options',
'robotstxt-smtp-newsletter-stats',
array( __CLASS__, 'render_page' )
);
add_action( 'admin_post_delete_campaign_history', array( __CLASS__, 'handle_delete_campaign' ) );
}
/**
* Render admin page.
*
* @return void
*/
public static function render_page() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Insufficient permissions', 'robotstxt-smtp-newsletter' ) );
}
$stats_instance = \Robotstxt_SMTP_Newsletter\Statistics::get_instance();
// Sync from queue first to get latest data.
$stats_instance->sync_from_queue();
$campaigns = $stats_instance->get_recent_campaigns( 20 );
$global = $stats_instance->get_global_stats( 30 );
// Handle success message.
if ( isset( $_GET['deleted'] ) ) {
?>
<div class="notice notice-success is-dismissible">
<p>
<?php
printf(
/* translators: %d: number of records deleted */
esc_html__( '%d queue records deleted.', 'robotstxt-smtp-newsletter' ),
absint( $_GET['deleted'] )
);
?>
</p>
</div>
<?php
}
?>
<div class="wrap">
<h1><?php esc_html_e( 'Email Statistics', 'robotstxt-smtp-newsletter' ); ?></h1>
<!-- Global Stats -->
<h2><?php esc_html_e( 'Global Performance (Last 30 Days)', 'robotstxt-smtp-newsletter' ); ?></h2>
<table class="widefat" style="max-width:600px; margin-bottom:30px;">
<tbody>
<tr>
<td><strong><?php esc_html_e( 'Total Emails Sent', 'robotstxt-smtp-newsletter' ); ?></strong></td>
<td style="text-align:right;">
<?php echo number_format_i18n( $global['total_sent'] ); ?>
</td>
</tr>
<tr>
<td><strong><?php esc_html_e( 'Total Failed', 'robotstxt-smtp-newsletter' ); ?></strong></td>
<td style="text-align:right; color:#d9534f;">
<?php echo number_format_i18n( $global['total_failed'] ); ?>
</td>
</tr>
<tr>
<td><strong><?php esc_html_e( 'Average Speed', 'robotstxt-smtp-newsletter' ); ?></strong></td>
<td style="text-align:right;">
<?php
printf(
/* translators: %s: emails per hour */
esc_html__( '%s emails/hour', 'robotstxt-smtp-newsletter' ),
number_format_i18n( $global['avg_emails_per_hour'], 0 )
);
?>
</td>
</tr>
<tr>
<td><strong><?php esc_html_e( 'Success Rate', 'robotstxt-smtp-newsletter' ); ?></strong></td>
<td style="text-align:right;">
<?php
$total = $global['total_sent'] + $global['total_failed'];
$rate = $total > 0 ? ( $global['total_sent'] / $total ) * 100 : 0;
echo number_format_i18n( $rate, 1 ) . '%';
?>
</td>
</tr>
</tbody>
</table>
<!-- Campaign Stats -->
<h2><?php esc_html_e( 'Recent Campaigns', 'robotstxt-smtp-newsletter' ); ?></h2>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php esc_html_e( 'Campaign', 'robotstxt-smtp-newsletter' ); ?></th>
<th style="text-align:right;"><?php esc_html_e( 'Total', 'robotstxt-smtp-newsletter' ); ?></th>
<th style="text-align:right;"><?php esc_html_e( 'Sent', 'robotstxt-smtp-newsletter' ); ?></th>
<th style="text-align:right;"><?php esc_html_e( 'Failed', 'robotstxt-smtp-newsletter' ); ?></th>
<th><?php esc_html_e( 'Started', 'robotstxt-smtp-newsletter' ); ?></th>
<th><?php esc_html_e( 'Finished', 'robotstxt-smtp-newsletter' ); ?></th>
<th style="text-align:right;"><?php esc_html_e( 'Duration', 'robotstxt-smtp-newsletter' ); ?></th>
<th style="text-align:right;"><?php esc_html_e( 'Speed', 'robotstxt-smtp-newsletter' ); ?></th>
<th><?php esc_html_e( 'Actions', 'robotstxt-smtp-newsletter' ); ?></th>
</tr>
</thead>
<tbody>
<?php if ( empty( $campaigns ) ) : ?>
<tr>
<td colspan="9" style="text-align:center; padding:40px;">
<p><?php esc_html_e( 'No campaigns found', 'robotstxt-smtp-newsletter' ); ?></p>
</td>
</tr>
<?php else : ?>
<?php foreach ( $campaigns as $campaign ) : ?>
<tr>
<td><strong><?php echo esc_html( $campaign->campaign_name ); ?></strong></td>
<td style="text-align:right;">
<?php echo number_format_i18n( $campaign->total_emails ); ?>
</td>
<td style="text-align:right; color:#5cb85c;">
<?php echo number_format_i18n( $campaign->sent_emails ); ?>
</td>
<td style="text-align:right; color:#d9534f;">
<?php echo number_format_i18n( $campaign->failed_emails ); ?>
</td>
<td>
<?php
if ( $campaign->started_at ) {
$started_time = mysql2date( 'Y-m-d H:i:s', $campaign->started_at );
echo esc_html( $started_time );
} else {
echo '-';
}
?>
</td>
<td>
<?php
if ( $campaign->finished_at ) {
$finished_time = mysql2date( 'Y-m-d H:i:s', $campaign->finished_at );
echo esc_html( $finished_time );
} else {
echo '<em>' . esc_html__( 'In progress', 'robotstxt-smtp-newsletter' ) . '</em>';
}
?>
</td>
<td style="text-align:right;">
<?php
if ( $campaign->duration_seconds ) {
$minutes = floor( $campaign->duration_seconds / 60 );
$seconds = $campaign->duration_seconds % 60;
echo sprintf( '%dm %ds', absint( $minutes ), absint( $seconds ) );
} else {
echo '-';
}
?>
</td>
<td style="text-align:right;">
<?php
if ( $campaign->emails_per_hour ) {
echo number_format_i18n( $campaign->emails_per_hour, 0 ) . '/h<br>';
echo '<small>' . number_format_i18n( $campaign->emails_per_minute, 1 ) . '/min</small>';
} else {
echo '-';
}
?>
</td>
<td>
<?php if ( $campaign->newsletter_id ) : ?>
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" style="display:inline;">
<?php wp_nonce_field( 'delete_campaign_history', 'delete_campaign_nonce' ); ?>
<input type="hidden" name="action" value="delete_campaign_history">
<input type="hidden" name="newsletter_id" value="<?php echo absint( $campaign->newsletter_id ); ?>">
<button type="submit" class="button button-small" onclick="return confirm('<?php echo esc_attr__( 'Delete all queue records for this campaign? Statistics will be preserved.', 'robotstxt-smtp-newsletter' ); ?>');">
<?php esc_html_e( 'Delete Queue', 'robotstxt-smtp-newsletter' ); ?>
</button>
</form>
<?php else : ?>
-
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
<?php
}
/**
* Handle delete campaign queue action.
*
* @return void
*/
public static function handle_delete_campaign() {
check_admin_referer( 'delete_campaign_history', 'delete_campaign_nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Insufficient permissions', 'robotstxt-smtp-newsletter' ) );
}
$newsletter_id = isset( $_POST['newsletter_id'] ) ? absint( $_POST['newsletter_id'] ) : 0;
if ( $newsletter_id > 0 ) {
$queue = \Robotstxt_SMTP_Newsletter\Queue::get_instance();
$deleted = $queue->delete_campaign_history( $newsletter_id );
wp_safe_redirect(
add_query_arg(
array(
'page' => 'robotstxt-smtp-newsletter-stats',
'deleted' => $deleted,
),
admin_url( 'admin.php' )
)
);
exit;
}
wp_safe_redirect( admin_url( 'admin.php?page=robotstxt-smtp-newsletter-stats' ) );
exit;
}
}