Files
Hi-School-Slide-Manager/includes/class-hssm-admin.php
T
stack_admn 9bb2171b92 audit clean-up
add 'no dates' logic
2026-02-22 19:05:49 -08:00

562 lines
22 KiB
PHP

<?php
/**
* HSSM Admin Class
*
* Handles admin functionality including settings pages and API key management
*
* @package Hi_School_Slide_Manager
* @since 1.0.0
*/
// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit( 'Direct access forbidden.' );
}
/**
* HSSM Admin Class
*
* Admin interface and settings management
*/
class HSSM_Admin {
/**
* Constructor
*
* @since 1.0.0
*/
public function __construct() {
// Hook is registered in main class
}
/**
* Initialize admin functionality
*
* @since 1.0.0
*/
public function init() {
// This is called during the admin_init hook from HSSM_Main
$this->register_settings();
}
/**
* Add admin menus
*
* @since 1.0.0
*/
public function add_menus() {
// Add settings page under the Slides menu
add_submenu_page(
'edit.php?post_type=hssm_slide',
__( 'Slide Manager Settings', 'hi-school-slide-manager' ),
__( 'Settings', 'hi-school-slide-manager' ),
'manage_options',
'hssm-settings',
array( $this, 'settings_page' )
);
// Add API documentation page
add_submenu_page(
'edit.php?post_type=hssm_slide',
__( 'API Documentation', 'hi-school-slide-manager' ),
__( 'API Docs', 'hi-school-slide-manager' ),
'manage_options',
'hssm-api-docs',
array( $this, 'api_docs_page' )
);
}
/**
* Register plugin settings
*
* @since 1.0.0
*/
public function register_settings() {
// Register settings
register_setting( 'hssm_settings', 'hssm_plugin_mode' );
register_setting( 'hssm_settings', 'hssm_api_url' );
register_setting( 'hssm_settings', 'hssm_client_site_slug' );
register_setting( 'hssm_settings', 'hssm_notification_emails' );
register_setting( 'hssm_settings', 'hssm_cache_duration' );
register_setting( 'hssm_settings', 'hssm_api_keys' );
// Add settings sections
add_settings_section(
'hssm_general',
__( 'General Settings', 'hi-school-slide-manager' ),
array( $this, 'general_section_callback' ),
'hssm-settings'
);
add_settings_section(
'hssm_notifications',
__( 'Email Notifications', 'hi-school-slide-manager' ),
array( $this, 'notifications_section_callback' ),
'hssm-settings'
);
add_settings_section(
'hssm_api',
__( 'API Settings', 'hi-school-slide-manager' ),
array( $this, 'api_section_callback' ),
'hssm-settings'
);
// Add settings fields
add_settings_field(
'hssm_plugin_mode',
__( 'Plugin Mode', 'hi-school-slide-manager' ),
array( $this, 'plugin_mode_field' ),
'hssm-settings',
'hssm_general'
);
add_settings_field(
'hssm_api_url',
__( 'Manager API URL', 'hi-school-slide-manager' ),
array( $this, 'api_url_field' ),
'hssm-settings',
'hssm_general'
);
add_settings_field(
'hssm_client_site_slug',
__( 'Client Site Slug', 'hi-school-slide-manager' ),
array( $this, 'client_site_slug_field' ),
'hssm-settings',
'hssm_general'
);
add_settings_field(
'hssm_cache_duration',
__( 'Cache Duration', 'hi-school-slide-manager' ),
array( $this, 'cache_duration_field' ),
'hssm-settings',
'hssm_general'
);
add_settings_field(
'hssm_notification_emails',
__( 'Notification Recipients', 'hi-school-slide-manager' ),
array( $this, 'notification_emails_field' ),
'hssm-settings',
'hssm_notifications'
);
add_settings_field(
'hssm_api_keys',
__( 'API Keys', 'hi-school-slide-manager' ),
array( $this, 'api_keys_field' ),
'hssm-settings',
'hssm_api'
);
}
/**
* Settings page callback
*
* @since 1.0.0
*/
public function settings_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
// Handle form submission
if ( isset( $_POST['submit'] ) || isset( $_POST['generate_api_key'] ) || isset( $_POST['delete_api_key'] ) ) {
check_admin_referer( 'hssm_settings' );
$this->handle_settings_save();
}
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<?php settings_errors(); ?>
<form method="post" action="">
<?php
wp_nonce_field( 'hssm_settings' );
// Use a consistent page slug for do_settings_sections
do_settings_sections( 'hssm-settings' );
submit_button();
?>
</form>
<div class="hssm-api-endpoint-info" style="margin-top: 30px; padding: 20px; background: #f9f9f9; border: 1px solid #ddd;">
<h3><?php _e( 'API Endpoints', 'hi-school-slide-manager' ); ?></h3>
<p><?php _e( 'Use these endpoints for companion sites:', 'hi-school-slide-manager' ); ?></p>
<ul>
<li><code><?php echo esc_html( rest_url( 'hssm/v1/slides/{site}' ) ); ?></code> - Get slides for a site</li>
<li><code><?php echo esc_html( rest_url( 'hssm/v1/sites' ) ); ?></code> - Get available sites</li>
<li><code><?php echo esc_html( rest_url( 'hssm/v1/slide/{id}' ) ); ?></code> - Get single slide</li>
<li><code><?php echo esc_html( rest_url( 'hssm/v1/health' ) ); ?></code> - Health check (no auth required)</li>
</ul>
<p><strong><?php _e( 'Authentication:', 'hi-school-slide-manager' ); ?></strong> <?php _e( 'Include API key in X-HSSM-API-Key header or api_key parameter', 'hi-school-slide-manager' ); ?></p>
</div>
</div>
<?php
}
/**
* API documentation page
*
* @since 1.0.0
*/
public function api_docs_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
?>
<div class="wrap">
<h1><?php _e( 'Hi-School Slide Manager API Documentation', 'hi-school-slide-manager' ); ?></h1>
<div class="hssm-api-docs">
<h2><?php _e( 'Authentication', 'hi-school-slide-manager' ); ?></h2>
<p><?php _e( 'All API endpoints (except health check) require authentication using an API key.', 'hi-school-slide-manager' ); ?></p>
<p><?php _e( 'Include the API key in one of these ways:', 'hi-school-slide-manager' ); ?></p>
<ul>
<li><?php _e( 'Header:', 'hi-school-slide-manager' ); ?> <code>X-HSSM-API-Key: your-api-key</code></li>
<li><?php _e( 'Query parameter:', 'hi-school-slide-manager' ); ?> <code>?api_key=your-api-key</code></li>
</ul>
<h2><?php _e( 'Endpoints', 'hi-school-slide-manager' ); ?></h2>
<h3><code>GET /wp-json/hssm/v1/slides/{site}</code></h3>
<p><?php _e( 'Get slides for a specific site.', 'hi-school-slide-manager' ); ?></p>
<h4><?php _e( 'Parameters:', 'hi-school-slide-manager' ); ?></h4>
<ul>
<li><code>site</code> (required) - Site slug: hi-school, one-stop, or ace</li>
<li><code>date</code> (optional) - Date to filter by (YYYY-MM-DD)</li>
<li><code>limit</code> (optional) - Max slides to return (1-50, default: 10)</li>
<li><code>status</code> (optional) - Filter by status: active, scheduled, all (default: active)</li>
</ul>
<h4><?php _e( 'Example:', 'hi-school-slide-manager' ); ?></h4>
<pre><code>GET <?php echo esc_html( rest_url( 'hssm/v1/slides/hi-school?limit=5&date=2025-12-01' ) ); ?>
Headers: X-HSSM-API-Key: your-api-key</code></pre>
<h3><code>GET /wp-json/hssm/v1/sites</code></h3>
<p><?php _e( 'Get all available sites.', 'hi-school-slide-manager' ); ?></p>
<h4><?php _e( 'Example:', 'hi-school-slide-manager' ); ?></h4>
<pre><code>GET <?php echo esc_html( rest_url( 'hssm/v1/sites' ) ); ?>
Headers: X-HSSM-API-Key: your-api-key</code></pre>
<h3><code>GET /wp-json/hssm/v1/slide/{id}</code></h3>
<p><?php _e( 'Get a specific slide by ID.', 'hi-school-slide-manager' ); ?></p>
<h4><?php _e( 'Parameters:', 'hi-school-slide-manager' ); ?></h4>
<ul>
<li><code>id</code> (required) - Slide ID</li>
</ul>
<h3><code>GET /wp-json/hssm/v1/health</code></h3>
<p><?php _e( 'Health check endpoint (no authentication required).', 'hi-school-slide-manager' ); ?></p>
<h2><?php _e( 'Response Format', 'hi-school-slide-manager' ); ?></h2>
<p><?php _e( 'All responses are in JSON format. Slide objects include:', 'hi-school-slide-manager' ); ?></p>
<pre><code>{
"id": 123,
"title": "Slide Title",
"subtitle": "Slide Subtitle",
"content": "Slide content...",
"buttons": [
{
"text": "Learn More",
"url": "https://example.com"
}
],
"order": 0,
"background_image": {
"id": 456,
"url": "https://example.com/image.jpg",
"width": 1920,
"height": 800,
"alt": "Image description",
"sizes": {
"full": "https://example.com/image.jpg",
"large": "https://example.com/image-1024x428.jpg"
}
},
"schedule": {
"start_date": "2025-01-01 00:00:00",
"end_date": "2025-12-31 23:59:59",
"auto_publish": true,
"auto_unpublish": true
},
"target_sites": [
{
"slug": "hi-school",
"name": "Hi-School Pharmacy"
}
],
"client": {
"slug": "client-name",
"name": "Client Name"
},
"status": "publish",
"created": "2025-01-01 12:00:00",
"modified": "2025-01-01 12:00:00"
}
</code></pre>
</div>
<style>
.hssm-api-docs {
max-width: 800px;
}
.hssm-api-docs h3 {
background: #f0f0f0;
padding: 10px;
border-left: 4px solid #0073aa;
}
.hssm-api-docs pre {
background: #f9f9f9;
padding: 15px;
border: 1px solid #ddd;
overflow-x: auto;
}
.hssm-api-docs code {
background: #f9f9f9;
padding: 2px 4px;
border-radius: 3px;
}
.hssm-api-docs pre code {
background: none;
padding: 0;
}
</style>
</div>
<?php
}
/**
* Enqueue admin assets
*
* @since 1.0.0
* @param string $hook Current admin page hook
*/
public function enqueue_assets( $hook ) {
// Enqueue general admin styles for all HSSM admin pages
if ( strpos( $hook, 'hssm' ) !== false || ( isset($_GET['post_type']) && $_GET['post_type'] === 'hssm_slide' ) ) {
wp_enqueue_style(
'hssm-admin',
HSSM_PLUGIN_URL . 'assets/css/admin.css',
array(),
HSSM_VERSION
);
wp_enqueue_script(
'hssm-admin',
HSSM_PLUGIN_URL . 'assets/js/admin.js',
array( 'jquery' ),
HSSM_VERSION,
true
);
}
// Conditionally enqueue dashboard-specific slide styles and dequeue public slider styles
global $pagenow;
if ( ( $pagenow === 'edit.php' && isset($_GET['post_type']) && $_GET['post_type'] === 'hssm_slide' ) || is_page_template('page-slide-dashboard.php') || is_page_template('page-slide-preview.php') ) {
wp_enqueue_style(
'hssm-admin-slides-dashboard',
HSSM_PLUGIN_URL . 'assets/css/admin-slides-dashboard.css',
array(),
HSSM_VERSION
);
// Dequeue the public slider styles on these admin-facing pages to prevent conflicts
// This is largely redundant after changes in HSSM_Main::enqueue_frontend_assets,
// but harmless to keep as a failsafe.
wp_dequeue_style('hssm-slider');
}
}
/**
* Handle settings save
*
* @since 1.0.0
*/
private function handle_settings_save() {
// Handle general settings save
if ( isset( $_POST['submit'] ) ) {
if ( isset( $_POST['hssm_plugin_mode'] ) ) {
update_option( 'hssm_plugin_mode', sanitize_text_field( $_POST['hssm_plugin_mode'] ) );
}
if ( isset( $_POST['hssm_api_url'] ) ) {
update_option( 'hssm_api_url', esc_url_raw( $_POST['hssm_api_url'] ) );
}
if ( isset( $_POST['hssm_client_site_slug'] ) ) {
update_option( 'hssm_client_site_slug', sanitize_text_field( $_POST['hssm_client_site_slug'] ) );
}
if ( isset( $_POST['hssm_cache_duration'] ) ) {
update_option( 'hssm_cache_duration', absint( $_POST['hssm_cache_duration'] ) );
}
if ( isset( $_POST['hssm_notification_emails'] ) ) {
$emails = explode( "\n", str_replace( "\r", "", $_POST['hssm_notification_emails'] ) );
$emails = array_map( 'sanitize_email', $emails );
$emails = array_filter( $emails );
update_option( 'hssm_notification_emails', $emails );
}
add_settings_error( 'hssm_settings', 'settings_saved', __( 'Settings saved successfully.', 'hi-school-slide-manager' ), 'success' );
}
// Handle API key generation
if ( isset( $_POST['generate_api_key'] ) ) {
$api_keys = get_option( 'hssm_api_keys', array() );
$api_keys[] = wp_generate_password( 32, false );
update_option( 'hssm_api_keys', $api_keys );
add_settings_error( 'hssm_settings', 'api_key_generated', __( 'New API key generated successfully.', 'hi-school-slide-manager' ), 'success' );
}
// Handle API key deletion (only when delete was explicitly triggered via JS with index)
if ( ! empty( $_POST['delete_api_key'] ) && isset( $_POST['api_key_index'] ) && $_POST['api_key_index'] !== '' ) {
$api_keys = get_option( 'hssm_api_keys', array() );
$index = (int) $_POST['api_key_index'];
if ( isset( $api_keys[ $index ] ) ) {
unset( $api_keys[ $index ] );
$api_keys = array_values( $api_keys ); // Reindex array
update_option( 'hssm_api_keys', $api_keys );
add_settings_error( 'hssm_settings', 'api_key_deleted', __( 'API key deleted successfully.', 'hi-school-slide-manager' ), 'success' );
}
}
}
/**
* General section callback
*/
public function general_section_callback() {
echo '<p>' . __( 'General plugin settings.', 'hi-school-slide-manager' ) . '</p>';
}
/**
* Notifications section callback
*/
public function notifications_section_callback() {
echo '<p>' . __( 'Configure email notifications for new slides.', 'hi-school-slide-manager' ) . '</p>';
}
/**
* API section callback
*/
public function api_section_callback() {
echo '<p>' . __( 'Manage API keys for companion sites.', 'hi-school-slide-manager' ) . '</p>';
}
/**
* Plugin mode field
*/
public function plugin_mode_field() {
$value = get_option( 'hssm_plugin_mode', 'manager' );
?>
<select name="hssm_plugin_mode" id="hssm_plugin_mode">
<option value="manager" <?php selected( $value, 'manager' ); ?>><?php _e( 'Manager (Source Site)', 'hi-school-slide-manager' ); ?></option>
<option value="client" <?php selected( $value, 'client' ); ?>><?php _e( 'Client (Companion Site)', 'hi-school-slide-manager' ); ?></option>
</select>
<p class="description"><?php _e( 'Choose "Manager" for the main site where slides are created, or "Client" for sites that just display slides from the manager.', 'hi-school-slide-manager' ); ?></p>
<?php
}
/**
* API URL field
*/
public function api_url_field() {
$value = get_option( 'hssm_api_url', '' );
echo '<input type="url" name="hssm_api_url" value="' . esc_attr( $value ) . '" class="regular-text" placeholder="https://main-site.com/wp-json/" /> ';
echo '<p class="description">' . __( 'The REST API base URL of the Manager site.', 'hi-school-slide-manager' ) . '</p>';
}
/**
* Client site slug field
*/
public function client_site_slug_field() {
$value = get_option( 'hssm_client_site_slug', '' );
?>
<select name="hssm_client_site_slug" id="hssm_client_site_slug">
<option value=""><?php _e( 'Select site...', 'hi-school-slide-manager' ); ?></option>
<?php
$sites = HSSM_Main::get_companion_sites();
foreach ( $sites as $site ) {
echo '<option value="' . esc_attr( $site['slug'] ) . '" ' . selected( $value, $site['slug'], false ) . '>' . esc_html( $site['name'] ) . '</option>';
}
?>
</select>
<p class="description"><?php _e( 'Identify this site to the Manager API.', 'hi-school-slide-manager' ); ?></p>
<?php
}
/**
* Cache duration field
*/
public function cache_duration_field() {
$value = get_option( 'hssm_cache_duration', 3600 );
echo '<input type="number" name="hssm_cache_duration" value="' . esc_attr( $value ) . '" min="300" max="86400" /> ';
echo '<span class="description">' . __( 'Recommended cache duration for API responses (seconds)', 'hi-school-slide-manager' ) . '</span>';
}
/**
* Notification emails field
*/
public function notification_emails_field() {
$emails = get_option( 'hssm_notification_emails', array() );
echo '<textarea name="hssm_notification_emails" rows="5" class="regular-text">' . esc_textarea( implode( "\n", $emails ) ) . '</textarea><br>';
echo '<span class="description">' . __( 'Enter email addresses (one per line) to receive notifications when new slides are published.', 'hi-school-slide-manager' ) . '</span>';
}
/**
* API keys field
*/
public function api_keys_field() {
$api_keys = get_option( 'hssm_api_keys', array() );
echo '<div class="hssm-api-keys">';
if ( empty( $api_keys ) ) {
echo '<p>' . __( 'No API keys generated yet.', 'hi-school-slide-manager' ) . '</p>';
} else {
echo '<input type="hidden" name="api_key_index" id="hssm-delete-api-key-index" value="" />';
echo '<input type="hidden" name="delete_api_key" id="hssm-delete-api-key-flag" value="0" />';
echo '<table class="widefat">';
echo '<thead><tr><th>' . __( 'API Key', 'hi-school-slide-manager' ) . '</th><th>' . __( 'Actions', 'hi-school-slide-manager' ) . '</th></tr></thead>';
echo '<tbody>';
foreach ( $api_keys as $index => $key ) {
echo '<tr>';
echo '<td><code>' . esc_html( $key ) . '</code></td>';
echo '<td>';
echo '<button type="button" class="button copy-api-key" data-key="' . esc_attr( $key ) . '">' . __( 'Copy', 'hi-school-slide-manager' ) . '</button> ';
echo '<button type="button" class="button button-link-delete hssm-delete-api-key" data-index="' . esc_attr( $index ) . '">' . __( 'Delete', 'hi-school-slide-manager' ) . '</button>';
echo '</td>';
echo '</tr>';
}
echo '</tbody></table>';
}
echo '<p><button type="submit" name="generate_api_key" value="1" class="button button-secondary">' . __( 'Generate New API Key', 'hi-school-slide-manager' ) . '</button></p>';
echo '<p class="description">' . __( 'API keys are used by companion sites to authenticate and fetch slides.', 'hi-school-slide-manager' ) . '</p>';
echo '</div>';
// Add JavaScript for copy and delete functionality
?>
<script>
jQuery(document).ready(function($) {
$(".copy-api-key").on("click", function() {
var key = $(this).data("key");
navigator.clipboard.writeText(key).then(function() {
alert("API key copied to clipboard!");
});
});
$(".hssm-delete-api-key").on("click", function() {
if (! confirm("<?php echo esc_js( __( 'Are you sure you want to delete this API key?', 'hi-school-slide-manager' ) ); ?>")) {
return;
}
var index = $(this).data("index");
$("#hssm-delete-api-key-index").val(index);
$("#hssm-delete-api-key-flag").val("1");
$(this).closest("form").submit();
});
});
</script>
<?php
}
}