Update dashboard JS and frontend class

This commit is contained in:
stack_admn committed 2026-10-31 18:17:55 -07:00
1 parent 48c7d23261
commit 2b1424d127
8 files changed
+245 -98

No files matched your search

+158 -73
View File
@@ -46,6 +46,7 @@ class HSSM_Frontend {
add_action( 'wp_ajax_hssm_save_slide', array( $this, 'ajax_save_slide' ) );
add_action( 'wp_ajax_hssm_upload_image', array( $this, 'ajax_upload_image' ) );
add_action( 'wp_ajax_hssm_get_slides', array( $this, 'ajax_get_slides' ) );
add_action( 'wp_ajax_hssm_get_slide_for_edit', array( $this, 'ajax_get_slide_for_edit' ) );
add_action( 'wp_ajax_hssm_delete_slide', array( $this, 'ajax_delete_slide' ) );
add_action( 'wp_ajax_hssm_update_slide', array( $this, 'ajax_update_slide' ) );
add_action( 'wp_ajax_hssm_schedule_slide', array( $this, 'ajax_schedule_slide' ) );
@@ -142,20 +143,20 @@ class HSSM_Frontend {
private function check_dashboard_access( $check_upload = false ) {
// Check if user is logged in
if ( ! is_user_logged_in() ) {
error_log( 'Dashboard access denied: User not logged in' );
hssm_debug_log( 'Dashboard access denied: User not logged in' );
return false;
}
$user_id = get_current_user_id();
error_log( 'Checking dashboard access for user ID: ' . $user_id );
hssm_debug_log( 'Checking dashboard access for user ID: ' . $user_id );
// Check Members plugin capability FIRST
if ( function_exists( 'members_user_can' ) && members_user_can( $user_id, 'hssm_manage_slides' ) ) {
error_log( 'Members plugin check: PASS (hssm_manage_slides)' );
hssm_debug_log( 'Members plugin check: PASS (hssm_manage_slides)' );
if ( $check_upload ) {
$can_upload = current_user_can( 'upload_files' );
error_log( 'Upload files capability check: ' . ($can_upload ? 'PASS' : 'FAIL') );
hssm_debug_log( 'Upload files capability check: ' . ($can_upload ? 'PASS' : 'FAIL') );
return $can_upload;
}
@@ -164,11 +165,11 @@ class HSSM_Frontend {
// Fallback to WordPress capabilities - be more permissive
$can_edit = current_user_can( 'edit_posts' ) || current_user_can( 'publish_posts' ) || current_user_can( 'manage_options' );
error_log( 'WordPress capability check (edit_posts/publish_posts/manage_options): ' . ($can_edit ? 'PASS' : 'FAIL') );
hssm_debug_log( 'WordPress capability check (edit_posts/publish_posts/manage_options): ' . ($can_edit ? 'PASS' : 'FAIL') );
if ( $check_upload ) {
$can_upload = current_user_can( 'upload_files' );
error_log( 'Upload files capability check: ' . ($can_upload ? 'PASS' : 'FAIL') );
hssm_debug_log( 'Upload files capability check: ' . ($can_upload ? 'PASS' : 'FAIL') );
return $can_edit && $can_upload;
}
@@ -475,7 +476,7 @@ class HSSM_Frontend {
* @return array Sanitized data
*/
private function sanitize_slide_data( $data ) {
error_log( 'Raw form data received: ' . print_r( $data, true ) );
hssm_debug_log( 'Raw form data received: ' . print_r( $data, true ) );
// Handle target_sites - it might come as an array or need to be extracted
$target_sites = array();
@@ -514,8 +515,8 @@ class HSSM_Frontend {
'hide_all_text' => ! empty( $data['hide_all_text'] ) && $data['hide_all_text'] === '1',
);
error_log( 'Sanitized slide data: ' . print_r( $sanitized, true ) );
error_log( 'Target sites count: ' . count( $sanitized['target_sites'] ) );
hssm_debug_log( 'Sanitized slide data: ' . print_r( $sanitized, true ) );
hssm_debug_log( 'Target sites count: ' . count( $sanitized['target_sites'] ) );
return $sanitized;
}
@@ -556,11 +557,11 @@ class HSSM_Frontend {
* @return bool Is valid
*/
private function validate_slide_data( $data ) {
error_log( 'Validating slide data: ' . print_r( $data, true ) );
hssm_debug_log( 'Validating slide data: ' . print_r( $data, true ) );
// Required fields
if ( empty( $data['title'] ) ) {
error_log( 'Validation failed: Missing title' );
hssm_debug_log( 'Validation failed: Missing title' );
return false;
}
@@ -570,17 +571,17 @@ class HSSM_Frontend {
foreach ( $data['target_sites'] as $site_slug ) {
$term = get_term_by( 'slug', $site_slug, 'hssm_site' );
if ( ! $term || is_wp_error( $term ) ) {
error_log( 'Validation failed: Invalid site slug (not a taxonomy term): ' . $site_slug );
hssm_debug_log( 'Validation failed: Invalid site slug (not a taxonomy term): ' . $site_slug );
return false;
}
}
} else {
error_log( 'Validation failed: No target sites selected or target_sites is not an array' );
error_log( 'target_sites value: ' . print_r( $data['target_sites'] ?? 'NOT SET', true ) );
hssm_debug_log( 'Validation failed: No target sites selected or target_sites is not an array' );
hssm_debug_log( 'target_sites value: ' . print_r( $data['target_sites'] ?? 'NOT SET', true ) );
return false;
}
error_log( 'Validation passed' );
hssm_debug_log( 'Validation passed' );
return true;
}
@@ -618,7 +619,7 @@ class HSSM_Frontend {
private function save_slide_taxonomies( $slide_id, $data ) {
// Set target sites
if ( ! empty( $data['target_sites'] ) && is_array( $data['target_sites'] ) ) {
error_log( 'Saving target sites for slide ' . $slide_id . ': ' . print_r( $data['target_sites'], true ) );
hssm_debug_log( 'Saving target sites for slide ' . $slide_id . ': ' . print_r( $data['target_sites'], true ) );
// Ensure we're using term slugs, not IDs
$term_slugs = array();
@@ -638,12 +639,12 @@ class HSSM_Frontend {
if ( ! empty( $term_slugs ) ) {
$result = wp_set_post_terms( $slide_id, $term_slugs, 'hssm_site' );
error_log( 'wp_set_post_terms result: ' . print_r( $result, true ) );
hssm_debug_log( 'wp_set_post_terms result: ' . print_r( $result, true ) );
} else {
error_log( 'No valid term slugs to save' );
hssm_debug_log( 'No valid term slugs to save' );
}
} else {
error_log( 'No target sites to save for slide ' . $slide_id );
hssm_debug_log( 'No target sites to save for slide ' . $slide_id );
}
// Set client
@@ -794,54 +795,10 @@ class HSSM_Frontend {
$formatted_slides = array();
foreach ( $slides as $slide ) {
$slide_meta = get_post_meta( $slide->ID );
// Get selected sites from taxonomy terms
$site_terms = wp_get_post_terms( $slide->ID, 'hssm_site', array( 'fields' => 'all' ) );
$site_names = array();
if ( ! empty( $site_terms ) && ! is_wp_error( $site_terms ) ) {
foreach ( $site_terms as $site_term ) {
$site_names[] = $site_term->name;
}
$formatted = $this->format_slide_for_dashboard( $slide );
if ( $formatted ) {
$formatted_slides[] = $formatted;
}
// Get featured image
$featured_image_url = get_the_post_thumbnail_url( $slide->ID, 'thumbnail' );
// Get schedule info
$start_date = isset( $slide_meta['_hssm_start_date'][0] ) ? $slide_meta['_hssm_start_date'][0] : '';
$end_date = isset( $slide_meta['_hssm_end_date'][0] ) ? $slide_meta['_hssm_end_date'][0] : '';
$auto_publish = isset( $slide_meta['_hssm_auto_publish'][0] ) ? $slide_meta['_hssm_auto_publish'][0] : '';
$auto_unpublish = isset( $slide_meta['_hssm_auto_unpublish'][0] ) ? $slide_meta['_hssm_auto_unpublish'][0] : '';
// Format status for display
$status_display = ucfirst( $slide->post_status );
if ( $slide->post_status === 'pending' ) {
$status_display = 'Pending Approval';
} elseif ( $slide->post_status === 'future' ) {
$status_display = 'Scheduled';
}
$formatted_slides[] = array(
'id' => $slide->ID,
'title' => $slide->post_title,
'subtitle' => isset( $slide_meta['_hssm_subtitle'][0] ) ? $slide_meta['_hssm_subtitle'][0] : '',
'content' => $slide->post_content,
'status' => $slide->post_status,
'status_display' => $status_display,
'sites' => $site_names,
'target_sites' => $site_names,
'client' => $this->get_slide_client_name( $slide->ID ),
'start_date' => $start_date,
'end_date' => $end_date,
'auto_publish' => $auto_publish,
'auto_unpublish' => $auto_unpublish,
'featured_image_url' => $featured_image_url,
'created' => $slide->post_date,
'modified' => $slide->post_modified,
'buttons' => isset( $slide_meta['_hssm_buttons'][0] ) ? maybe_unserialize( $slide_meta['_hssm_buttons'][0] ) : array(),
'hide_all_text' => isset( $slide_meta['_hssm_hide_all_text'][0] ) && $slide_meta['_hssm_hide_all_text'][0] === '1'
);
}
wp_send_json_success( array(
@@ -853,6 +810,134 @@ class HSSM_Frontend {
'has_more' => ( $page * $per_page ) < $total_slides
) );
}
/**
* AJAX handler for loading a single slide into the dashboard edit form.
*
* Used when the slide is not already in the in-memory list (pagination, filters, deep link).
*
* @since 1.1.2
*/
public function ajax_get_slide_for_edit() {
if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'hssm_dashboard_nonce' ) ) {
wp_send_json_error( array( 'message' => 'Nonce verification failed' ) );
return;
}
if ( ! current_user_can( 'edit_posts' ) ) {
wp_send_json_error( array( 'message' => 'You do not have permission to edit slides.' ) );
return;
}
if ( ! isset( $_POST['slide_id'] ) || '' === trim( (string) $_POST['slide_id'] ) ) {
wp_send_json_error( array( 'message' => 'Slide ID is required' ) );
return;
}
$slide_id = absint( $_POST['slide_id'] );
$slide = get_post( $slide_id );
if ( ! $slide || 'hssm_slide' !== $slide->post_type ) {
wp_send_json_error( array( 'message' => 'Slide not found' ) );
return;
}
if ( ! current_user_can( 'edit_post', $slide_id ) ) {
wp_send_json_error( array( 'message' => 'Insufficient permissions' ) );
return;
}
$formatted = $this->format_slide_for_dashboard( $slide );
if ( ! $formatted ) {
wp_send_json_error( array( 'message' => 'Slide not found' ) );
return;
}
wp_send_json_success( array( 'slide' => $formatted ) );
}
/**
* Format a slide for the dashboard list and edit form.
*
* @since 1.1.2
* @param int|WP_Post $slide Slide ID or post object.
* @return array|null Formatted slide data.
*/
private function format_slide_for_dashboard( $slide ) {
if ( is_numeric( $slide ) ) {
$slide = get_post( $slide );
}
if ( ! $slide instanceof WP_Post || 'hssm_slide' !== $slide->post_type ) {
return null;
}
$slide_meta = get_post_meta( $slide->ID );
$site_terms = wp_get_post_terms( $slide->ID, 'hssm_site', array( 'fields' => 'all' ) );
$site_names = array();
if ( ! empty( $site_terms ) && ! is_wp_error( $site_terms ) ) {
foreach ( $site_terms as $site_term ) {
$site_names[] = $site_term->name;
}
}
$status_display = ucfirst( $slide->post_status );
if ( 'pending' === $slide->post_status ) {
$status_display = 'Pending Approval';
} elseif ( 'future' === $slide->post_status ) {
$status_display = 'Scheduled';
}
$start_date = isset( $slide_meta['_hssm_start_date'][0] ) ? $slide_meta['_hssm_start_date'][0] : '';
$end_date = isset( $slide_meta['_hssm_end_date'][0] ) ? $slide_meta['_hssm_end_date'][0] : '';
return array(
'id' => $slide->ID,
'title' => $slide->post_title,
'subtitle' => isset( $slide_meta['_hssm_subtitle'][0] ) ? $slide_meta['_hssm_subtitle'][0] : '',
'content' => $slide->post_content,
'status' => $slide->post_status,
'status_display' => $status_display,
'sites' => $site_names,
'target_sites' => $site_names,
'client' => $this->get_slide_client_name( $slide->ID ),
'start_date' => $this->format_dashboard_date( $start_date ),
'end_date' => $this->format_dashboard_date( $end_date ),
'auto_publish' => isset( $slide_meta['_hssm_auto_publish'][0] ) ? $slide_meta['_hssm_auto_publish'][0] : '',
'auto_unpublish' => isset( $slide_meta['_hssm_auto_unpublish'][0] ) ? $slide_meta['_hssm_auto_unpublish'][0] : '',
'featured_image' => (int) get_post_thumbnail_id( $slide->ID ),
'featured_image_url' => get_the_post_thumbnail_url( $slide->ID, 'thumbnail' ),
'created' => $slide->post_date,
'modified' => $slide->post_modified,
'buttons' => isset( $slide_meta['_hssm_buttons'][0] ) ? maybe_unserialize( $slide_meta['_hssm_buttons'][0] ) : array(),
'hide_all_text' => isset( $slide_meta['_hssm_hide_all_text'][0] ) && '1' === $slide_meta['_hssm_hide_all_text'][0],
);
}
/**
* Normalize stored dates for HTML date inputs (YYYY-MM-DD).
*
* @since 1.1.2
* @param string $value Stored date or datetime.
* @return string
*/
private function format_dashboard_date( $value ) {
if ( empty( $value ) ) {
return '';
}
if ( preg_match( '/^(\d{4}-\d{2}-\d{2})/', $value, $matches ) ) {
return $matches[1];
}
$timestamp = strtotime( $value );
if ( ! $timestamp ) {
return '';
}
return wp_date( 'Y-m-d', $timestamp );
}
/**
* AJAX handler for approving slides
@@ -907,7 +992,7 @@ class HSSM_Frontend {
$result = wp_update_post( $post_data );
if ( $result ) {
error_log( "Slide $slide_id approved with action: $approve_action" );
hssm_debug_log( "Slide $slide_id approved with action: $approve_action" );
// Trigger 2: Notification to Creator (Author) when approved
$notifications = new HSSM_Notifications();
@@ -1057,18 +1142,18 @@ class HSSM_Frontend {
* @since 1.0.0
*/
public function ajax_schedule_slide() {
error_log( 'Schedule slide AJAX called' );
error_log( 'POST data: ' . print_r( $_POST, true ) );
hssm_debug_log( 'Schedule slide AJAX called' );
hssm_debug_log( 'POST data: ' . print_r( $_POST, true ) );
// Check nonce
if ( ! check_ajax_referer( 'hssm_dashboard_nonce', 'nonce', false ) ) {
error_log( 'Nonce verification failed' );
hssm_debug_log( 'Nonce verification failed' );
wp_send_json_error( array( 'message' => 'Security check failed' ) );
}
// Check user permissions
if ( ! current_user_can( 'edit_posts' ) ) {
error_log( 'User permissions check failed' );
hssm_debug_log( 'User permissions check failed' );
wp_send_json_error( array( 'message' => 'Insufficient permissions' ) );
}
@@ -1076,7 +1161,7 @@ class HSSM_Frontend {
$slide_data = $this->sanitize_slide_data( $_POST );
if ( ! $this->validate_slide_data( $slide_data ) ) {
error_log( 'Slide data validation failed' );
hssm_debug_log( 'Slide data validation failed' );
wp_send_json_error( array( 'message' => 'Invalid slide data' ) );
}
@@ -1416,7 +1501,7 @@ class HSSM_Frontend {
}
// --- DEBUG ---
// error_log('HSSM Query Filter Check: is_main=' . ($query->is_main_query()?'Y':'N') . ' post_type=' . print_r($query->get('post_type'), true));
// hssm_debug_log('HSSM Query Filter Check: is_main=' . ($query->is_main_query()?'Y':'N') . ' post_type=' . print_r($query->get('post_type'), true));
// Only on preview page
$obj_id = get_queried_object_id();