Unsent: the emails and sign-ups waiting to be tried again, and the * ones meil.ro refused, each with why. They can be sent again or deleted. * * A failed one shows as a count on the menu item, and as a notice on every * admin screen until the list is opened, so a problem does not go unseen. * * @package Meil_Mailer */ if ( ! defined( 'ABSPATH' ) ) { exit; } class Meil_Queue_Admin { public const PAGE = 'meil-unsent'; private const NONCE = 'meil_unsent'; /** The newest failed id the admins have seen on the list. */ private const SEEN = 'meil_unsent_seen'; /** @var Meil_Queue */ private $queue; public function __construct( Meil_Queue $queue ) { $this->queue = $queue; add_action( 'admin_menu', array( $this, 'register_menu' ), 20 ); add_action( 'admin_post_meil_unsent', array( $this, 'handle_action' ) ); add_action( 'admin_notices', array( $this, 'render_notice' ) ); } public function register_menu(): void { list( $failed ) = Meil_Queue::failed_summary(); $title = __( 'Unsent', 'meilro' ); add_submenu_page( 'meil-mailer', $title, $failed > 0 ? $title . ' ' . number_format_i18n( $failed ) . '' : $title, 'manage_options', self::PAGE, array( $this, 'render_page' ) ); } /** On every admin screen but the list itself, while something failed that the admins have not seen yet. */ public function render_notice(): void { if ( ! current_user_can( 'manage_options' ) ) { return; } $screen = get_current_screen(); if ( $screen && false !== strpos( $screen->id, self::PAGE ) ) { return; } list( $failed, $newest ) = Meil_Queue::failed_summary(); if ( 0 === $failed || $newest <= (int) get_option( self::SEEN, 0 ) ) { return; } echo '

'; echo esc_html( sprintf( /* translators: %s: how many */ _n( 'meil.ro: %s email or sign-up could not be sent.', 'meil.ro: %s emails or sign-ups could not be sent.', $failed, 'meilro' ), number_format_i18n( $failed ) ) ); echo ' ' . esc_html__( 'See why', 'meilro' ) . ''; echo '

'; } public function render_page(): void { if ( ! current_user_can( 'manage_options' ) ) { return; } Meil_Queue::prune(); $rows = Meil_Queue::rows(); list( , $newest ) = Meil_Queue::failed_summary(); update_option( self::SEEN, $newest, false ); $format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' ); ?>
render_result(); ?>

' . esc_html( sprintf( /* translators: %s: date and time */ __( 'Waiting, next try %s', 'meilro' ), wp_date( $format, (int) strtotime( $row['next_try'] . ' UTC' ) ) ) ) . ''; } else { echo '' . esc_html__( 'Failed', 'meilro' ) . ''; } ?> action_button( 'send', (int) $row['id'], __( 'Send now', 'meilro' ), 'button button-small' ); ?> action_button( 'delete', (int) $row['id'], __( 'Delete', 'meilro' ), 'button-link button-link-delete' ); ?>
action_button( 'delete_failed', 0, __( 'Delete all failed', 'meilro' ), 'button' ); ?>
queue->send_now( $id ); if ( true === $outcome ) { $result = 'sent'; } elseif ( is_wp_error( $outcome ) ) { $result = Meil_Queue::is_temporary( $outcome ) ? 'waiting' : 'failed'; } } elseif ( 'delete' === $do ) { Meil_Queue::delete( $id ); } elseif ( 'delete_failed' === $do ) { Meil_Queue::delete_failed(); } wp_safe_redirect( add_query_arg( 'meil_unsent', $result, admin_url( 'admin.php?page=' . self::PAGE ) ) ); exit; } /** The notice for what the last action did. Only reads the plugin's own flag. */ private function render_result(): void { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- only picks which notice to show. $result = isset( $_GET['meil_unsent'] ) ? sanitize_key( wp_unslash( (string) $_GET['meil_unsent'] ) ) : ''; $texts = array( 'sent' => array( 'success', __( 'Sent.', 'meilro' ) ), 'waiting' => array( 'warning', __( 'meil.ro still cannot be reached. It will be tried again on its own.', 'meilro' ) ), 'failed' => array( 'error', __( 'meil.ro refused it again. The reason is in the list.', 'meilro' ) ), 'deleted' => array( 'success', __( 'Deleted.', 'meilro' ) ), ); if ( isset( $texts[ $result ] ) ) { printf( '

%2$s

', esc_attr( $texts[ $result ][0] ), esc_html( $texts[ $result ][1] ) ); } } }