upskill-event-manager/includes/class-hvac-announcements-manager.php
Ben cc34abb5fe feat: implement announcement modal system with comprehensive documentation
- Add interactive modal popup for announcement 'Read More' functionality
- Fix nonce conflict by creating separate hvac_announcements_ajax object
- Implement secure AJAX handler with rate limiting and permission checks
- Add comprehensive modal CSS with smooth animations and responsive design
- Include accessibility features (ARIA, keyboard navigation, screen reader support)
- Create detailed documentation in docs/ANNOUNCEMENT-MODAL-SYSTEM.md
- Update API-REFERENCE.md with new modal endpoints and security details
- Add automated Playwright E2E testing for modal functionality
- All modal interactions working: click to open, X to close, ESC to close, outside click
- Production-ready with full error handling and content sanitization

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-20 16:28:55 -03:00

285 lines
No EOL
8.6 KiB
PHP

<?php
/**
* HVAC Announcements Manager
*
* @package HVAC_Community_Events
* @since 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Class HVAC_Announcements_Manager
*
* Main orchestrator for the announcements system
*/
class HVAC_Announcements_Manager {
/**
* Instance of this class
*
* @var HVAC_Announcements_Manager
*/
private static $instance = null;
/**
* Component instances
*
* @var array
*/
private $components = array();
/**
* Get instance of this class
*
* @return HVAC_Announcements_Manager
*/
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
$this->load_dependencies();
$this->init_components();
$this->init_hooks();
}
/**
* Load required files
*/
private function load_dependencies() {
$base_path = plugin_dir_path(dirname(__FILE__)) . 'includes/';
// Load component classes
require_once $base_path . 'class-hvac-announcements-cpt.php';
require_once $base_path . 'class-hvac-announcements-permissions.php';
require_once $base_path . 'class-hvac-announcements-ajax.php';
require_once $base_path . 'class-hvac-announcements-email.php';
require_once $base_path . 'class-hvac-announcements-display.php';
}
/**
* Initialize components
*/
private function init_components() {
$this->components['cpt'] = HVAC_Announcements_CPT::get_instance();
$this->components['permissions'] = HVAC_Announcements_Permissions::get_instance();
$this->components['ajax'] = HVAC_Announcements_Ajax::get_instance();
$this->components['email'] = HVAC_Announcements_Email::get_instance();
$this->components['display'] = HVAC_Announcements_Display::get_instance();
}
/**
* Initialize hooks
*/
private function init_hooks() {
// Activation/deactivation hooks
register_activation_hook(HVAC_PLUGIN_FILE, array($this, 'activate'));
register_deactivation_hook(HVAC_PLUGIN_FILE, array($this, 'deactivate'));
// Page creation
add_action('init', array($this, 'maybe_create_pages'), 20);
// Scripts and styles
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
// Add to plugin's script management
add_filter('hvac_plugin_page_slugs', array($this, 'add_page_slugs'));
}
/**
* Create required pages (now handled by HVAC_Page_Manager)
*/
private function create_pages() {
// Pages are now created by the main HVAC_Page_Manager
// This method is kept for backwards compatibility but no longer creates pages
// The pages are defined in HVAC_Page_Manager::$pages array
return;
}
/**
* Plugin activation hook
*/
public static function activate() {
$instance = self::get_instance();
// Create pages
$instance->create_pages();
// Add capabilities
if (class_exists('HVAC_Announcements_Permissions')) {
HVAC_Announcements_Permissions::add_capabilities();
}
// Flush rewrite rules
flush_rewrite_rules();
}
/**
* Plugin deactivation hook
*/
public static function deactivate() {
// Remove capabilities
if (class_exists('HVAC_Announcements_Permissions')) {
HVAC_Announcements_Permissions::remove_capabilities();
}
// Flush rewrite rules
flush_rewrite_rules();
}
/**
* Maybe create pages if they don't exist (now handled by HVAC_Page_Manager)
*/
public function maybe_create_pages() {
// Pages are now created by the main HVAC_Page_Manager during plugin activation
// This method is kept for backwards compatibility but no longer creates pages
return;
}
/**
* Add announcement page slugs to plugin pages list
*
* @param array $slugs Existing page slugs
* @return array
*/
public function add_page_slugs($slugs) {
$slugs[] = 'announcements'; // master-trainer/announcements
$slugs[] = 'resources'; // trainer/resources
return $slugs;
}
/**
* Enqueue frontend assets
*/
public function enqueue_frontend_assets() {
// Check if we're on a relevant page
if (!$this->is_announcement_page()) {
return;
}
// Enqueue styles
wp_enqueue_style(
'hvac-announcements',
plugin_dir_url(dirname(__FILE__)) . 'assets/css/hvac-announcements.css',
array(),
HVAC_VERSION
);
// Enqueue view script for trainer resources page
if (is_page('trainer-resources') || strpos(home_url($GLOBALS['wp']->request), '/trainer/resources') !== false) {
wp_enqueue_script(
'hvac-announcements-view',
plugin_dir_url(dirname(__FILE__)) . 'assets/js/hvac-announcements-view.js',
array('jquery'),
HVAC_VERSION,
true
);
// Localize script for viewing
wp_localize_script('hvac-announcements-view', 'hvac_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('hvac_announcements_nonce'),
));
}
// Enqueue scripts for master announcements page
if (is_page('master-announcements')) {
wp_enqueue_script(
'hvac-announcements-admin',
plugin_dir_url(dirname(__FILE__)) . 'assets/js/hvac-announcements-admin.js',
array('jquery', 'wp-util'),
HVAC_VERSION,
true
);
// Add TinyMCE
wp_enqueue_editor();
// Add media uploader
wp_enqueue_media();
// Localize script
wp_localize_script('hvac-announcements-admin', 'hvac_announcements', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('hvac_announcements_nonce'),
'strings' => array(
'confirm_delete' => __('Are you sure you want to delete this announcement?', 'hvac'),
'error_loading' => __('Error loading announcements', 'hvac'),
'error_saving' => __('Error saving announcement', 'hvac'),
'success_created' => __('Announcement created successfully', 'hvac'),
'success_updated' => __('Announcement updated successfully', 'hvac'),
'success_deleted' => __('Announcement deleted successfully', 'hvac'),
),
));
}
}
/**
* Enqueue admin assets
*/
public function enqueue_admin_assets($hook) {
// Only load on our custom pages
if (!$this->is_announcement_page()) {
return;
}
// Admin styles
wp_enqueue_style(
'hvac-announcements-admin',
plugin_dir_url(dirname(__FILE__)) . 'assets/css/hvac-announcements-admin.css',
array(),
HVAC_VERSION
);
}
/**
* Check if current page is an announcement-related page
*
* @return bool
*/
private function is_announcement_page() {
if (is_page('master-announcements') || is_page('trainer-resources')) {
return true;
}
// Check for hierarchical URLs
global $wp;
$current_url = home_url($wp->request);
if (strpos($current_url, '/master-trainer/announcements') !== false ||
strpos($current_url, '/trainer/resources') !== false) {
return true;
}
return false;
}
/**
* Get component instance
*
* @param string $component Component name
* @return object|null
*/
public function get_component($component) {
return isset($this->components[$component]) ? $this->components[$component] : null;
}
/**
* Initialize the announcements system
* Called from main plugin file
*/
public static function init() {
return self::get_instance();
}
}