mirror of
https://gh.llkk.cc/https://github.com/Tetrakern/fictioneer-email-notifications.git
synced 2025-10-03 18:11:01 +08:00
881 lines
26 KiB
PHP
881 lines
26 KiB
PHP
<?php
|
|
|
|
// No direct access!
|
|
defined( 'ABSPATH' ) OR exit;
|
|
|
|
// Make sure base class exists
|
|
if ( ! class_exists( 'WP_List_Table' ) ) {
|
|
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
|
}
|
|
|
|
/**
|
|
* Adds post_id to the list of removable query arguments
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $args The list of removable query arguments.
|
|
*
|
|
* @return array The modified list of removable query arguments.
|
|
*/
|
|
|
|
function fcnen_remove_post_id_query_arg( $args ) {
|
|
$args[] = 'post_id';
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* Class FCNEN_Notifications_Table
|
|
*
|
|
* @since 0.1.0
|
|
*/
|
|
|
|
class FCNEN_Notifications_Table extends WP_List_Table {
|
|
private $table_data;
|
|
private $view = '';
|
|
private $uri = '';
|
|
|
|
public $total_items;
|
|
public $ready_count = 0;
|
|
public $paused_count = 0;
|
|
public $sent_count = 0;
|
|
|
|
/**
|
|
* Constructor for the WP_List_Table subclass.
|
|
*
|
|
* @since Fictioneer Email Subscriptions 1.0.0
|
|
*/
|
|
|
|
function __construct() {
|
|
global $wpdb;
|
|
|
|
parent::__construct([
|
|
'singular' => 'notification',
|
|
'plural' => 'notifications',
|
|
'ajax' => false
|
|
]);
|
|
|
|
// Validate GET actions
|
|
if ( isset( $_GET['action'] ) ) {
|
|
if ( ! isset( $_GET['fcnen-nonce'] ) || ! check_admin_referer( 'fcnen-table-action', 'fcnen-nonce' ) ) {
|
|
wp_die( __( 'Nonce verification failed. Please try again.', 'fcnen' ) );
|
|
}
|
|
}
|
|
|
|
// Validate POST actions
|
|
if ( isset( $_POST['action'] ) ) {
|
|
if ( ! isset( $_POST['_wpnonce'] ) || ! check_admin_referer( 'bulk-' . $this->_args['plural'] ) ) {
|
|
wp_die( __( 'Nonce verification failed. Please try again.', 'fcnen' ) );
|
|
}
|
|
}
|
|
|
|
// Remove post_id query arg
|
|
add_filter( 'removable_query_args', 'fcnen_remove_post_id_query_arg' );
|
|
|
|
// Initialize
|
|
$table_name = $wpdb->prefix . 'fcnen_notifications';
|
|
$this->view = $_GET['view'] ?? 'all';
|
|
$this->total_items = $wpdb->get_var( "SELECT COUNT(post_id) FROM {$table_name}" ) ?? 0;
|
|
$this->ready_count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE paused = 0 AND last_sent IS NULL" ) ?? 0;
|
|
$this->paused_count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE paused = 1" ) ?? 0;
|
|
$this->sent_count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE last_sent IS NOT NULL" ) ?? 0;
|
|
$this->uri = remove_query_arg( ['action', 'id', 'notifications', 'fcnen-nonce'], $_SERVER['REQUEST_URI'] );
|
|
|
|
// Redirect from empty views
|
|
switch ( $this->view ) {
|
|
case 'paused':
|
|
if ( $this->paused_count < 1 ) {
|
|
wp_safe_redirect( remove_query_arg( 'view', $this->uri ) );
|
|
exit();
|
|
}
|
|
break;
|
|
case 'sent':
|
|
if ( $this->sent_count < 1 ) {
|
|
wp_safe_redirect( remove_query_arg( 'view', $this->uri ) );
|
|
exit();
|
|
}
|
|
break;
|
|
case 'ready':
|
|
if ( $this->ready_count < 1 ) {
|
|
wp_safe_redirect( remove_query_arg( 'view', $this->uri ) );
|
|
exit();
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Finishing cleaning up URI
|
|
$this->uri = remove_query_arg( ['fcnen-notice', 'fcnen-message'], $this->uri );
|
|
}
|
|
|
|
/**
|
|
* Retrieve the column headers for the table
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @return array Associative array of column names with their corresponding labels.
|
|
*/
|
|
|
|
function get_columns() {
|
|
return array(
|
|
'cb' => '<input type="checkbox" />',
|
|
'post_title' => __( 'Title', 'fcnen' ),
|
|
'status' => __( 'Status', 'fcnen' ),
|
|
'post_author' => __( 'Author', 'fcnen' ),
|
|
'post_id' => __( 'Post ID', 'fcnen' ),
|
|
'post_type' => __( 'Type', 'fcnen' ),
|
|
'added_at' => __( 'Date', 'fcnen' ),
|
|
'last_sent' => __( 'Last Sent', 'fcnen' )
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Prepare the items for display in the table
|
|
*
|
|
* @since 0.1.0
|
|
*/
|
|
|
|
function prepare_items() {
|
|
// Setup
|
|
$columns = $this->get_columns();
|
|
$sortable = $this->get_sortable_columns();
|
|
$primary = 'post_title';
|
|
|
|
// Hidden columns?
|
|
$hidden_columns = get_user_meta( get_current_user_id(), 'managetoplevel_page_fcnen-notificationscolumnshidden', true );
|
|
$hidden = is_array( $hidden_columns ) ? $hidden_columns : [];
|
|
|
|
// Data
|
|
$this->table_data = $this->get_table_data();
|
|
$this->_column_headers = [ $columns, $hidden, $sortable, $primary ];
|
|
|
|
// Post data
|
|
$post_data = [];
|
|
$post_ids = array_column( $this->table_data, 'post_id' );
|
|
|
|
$posts = get_posts(
|
|
array(
|
|
'post_type' => ['post', 'fcn_story', 'fcn_chapter'],
|
|
'post__in' => $post_ids ?: [0],
|
|
'numberposts' => -1,
|
|
'update_post_meta_cache' => false,
|
|
'update_post_term_cache' => false,
|
|
'no_found_rows' => true
|
|
)
|
|
);
|
|
|
|
foreach ( $posts as $post ) {
|
|
$post_data[ $post->ID ] = array(
|
|
'post_link' => get_permalink( $post ),
|
|
'post_title' => $post->post_title,
|
|
'post_type' => $post->post_type,
|
|
'post_status' => $post->post_status,
|
|
'post_password' => $post->post_password,
|
|
'post_author' => $post->post_author
|
|
);
|
|
}
|
|
|
|
// Prime author cache
|
|
if ( function_exists( 'update_post_author_caches' ) ) {
|
|
update_post_author_caches( $posts );
|
|
}
|
|
|
|
// Merge datasets
|
|
foreach ( $this->table_data as $key => $notification ) {
|
|
$post_id = $notification['post_id'];
|
|
|
|
if ( isset( $post_data[ $post_id ] ) ) {
|
|
$notification = array_merge( $notification, $post_data[ $post_id ] );
|
|
}
|
|
|
|
$notification['status'] = fcnen_post_sendable( $post_id, true );
|
|
|
|
$notification['last_sent'] = ! empty( $notification['last_sent'] ) ? $notification['last_sent'] : '';
|
|
|
|
$this->table_data[ $key ] = $notification;
|
|
}
|
|
|
|
// Prepare rows
|
|
$this->items = $this->table_data;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the data for the table
|
|
*
|
|
* @since 0.1.0
|
|
* @global wpdb $wpdb The WordPress database object.
|
|
*
|
|
* @return array The table data with appended post data.
|
|
*/
|
|
|
|
function get_table_data() {
|
|
global $wpdb;
|
|
|
|
// Guard
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
return [];
|
|
}
|
|
|
|
// Setup
|
|
$table_name = $wpdb->prefix . 'fcnen_notifications';
|
|
$view_total_items = $this->total_items;
|
|
$per_page = $this->get_items_per_page( 'fcnen_notifications_per_page', 25 );
|
|
$current_page = $this->get_pagenum();
|
|
$offset = ( $per_page * max( 0, absint( $current_page ) - 1 ) );
|
|
$orderby = sanitize_text_field( $_GET['orderby'] ?? 'id' );
|
|
$order = strtolower( $_GET['order'] ?? 'desc' ) === 'desc' ? 'DESC' : 'ASC';
|
|
|
|
// Sanitize orderby
|
|
$orderby = in_array( $orderby, ['post_id', 'post_title', 'post_type', 'post_author', 'added_at', 'last_sent'] ) ?
|
|
$orderby : 'added_at';
|
|
|
|
// Search?
|
|
if ( ! empty( $_POST['s'] ?? '' ) ) {
|
|
$search = sanitize_text_field( $_POST['s'] );
|
|
$query = "SELECT * FROM {$table_name} WHERE post_title LIKE '%" . $wpdb->esc_like( $search ) . "%'";
|
|
} else {
|
|
$query = "SELECT * FROM {$table_name}";
|
|
}
|
|
|
|
// Prepare for extension
|
|
if ( $this->view !== 'all' ) {
|
|
if ( ! strpos( $query, 'WHERE' ) ) {
|
|
$query .= ' WHERE ';
|
|
} else {
|
|
$query .= ' AND ';
|
|
}
|
|
}
|
|
|
|
// View
|
|
switch ( $this->view ) {
|
|
case 'paused':
|
|
$query .= "paused = 1";
|
|
$view_total_items = $this->paused_count;
|
|
break;
|
|
case 'sent':
|
|
$query .= "last_sent IS NOT NULL";
|
|
$view_total_items = $this->sent_count;
|
|
break;
|
|
case 'ready':
|
|
$query .= "paused = 0 AND last_sent IS NULL";
|
|
$view_total_items = $this->ready_count;
|
|
break;
|
|
}
|
|
|
|
// Order
|
|
$query .= " ORDER BY {$orderby} {$order}";
|
|
|
|
// Query
|
|
$notifications = $wpdb->get_results( $wpdb->prepare( "{$query} LIMIT %d OFFSET %d", $per_page, $offset ), ARRAY_A );
|
|
|
|
// Pagination
|
|
$this->set_pagination_args(
|
|
array(
|
|
'total_items' => $view_total_items,
|
|
'per_page' => $per_page,
|
|
'total_pages' => ceil( $view_total_items / $per_page )
|
|
)
|
|
);
|
|
|
|
// Return results
|
|
return $notifications;
|
|
}
|
|
|
|
/**
|
|
* Renders the content of the "cb" column
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $item The data for the current row item.
|
|
*
|
|
* @return string The "cb" column content.
|
|
*/
|
|
|
|
function column_cb( $item ) {
|
|
return sprintf( '<input type="checkbox" name="notifications[]" value="%s" />', $item['post_id'] );
|
|
}
|
|
|
|
/**
|
|
* Render the content of the "post_title" column
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $item The data for the current row item.
|
|
*
|
|
* @return string The "post_title" column content.
|
|
*/
|
|
|
|
function column_post_title( $item ) {
|
|
// Setup
|
|
$actions = [];
|
|
$notes = [];
|
|
$title = '';
|
|
$suffix = '';
|
|
|
|
// Chapter?
|
|
if ( $item['post_type'] === 'fcn_chapter' ) {
|
|
$story_id = get_post_meta( $item['post_id'], 'fictioneer_chapter_story', true );
|
|
$story_title = get_the_title( $story_id ) ?: '';
|
|
|
|
// Story title as suffix
|
|
if ( ! empty( $story_title ) ) {
|
|
$story_title = mb_strimwidth( $story_title, 0, 25, '…' ); // Truncate to max 24 characters
|
|
$suffix = " — {$story_title}";
|
|
}
|
|
|
|
// Hidden?
|
|
if ( ! empty( get_post_meta( $item['post_id'], 'fictioneer_chapter_hidden', true ) ) ) {
|
|
$notes[] = __( 'Hidden', 'fcnen' );
|
|
}
|
|
}
|
|
|
|
// Story?
|
|
if ( $item['post_type'] === 'fcn_story' ) {
|
|
// Hidden?
|
|
if ( ! empty( get_post_meta( $item['post_id'], 'fictioneer_story_hidden', true ) ) ) {
|
|
$notes[] = __( 'Hidden', 'fcnen' );
|
|
}
|
|
}
|
|
|
|
// Build title
|
|
if ( $item['post_link'] ?? 0 ) {
|
|
$title = sprintf(
|
|
_x( '<a href="%1$s">%2$s</a> %3$s %4$s', 'Notification list table title column.', 'fcnen' ),
|
|
$item['post_link'],
|
|
mb_strimwidth( trim( $item['post_title'] ), 0, 41, '…' ), // Truncate to max 40 characters
|
|
$suffix,
|
|
empty( $notes ) ? '' : '(' . implode( ', ', $notes ) . ')'
|
|
);
|
|
} else {
|
|
$title = sprintf(
|
|
_x( '<span>%1$s</span> %2$s %3$s', 'Notification list table title column.', 'fcnen' ),
|
|
mb_strimwidth( trim( $item['post_title'] ), 0, 41, '…' ), // Truncate to max 40 characters
|
|
$suffix,
|
|
empty( $notes ) ? '' : '(' . implode( ', ', $notes ) . ')'
|
|
);
|
|
}
|
|
|
|
// Unsent action
|
|
if ( ! empty( $item['last_sent'] ) ) {
|
|
$actions['unsent'] = sprintf(
|
|
'<a href="%s">%s</a>',
|
|
wp_nonce_url(
|
|
add_query_arg(
|
|
array( 'action' => 'unsent_notification', 'id' => $item['id'], 'post_id' => $item['post_id'] ),
|
|
$this->uri
|
|
),
|
|
'fcnen-table-action',
|
|
'fcnen-nonce'
|
|
),
|
|
__( 'Unsent', 'fcnen' )
|
|
);
|
|
}
|
|
|
|
// Pause action
|
|
if ( empty( $item['last_sent'] ) && ! $item['paused'] ) {
|
|
$actions['pause'] = sprintf(
|
|
'<a href="%s">%s</a>',
|
|
wp_nonce_url(
|
|
add_query_arg(
|
|
array( 'action' => 'pause_notification', 'id' => $item['id'], 'post_id' => $item['post_id'] ),
|
|
$this->uri
|
|
),
|
|
'fcnen-table-action',
|
|
'fcnen-nonce'
|
|
),
|
|
__( 'Pause', 'fcnen' )
|
|
);
|
|
}
|
|
|
|
// Unpause action
|
|
if ( $item['paused'] ) {
|
|
$actions['unpause'] = sprintf(
|
|
'<a href="%s">%s</a>',
|
|
wp_nonce_url(
|
|
add_query_arg(
|
|
array( 'action' => 'unpause_notification', 'id' => $item['id'], 'post_id' => $item['post_id'] ),
|
|
$this->uri
|
|
),
|
|
'fcnen-table-action',
|
|
'fcnen-nonce'
|
|
),
|
|
__( 'Unpause', 'fcnen' )
|
|
);
|
|
}
|
|
|
|
// Delete action
|
|
$actions['delete'] = sprintf(
|
|
'<a href="%s">%s</a>',
|
|
wp_nonce_url(
|
|
add_query_arg(
|
|
array( 'action' => 'delete_notification', 'id' => $item['id'], 'post_id' => $item['post_id'] ),
|
|
$this->uri
|
|
),
|
|
'fcnen-table-action',
|
|
'fcnen-nonce'
|
|
),
|
|
__( 'Remove', 'fcnen' )
|
|
);
|
|
|
|
// Return the final output
|
|
return sprintf(
|
|
'<span>%s</span> %s',
|
|
trim( $title ),
|
|
$this->row_actions( $actions )
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render the content of the "post_author" column
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $item The data for the current row item.
|
|
*
|
|
* @return string The "post_author" column content.
|
|
*/
|
|
|
|
function column_post_author( $item ) {
|
|
return empty( $item['post_author'] ) ? '—' : get_the_author_meta( 'display_name', $item['post_author'] ) ;
|
|
}
|
|
|
|
/**
|
|
* Render the content of the "status" column
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $item The data for the current row item.
|
|
*
|
|
* @return string The "status" column content.
|
|
*/
|
|
|
|
function column_status( $item ) {
|
|
// Setup
|
|
$excluded_posts = get_option( 'fcnen_excluded_posts', [] ) ?: [];
|
|
$excluded_authors = get_option( 'fcnen_excluded_authors', [] ) ?: [];
|
|
|
|
// Return correct status label
|
|
if ( $item['last_sent'] ) {
|
|
return _x( 'Sent', 'Notification list table status column.', 'fcnen' );
|
|
}
|
|
|
|
if ( $item['paused'] ) {
|
|
return _x( 'Paused', 'Notification list table status column.', 'fcnen' );
|
|
}
|
|
|
|
if ( ! get_post( $item['post_id'] ) ) {
|
|
return _x( 'Blocked:<br>Deleted', 'Notification list table status column.', 'fcnen' );
|
|
}
|
|
|
|
if ( get_post_status( $item['post_id'] ) === 'trash' ) {
|
|
return _x( 'Blocked:<br>Trashed', 'Notification list table status column.', 'fcnen' );
|
|
}
|
|
|
|
if ( in_array( $item['post_author'], $excluded_authors ) ) {
|
|
return _x( 'Blocked:<br>Excluded Author', 'Notification list table status column.', 'fcnen' );
|
|
}
|
|
|
|
if ( in_array( $item['post_id'], $excluded_posts ) ) {
|
|
return _x( 'Blocked:<br>Excluded Post', 'Notification list table status column.', 'fcnen' );
|
|
}
|
|
|
|
if ( $item['status']['sendable'] ?? 0 ) {
|
|
return _x( 'Ready', 'Notification list table status column.', 'fcnen' );
|
|
}
|
|
|
|
$status = '';
|
|
|
|
switch ( $item['status']['message'] ) {
|
|
case 'post-unpublished':
|
|
$status = _x( 'Blocked:<br>Unpublished', 'Notification list table status column.', 'fcnen' );
|
|
break;
|
|
case 'post-protected':
|
|
$status = _x( 'Blocked:<br>Protected', 'Notification list table status column.', 'fcnen' );
|
|
break;
|
|
case 'post-invalid-type':
|
|
$status = _x( 'Blocked:<br>Invalid', 'Notification list table status column.', 'fcnen' );
|
|
break;
|
|
case 'post-excluded':
|
|
$status = _x( 'Blocked:<br>Excluded', 'Notification list table status column.', 'fcnen' );
|
|
break;
|
|
case 'post-hidden':
|
|
$status = _x( 'Blocked:<br>Hidden', 'Notification list table status column.', 'fcnen' );
|
|
break;
|
|
default:
|
|
$status = _x( 'Blocked', 'Notification list table status column.', 'fcnen' );
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Render the content of the "post_id" column
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $item The data for the current row item.
|
|
*
|
|
* @return string The "post_id" column content.
|
|
*/
|
|
|
|
function column_post_id( $item ) {
|
|
return $item['post_id'];
|
|
}
|
|
|
|
/**
|
|
* Render the content of the "post_type" column
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $item The data for the current row item.
|
|
*
|
|
* @return string The "post_type" column content.
|
|
*/
|
|
|
|
function column_post_type( $item ) {
|
|
$type_object = get_post_type_object( $item['post_type'] );
|
|
|
|
return $type_object->labels->singular_name;
|
|
}
|
|
|
|
/**
|
|
* Render the content of the "added_at" column
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $item The data for the current row item.
|
|
*
|
|
* @return string The "added_at" column content.
|
|
*/
|
|
|
|
function column_added_at( $item ) {
|
|
return __( 'Enqueued', 'fcnen' ) . '<br>' . get_date_from_gmt( $item['added_at'], 'Y-m-d H:i:s' );
|
|
}
|
|
|
|
/**
|
|
* Render the content of the "last_sent" column
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $item The data for the current row item.
|
|
*
|
|
* @return string The "last_sent" column content.
|
|
*/
|
|
|
|
function column_last_sent( $item ) {
|
|
if ( empty( $item['last_sent'] ) ) {
|
|
return '—';
|
|
}
|
|
|
|
return __( 'Mailed', 'fcnen' ) . '<br>' . get_date_from_gmt( $item['last_sent'], 'Y-m-d H:i:s' );
|
|
}
|
|
|
|
/**
|
|
* Retrieve the bulk actions available for the table
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @return array An associative array of bulk actions. The keys represent the action identifiers,
|
|
* and the values represent the action labels.
|
|
*/
|
|
|
|
function get_bulk_actions() {
|
|
return array(
|
|
'bulk_pause' => __( 'Pause', 'fcnen' ),
|
|
'bulk_unpause' => __( 'Unpause', 'fcnen' ),
|
|
'bulk_unsent' => __( 'Unsent', 'fcnen' ),
|
|
'bulk_delete' => __( 'Remove', 'fcnen' )
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render extra content in the table navigation section
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param string $which The position of the navigation, either "top" or "bottom".
|
|
*/
|
|
|
|
function extra_tablenav( $which ) {
|
|
if ( $this->total_items > 0 ) {
|
|
// Start HTML ---> ?>
|
|
<div class="alignleft actions">
|
|
<?php
|
|
printf(
|
|
'<a href="%s" class="button action">%s</a>',
|
|
wp_nonce_url(
|
|
add_query_arg(
|
|
array( 'action' => 'remove_sent' ),
|
|
remove_query_arg( ['paged'], $this->uri )
|
|
),
|
|
'fcnen-table-action',
|
|
'fcnen-nonce'
|
|
),
|
|
__( 'Remove Sent', 'fcnen' )
|
|
);
|
|
?>
|
|
</div>
|
|
<?php // <--- End HTML
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Display the views for filtering the table
|
|
*
|
|
* @since 0.1.0
|
|
*/
|
|
|
|
function display_views() {
|
|
// Guard
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
echo '';
|
|
return;
|
|
}
|
|
|
|
// Setup
|
|
$views = [];
|
|
$current = 'all';
|
|
$uri = remove_query_arg( ['paged'], $this->uri );
|
|
|
|
// Current
|
|
if ( ! empty( $this->view ) ) {
|
|
switch ( $this->view ) {
|
|
case 'paused':
|
|
$current = 'paused';
|
|
break;
|
|
case 'sent':
|
|
$current = 'sent';
|
|
break;
|
|
case 'ready':
|
|
$current = 'ready';
|
|
break;
|
|
default:
|
|
$current = 'all';
|
|
}
|
|
}
|
|
|
|
// Build views HTML
|
|
$views['all'] = sprintf(
|
|
'<li class="all"><a href="%s" class="%s">%s</a></li>',
|
|
add_query_arg( array( 'view' => 'all' ), $uri ),
|
|
$current === 'all' ? 'current' : '',
|
|
sprintf( __( 'All <span class="count">(%s)</span>', 'fcnen' ), $this->total_items )
|
|
);
|
|
|
|
if ( $this->ready_count > 0 ) {
|
|
$views['ready'] = sprintf(
|
|
'<li class="ready"><a href="%s" class="%s">%s</a></li>',
|
|
add_query_arg( array( 'view' => 'ready' ), $uri ),
|
|
$current === 'ready' ? 'current' : '',
|
|
sprintf( __( 'Ready <span class="count">(%s)</span>', 'fcnen' ), $this->ready_count )
|
|
);
|
|
}
|
|
|
|
if ( $this->paused_count > 0 ) {
|
|
$views['paused'] = sprintf(
|
|
'<li class="paused"><a href="%s" class="%s">%s</a></li>',
|
|
add_query_arg( array( 'view' => 'paused' ), $uri ),
|
|
$current === 'paused' ? 'current' : '',
|
|
sprintf( __( 'Paused <span class="count">(%s)</span>', 'fcnen' ), $this->paused_count )
|
|
);
|
|
}
|
|
|
|
if ( $this->sent_count > 0 ) {
|
|
$views['sent'] = sprintf(
|
|
'<li class="sent"><a href="%s" class="%s">%s</a></li>',
|
|
add_query_arg( array( 'view' => 'sent' ), $uri ),
|
|
$current === 'sent' ? 'current' : '',
|
|
sprintf( __( 'Sent <span class="count">(%s)</span>', 'fcnen' ), $this->sent_count )
|
|
);
|
|
}
|
|
|
|
// Output final HTML
|
|
echo '<ul class="subsubsub">' . implode( ' | ', $views ) . '</ul>';
|
|
}
|
|
|
|
/**
|
|
* Perform actions based on the GET and POST requests
|
|
*
|
|
* @since 0.1.0
|
|
* @global wpdb $wpdb The WordPress database object.
|
|
*/
|
|
|
|
function perform_actions() {
|
|
global $wpdb;
|
|
|
|
// Guard
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
return;
|
|
}
|
|
|
|
// Setup
|
|
$table_name = $wpdb->prefix . 'fcnen_notifications';
|
|
$query_args = [];
|
|
|
|
// GET actions
|
|
if ( isset( $_GET['action'] ) ) {
|
|
$id = absint( $_GET['id'] ?? 0 );
|
|
$post_id = absint( $_GET['post_id'] ?? 0 );
|
|
$post = get_post( $post_id );
|
|
$title = empty( $post ) ? __( 'UNAVAILABLE', 'fcnen' ) : $post->post_title;
|
|
|
|
// Remove sent notifications
|
|
if ( $_GET['action'] === 'remove_sent' ) {
|
|
if ( $wpdb->query( $wpdb->prepare( "DELETE FROM $table_name WHERE last_sent IS NOT NULL" ) ) ) {
|
|
$query_args['fcnen-notice'] = 'remove-sent-notification-success';
|
|
fcnen_log( 'Removed sent notification.' );
|
|
} else {
|
|
$query_args['fcnen-notice'] = 'remove-sent-notification-failure';
|
|
}
|
|
}
|
|
|
|
// Abort if...
|
|
if ( empty( $post_id ) ) {
|
|
wp_safe_redirect( add_query_arg( $query_args, $this->uri ) );
|
|
exit();
|
|
}
|
|
|
|
// Delete notifications
|
|
if ( $_GET['action'] === 'delete_notification' ) {
|
|
if ( $wpdb->delete( $table_name, array( 'id' => $id ), ['%d'] ) ) {
|
|
$query_args['fcnen-notice'] = 'delete-notification-success';
|
|
fcnen_log( "Deleted notification for \"{$title}\" (#{$post_id})." );
|
|
} else {
|
|
$query_args['fcnen-notice'] = 'delete-notification-failure';
|
|
}
|
|
|
|
$query_args['fcnen-message'] = $post_id;
|
|
}
|
|
|
|
// Pause notifications
|
|
if ( $_GET['action'] === 'pause_notification' ) {
|
|
if ( $wpdb->update( $table_name, array( 'paused' => 1 ), array( 'id' => $id ), ['%d'], ['%d'] ) ) {
|
|
$query_args['fcnen-notice'] = 'paused-notification-success';
|
|
fcnen_log( "Paused notification for \"{$title}\" (#{$post_id})." );
|
|
} else {
|
|
$query_args['fcnen-notice'] = 'paused-notification-failure';
|
|
}
|
|
|
|
$query_args['fcnen-message'] = $post_id;
|
|
}
|
|
|
|
// Unpause notifications
|
|
if ( $_GET['action'] === 'unpause_notification' ) {
|
|
if ( $wpdb->update( $table_name, array( 'paused' => 0 ), array( 'id' => $id ), ['%d'], ['%d'] ) ) {
|
|
$query_args['fcnen-notice'] = 'unpaused-notification-success';
|
|
fcnen_log( "Unpaused notification for \"{$title}\" (#{$post_id})." );
|
|
} else {
|
|
$query_args['fcnen-notice'] = 'unpaused-notification-failure';
|
|
}
|
|
|
|
$query_args['fcnen-message'] = $post_id;
|
|
}
|
|
|
|
// Unsent notifications
|
|
if ( $_GET['action'] === 'unsent_notification' ) {
|
|
if ( $wpdb->update( $table_name, array( 'last_sent' => null ), array( 'id' => $id ) ) ) {
|
|
$query_args['fcnen-notice'] = 'unsent-notification-success';
|
|
fcnen_log( "Marked notification for \"{$title}\" (#{$post_id}) as unsent." );
|
|
} else {
|
|
$query_args['fcnen-notice'] = 'unsent-notification-failure';
|
|
}
|
|
|
|
$query_args['fcnen-message'] = $post_id;
|
|
}
|
|
|
|
// Redirect with notice (prevents multi-submit)
|
|
wp_safe_redirect( add_query_arg( $query_args, $this->uri ) );
|
|
exit();
|
|
}
|
|
|
|
// POST actions
|
|
if ( isset( $_POST['action'] ) && empty( $_POST['s'] ?? 0 ) ) {
|
|
$ids = array_map( 'absint', $_POST['notifications'] ?? [] );
|
|
$collection = implode( ',', $ids );
|
|
$log_ids = implode( ', ', array_map( function( $id ) { return "#{$id}"; }, $ids ) );
|
|
|
|
// Abort if...
|
|
if ( empty( $collection ) ) {
|
|
wp_safe_redirect( add_query_arg( $query_args, $this->uri ) );
|
|
exit();
|
|
}
|
|
|
|
// Bulk delete notifications
|
|
if ( $_POST['action'] === 'bulk_delete' ) {
|
|
$query = "DELETE FROM $table_name WHERE post_id IN ($collection)";
|
|
$result = $wpdb->query( $query );
|
|
|
|
if ( $result !== false ) {
|
|
$query_args['fcnen-notice'] = 'bulk-delete-notifications-success';
|
|
$query_args['fcnen-message'] = $result;
|
|
fcnen_log( "Deleted set of notifications: $log_ids." );
|
|
} else {
|
|
$query_args['fcnen-notice'] = 'bulk-delete-notifications-failure';
|
|
}
|
|
}
|
|
|
|
// Bulk unsent notifications
|
|
if ( $_POST['action'] === 'bulk_unsent' ) {
|
|
$query = "UPDATE $table_name SET last_sent = NULL WHERE post_id IN ($collection)";
|
|
$result = $wpdb->query( $query );
|
|
|
|
if ( $result !== false ) {
|
|
$query_args['fcnen-notice'] = 'bulk-unsent-notifications-success';
|
|
$query_args['fcnen-message'] = $result;
|
|
fcnen_log( "Marked set of notifications as unsent: $log_ids." );
|
|
} else {
|
|
$query_args['fcnen-notice'] = 'bulk-unsent-notifications-failure';
|
|
}
|
|
}
|
|
|
|
// Bulk pause notifications
|
|
if ( $_POST['action'] === 'bulk_pause' ) {
|
|
$query = "UPDATE $table_name SET paused = 1 WHERE post_id IN ($collection)";
|
|
$result = $wpdb->query( $query );
|
|
|
|
if ( $result !== false ) {
|
|
$query_args['fcnen-notice'] = 'bulk-pause-notifications-success';
|
|
$query_args['fcnen-message'] = $result;
|
|
fcnen_log( "Paused set of notifications: $log_ids." );
|
|
} else {
|
|
$query_args['fcnen-notice'] = 'bulk-pause-notifications-failure';
|
|
}
|
|
}
|
|
|
|
// Bulk unpause notifications
|
|
if ( $_POST['action'] === 'bulk_unpause' ) {
|
|
$query = "UPDATE $table_name SET paused = 0 WHERE post_id IN ($collection)";
|
|
$result = $wpdb->query( $query );
|
|
|
|
if ( $result !== false ) {
|
|
$query_args['fcnen-notice'] = 'bulk-unpause-notifications-success';
|
|
$query_args['fcnen-message'] = $result;
|
|
fcnen_log( "Unpaused set of notifications: $log_ids." );
|
|
} else {
|
|
$query_args['fcnen-notice'] = 'bulk-unpause-notifications-failure';
|
|
}
|
|
}
|
|
|
|
// Redirect with notice (prevents multi-submit)
|
|
wp_safe_redirect( add_query_arg( $query_args, $this->uri ) );
|
|
exit();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve the sortable columns for the table
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @return array An associative array of sortable columns and their sort parameters.
|
|
* The keys represent the column names, and the values are arrays
|
|
* with the column key and sort order (true for ascending, false for descending).
|
|
*/
|
|
|
|
protected function get_sortable_columns() {
|
|
return array(
|
|
'post_title' => ['post_title', false],
|
|
'added_at' => ['added_at', false],
|
|
'last_sent' => ['last_sent', false]
|
|
);
|
|
}
|
|
}
|