feat: implement Phase 2A Event Templates & Bulk Operations foundation
Comprehensive template system implementation including: HVAC_Event_Template_Manager (700+ lines): - Full CRUD operations for event templates - Security-first design with nonce verification and user permissions - Performance-optimized with 15-minute caching and efficient data loading - Template validation, sanitization, and version control - Public/private template support with access control - Usage tracking and popularity-based sorting - Complete AJAX API for seamless UI interactions HVAC_Event_Form_Builder (1000+ lines): - Extended base form builder with event-specific functionality - Full template integration with selection and population capabilities - Comprehensive field types: datetime, venue, organizer, capacity, cost - Template loading with AJAX-powered real-time updates - Save-as-template functionality with modal interface - Advanced validation including datetime and numeric ranges - Venue/organizer creation with dynamic field visibility - Timezone support with cached options Key Features: - Template schema with metadata, categories, and validation rules - Field-level template population and validation rule inheritance - Cache-optimized performance with 15-minute TTL - Complete security framework with proper sanitization - Modern PHP 8+ patterns with strict typing and singleton architecture - Extensible design ready for bulk operations and UI components Foundation complete for Phase 2A Week 1-2 implementation goals. Next: UI components, JavaScript integration, and bulk operations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
5ab180b5d0
commit
f127e33b03
2 changed files with 1991 additions and 0 deletions
1052
includes/class-hvac-event-form-builder.php
Normal file
1052
includes/class-hvac-event-form-builder.php
Normal file
File diff suppressed because it is too large
Load diff
939
includes/class-hvac-event-template-manager.php
Normal file
939
includes/class-hvac-event-template-manager.php
Normal file
|
|
@ -0,0 +1,939 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* HVAC Event Template Manager
|
||||
*
|
||||
* Manages event templates for reusable event creation and bulk operations
|
||||
* Extends the form builder architecture with template functionality
|
||||
*
|
||||
* @package HVAC_Community_Events
|
||||
* @subpackage Includes
|
||||
* @since 3.1.0 (Phase 2A)
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class HVAC_Event_Template_Manager
|
||||
*
|
||||
* Provides CRUD operations for event templates with performance optimization
|
||||
*/
|
||||
class HVAC_Event_Template_Manager {
|
||||
|
||||
use HVAC_Singleton_Trait;
|
||||
|
||||
/**
|
||||
* Template data structure version for backward compatibility
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private const TEMPLATE_VERSION = '1.0';
|
||||
|
||||
/**
|
||||
* Cache group for template operations
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private const CACHE_GROUP = 'hvac_event_templates';
|
||||
|
||||
/**
|
||||
* Cache TTL for template data (15 minutes)
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private const CACHE_TTL = 900;
|
||||
|
||||
/**
|
||||
* WordPress option key for template storage
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private const OPTION_KEY = 'hvac_event_templates';
|
||||
|
||||
/**
|
||||
* Template metadata schema
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private array $template_schema = [
|
||||
'id' => '', // Unique template identifier
|
||||
'name' => '', // User-friendly template name
|
||||
'description' => '', // Template description
|
||||
'category' => 'general', // Template category (general, training, workshop, etc.)
|
||||
'created_by' => 0, // User ID who created the template
|
||||
'created_date' => '', // Creation timestamp
|
||||
'modified_date' => '', // Last modification timestamp
|
||||
'is_public' => false, // Whether template is available to all users
|
||||
'usage_count' => 0, // Number of times template has been used
|
||||
'version' => self::TEMPLATE_VERSION,
|
||||
'field_data' => [], // Form field values and configuration
|
||||
'validation_rules' => [], // Template-specific validation rules
|
||||
'meta_data' => [] // Additional template metadata
|
||||
];
|
||||
|
||||
/**
|
||||
* Loaded templates cache
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private array $templates_cache = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private function __construct() {
|
||||
$this->init_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize WordPress hooks
|
||||
*/
|
||||
private function init_hooks(): void {
|
||||
// AJAX endpoints for template operations
|
||||
add_action('wp_ajax_hvac_create_template', [$this, 'ajax_create_template']);
|
||||
add_action('wp_ajax_hvac_update_template', [$this, 'ajax_update_template']);
|
||||
add_action('wp_ajax_hvac_delete_template', [$this, 'ajax_delete_template']);
|
||||
add_action('wp_ajax_hvac_get_templates', [$this, 'ajax_get_templates']);
|
||||
add_action('wp_ajax_hvac_get_template', [$this, 'ajax_get_template']);
|
||||
add_action('wp_ajax_hvac_duplicate_template', [$this, 'ajax_duplicate_template']);
|
||||
|
||||
// Admin hooks
|
||||
add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new event template
|
||||
*
|
||||
* @param array $template_data Template configuration data
|
||||
* @return array Result with success status and template ID
|
||||
*/
|
||||
public function create_template(array $template_data): array {
|
||||
try {
|
||||
// Generate unique template ID
|
||||
$template_id = $this->generate_template_id();
|
||||
|
||||
// Prepare template data with schema defaults
|
||||
$template = wp_parse_args($template_data, $this->template_schema);
|
||||
$template['id'] = $template_id;
|
||||
$template['created_date'] = current_time('mysql');
|
||||
$template['modified_date'] = current_time('mysql');
|
||||
$template['created_by'] = get_current_user_id();
|
||||
|
||||
// Validate template data
|
||||
$validation_result = $this->validate_template($template);
|
||||
if (!$validation_result['valid']) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Template validation failed: ' . implode(', ', $validation_result['errors'])
|
||||
];
|
||||
}
|
||||
|
||||
// Sanitize template data
|
||||
$template = $this->sanitize_template($template);
|
||||
|
||||
// Save template
|
||||
$save_result = $this->save_template($template);
|
||||
|
||||
if ($save_result) {
|
||||
// Clear cache
|
||||
$this->clear_templates_cache();
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'template_id' => $template_id,
|
||||
'message' => 'Template created successfully'
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Failed to save template'
|
||||
];
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('HVAC Template Manager - Create template error: ' . $e->getMessage());
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'An error occurred while creating the template'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all event templates for current user
|
||||
*
|
||||
* @param array $filters Optional filters (category, public_only, etc.)
|
||||
* @return array Array of templates
|
||||
*/
|
||||
public function get_templates(array $filters = []): array {
|
||||
$cache_key = 'all_templates_' . md5(serialize($filters) . get_current_user_id());
|
||||
|
||||
// Check cache first
|
||||
$cached_templates = wp_cache_get($cache_key, self::CACHE_GROUP);
|
||||
if ($cached_templates !== false) {
|
||||
return $cached_templates;
|
||||
}
|
||||
|
||||
try {
|
||||
$all_templates = $this->load_templates();
|
||||
$user_id = get_current_user_id();
|
||||
$filtered_templates = [];
|
||||
|
||||
foreach ($all_templates as $template) {
|
||||
// Apply access control
|
||||
if (!$template['is_public'] && $template['created_by'] !== $user_id) {
|
||||
// Check if user has permission to see this template
|
||||
if (!current_user_can('manage_options') && !$this->user_can_access_template($template)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply filters
|
||||
if ($this->template_matches_filters($template, $filters)) {
|
||||
$filtered_templates[] = $template;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by usage count and modification date
|
||||
usort($filtered_templates, function($a, $b) {
|
||||
if ($a['usage_count'] === $b['usage_count']) {
|
||||
return strtotime($b['modified_date']) - strtotime($a['modified_date']);
|
||||
}
|
||||
return $b['usage_count'] - $a['usage_count'];
|
||||
});
|
||||
|
||||
// Cache results
|
||||
wp_cache_set($cache_key, $filtered_templates, self::CACHE_GROUP, self::CACHE_TTL);
|
||||
|
||||
return $filtered_templates;
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('HVAC Template Manager - Get templates error: ' . $e->getMessage());
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific template by ID
|
||||
*
|
||||
* @param string $template_id Template ID
|
||||
* @return array|null Template data or null if not found
|
||||
*/
|
||||
public function get_template(string $template_id): ?array {
|
||||
$cache_key = 'template_' . $template_id;
|
||||
|
||||
// Check cache first
|
||||
$cached_template = wp_cache_get($cache_key, self::CACHE_GROUP);
|
||||
if ($cached_template !== false) {
|
||||
return $cached_template;
|
||||
}
|
||||
|
||||
try {
|
||||
$all_templates = $this->load_templates();
|
||||
|
||||
foreach ($all_templates as $template) {
|
||||
if ($template['id'] === $template_id) {
|
||||
// Check access permissions
|
||||
if (!$this->user_can_access_template($template)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cache template
|
||||
wp_cache_set($cache_key, $template, self::CACHE_GROUP, self::CACHE_TTL);
|
||||
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('HVAC Template Manager - Get template error: ' . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing template
|
||||
*
|
||||
* @param string $template_id Template ID to update
|
||||
* @param array $template_data New template data
|
||||
* @return array Result with success status
|
||||
*/
|
||||
public function update_template(string $template_id, array $template_data): array {
|
||||
try {
|
||||
// Get existing template
|
||||
$existing_template = $this->get_template($template_id);
|
||||
if (!$existing_template) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Template not found'
|
||||
];
|
||||
}
|
||||
|
||||
// Check permissions
|
||||
if (!$this->user_can_edit_template($existing_template)) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Insufficient permissions to edit this template'
|
||||
];
|
||||
}
|
||||
|
||||
// Merge with existing data
|
||||
$updated_template = array_merge($existing_template, $template_data);
|
||||
$updated_template['modified_date'] = current_time('mysql');
|
||||
|
||||
// Validate updated template
|
||||
$validation_result = $this->validate_template($updated_template);
|
||||
if (!$validation_result['valid']) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Template validation failed: ' . implode(', ', $validation_result['errors'])
|
||||
];
|
||||
}
|
||||
|
||||
// Sanitize template data
|
||||
$updated_template = $this->sanitize_template($updated_template);
|
||||
|
||||
// Save template
|
||||
$save_result = $this->save_template($updated_template);
|
||||
|
||||
if ($save_result) {
|
||||
// Clear cache
|
||||
$this->clear_template_cache($template_id);
|
||||
$this->clear_templates_cache();
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'Template updated successfully'
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Failed to update template'
|
||||
];
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('HVAC Template Manager - Update template error: ' . $e->getMessage());
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'An error occurred while updating the template'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a template
|
||||
*
|
||||
* @param string $template_id Template ID to delete
|
||||
* @return array Result with success status
|
||||
*/
|
||||
public function delete_template(string $template_id): array {
|
||||
try {
|
||||
// Get existing template
|
||||
$existing_template = $this->get_template($template_id);
|
||||
if (!$existing_template) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Template not found'
|
||||
];
|
||||
}
|
||||
|
||||
// Check permissions
|
||||
if (!$this->user_can_delete_template($existing_template)) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Insufficient permissions to delete this template'
|
||||
];
|
||||
}
|
||||
|
||||
// Load all templates
|
||||
$all_templates = $this->load_templates();
|
||||
|
||||
// Remove the target template
|
||||
$filtered_templates = array_filter($all_templates, function($template) use ($template_id) {
|
||||
return $template['id'] !== $template_id;
|
||||
});
|
||||
|
||||
// Save updated template list
|
||||
$save_result = update_option(self::OPTION_KEY, array_values($filtered_templates));
|
||||
|
||||
if ($save_result) {
|
||||
// Clear cache
|
||||
$this->clear_template_cache($template_id);
|
||||
$this->clear_templates_cache();
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'Template deleted successfully'
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Failed to delete template'
|
||||
];
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('HVAC Template Manager - Delete template error: ' . $e->getMessage());
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'An error occurred while deleting the template'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique template ID
|
||||
*
|
||||
* @return string Unique template ID
|
||||
*/
|
||||
private function generate_template_id(): string {
|
||||
return 'hvac_template_' . uniqid() . '_' . time();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate template data
|
||||
*
|
||||
* @param array $template Template data to validate
|
||||
* @return array Validation result with 'valid' boolean and 'errors' array
|
||||
*/
|
||||
private function validate_template(array $template): array {
|
||||
$errors = [];
|
||||
|
||||
// Required fields
|
||||
if (empty($template['name'])) {
|
||||
$errors[] = 'Template name is required';
|
||||
}
|
||||
|
||||
if (strlen($template['name']) > 100) {
|
||||
$errors[] = 'Template name must be 100 characters or less';
|
||||
}
|
||||
|
||||
if (strlen($template['description']) > 500) {
|
||||
$errors[] = 'Template description must be 500 characters or less';
|
||||
}
|
||||
|
||||
// Validate category
|
||||
$valid_categories = ['general', 'training', 'workshop', 'certification', 'webinar'];
|
||||
if (!in_array($template['category'], $valid_categories)) {
|
||||
$errors[] = 'Invalid template category';
|
||||
}
|
||||
|
||||
// Validate field data structure
|
||||
if (!is_array($template['field_data'])) {
|
||||
$errors[] = 'Field data must be an array';
|
||||
}
|
||||
|
||||
// Validate user permissions for public templates
|
||||
if ($template['is_public'] && !current_user_can('manage_options')) {
|
||||
$errors[] = 'Only administrators can create public templates';
|
||||
}
|
||||
|
||||
return [
|
||||
'valid' => empty($errors),
|
||||
'errors' => $errors
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize template data
|
||||
*
|
||||
* @param array $template Template data to sanitize
|
||||
* @return array Sanitized template data
|
||||
*/
|
||||
private function sanitize_template(array $template): array {
|
||||
$sanitized = [];
|
||||
|
||||
$sanitized['id'] = sanitize_text_field($template['id']);
|
||||
$sanitized['name'] = sanitize_text_field($template['name']);
|
||||
$sanitized['description'] = sanitize_textarea_field($template['description']);
|
||||
$sanitized['category'] = sanitize_text_field($template['category']);
|
||||
$sanitized['created_by'] = absint($template['created_by']);
|
||||
$sanitized['created_date'] = sanitize_text_field($template['created_date']);
|
||||
$sanitized['modified_date'] = sanitize_text_field($template['modified_date']);
|
||||
$sanitized['is_public'] = (bool) $template['is_public'];
|
||||
$sanitized['usage_count'] = absint($template['usage_count']);
|
||||
$sanitized['version'] = sanitize_text_field($template['version']);
|
||||
$sanitized['field_data'] = $this->sanitize_field_data($template['field_data']);
|
||||
$sanitized['validation_rules'] = $this->sanitize_validation_rules($template['validation_rules']);
|
||||
$sanitized['meta_data'] = $this->sanitize_meta_data($template['meta_data']);
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize field data array
|
||||
*
|
||||
* @param array $field_data Field data to sanitize
|
||||
* @return array Sanitized field data
|
||||
*/
|
||||
private function sanitize_field_data(array $field_data): array {
|
||||
$sanitized = [];
|
||||
|
||||
foreach ($field_data as $key => $value) {
|
||||
$sanitized_key = sanitize_text_field($key);
|
||||
|
||||
if (is_array($value)) {
|
||||
$sanitized[$sanitized_key] = array_map('sanitize_text_field', $value);
|
||||
} else {
|
||||
$sanitized[$sanitized_key] = sanitize_text_field($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize validation rules
|
||||
*
|
||||
* @param array $validation_rules Validation rules to sanitize
|
||||
* @return array Sanitized validation rules
|
||||
*/
|
||||
private function sanitize_validation_rules(array $validation_rules): array {
|
||||
// Implementation for validation rule sanitization
|
||||
return array_map('sanitize_text_field', $validation_rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize meta data
|
||||
*
|
||||
* @param array $meta_data Meta data to sanitize
|
||||
* @return array Sanitized meta data
|
||||
*/
|
||||
private function sanitize_meta_data(array $meta_data): array {
|
||||
$sanitized = [];
|
||||
|
||||
foreach ($meta_data as $key => $value) {
|
||||
$sanitized_key = sanitize_text_field($key);
|
||||
|
||||
if (is_array($value)) {
|
||||
$sanitized[$sanitized_key] = array_map('sanitize_text_field', $value);
|
||||
} else {
|
||||
$sanitized[$sanitized_key] = sanitize_text_field($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all templates from WordPress options
|
||||
*
|
||||
* @return array Array of templates
|
||||
*/
|
||||
private function load_templates(): array {
|
||||
if (!empty($this->templates_cache)) {
|
||||
return $this->templates_cache;
|
||||
}
|
||||
|
||||
$templates = get_option(self::OPTION_KEY, []);
|
||||
|
||||
// Ensure templates are arrays and have required structure
|
||||
$templates = array_filter($templates, function($template) {
|
||||
return is_array($template) && !empty($template['id']);
|
||||
});
|
||||
|
||||
$this->templates_cache = $templates;
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a template to storage
|
||||
*
|
||||
* @param array $template Template data to save
|
||||
* @return bool Success status
|
||||
*/
|
||||
private function save_template(array $template): bool {
|
||||
$all_templates = $this->load_templates();
|
||||
|
||||
// Find and replace existing template or add new one
|
||||
$template_found = false;
|
||||
foreach ($all_templates as $index => $existing_template) {
|
||||
if ($existing_template['id'] === $template['id']) {
|
||||
$all_templates[$index] = $template;
|
||||
$template_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$template_found) {
|
||||
$all_templates[] = $template;
|
||||
}
|
||||
|
||||
return update_option(self::OPTION_KEY, $all_templates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can access a template
|
||||
*
|
||||
* @param array $template Template data
|
||||
* @return bool Whether user can access the template
|
||||
*/
|
||||
private function user_can_access_template(array $template): bool {
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
// Template owner can always access
|
||||
if ($template['created_by'] === $user_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Public templates are accessible to all authenticated users
|
||||
if ($template['is_public']) {
|
||||
return is_user_logged_in();
|
||||
}
|
||||
|
||||
// Administrators can access all templates
|
||||
if (current_user_can('manage_options')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can edit a template
|
||||
*
|
||||
* @param array $template Template data
|
||||
* @return bool Whether user can edit the template
|
||||
*/
|
||||
private function user_can_edit_template(array $template): bool {
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
// Template owner can edit
|
||||
if ($template['created_by'] === $user_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Administrators can edit all templates
|
||||
if (current_user_can('manage_options')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can delete a template
|
||||
*
|
||||
* @param array $template Template data
|
||||
* @return bool Whether user can delete the template
|
||||
*/
|
||||
private function user_can_delete_template(array $template): bool {
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
// Template owner can delete
|
||||
if ($template['created_by'] === $user_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Administrators can delete all templates
|
||||
if (current_user_can('manage_options')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if template matches filters
|
||||
*
|
||||
* @param array $template Template data
|
||||
* @param array $filters Filter criteria
|
||||
* @return bool Whether template matches filters
|
||||
*/
|
||||
private function template_matches_filters(array $template, array $filters): bool {
|
||||
foreach ($filters as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'category':
|
||||
if ($template['category'] !== $value) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'public_only':
|
||||
if ($value && !$template['is_public']) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'search':
|
||||
if (stripos($template['name'], $value) === false &&
|
||||
stripos($template['description'], $value) === false) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear template cache for specific template
|
||||
*
|
||||
* @param string $template_id Template ID
|
||||
*/
|
||||
private function clear_template_cache(string $template_id): void {
|
||||
wp_cache_delete('template_' . $template_id, self::CACHE_GROUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all templates cache
|
||||
*/
|
||||
private function clear_templates_cache(): void {
|
||||
// Clear object cache
|
||||
$this->templates_cache = [];
|
||||
|
||||
// Clear WordPress cache for all possible cache keys
|
||||
// Since we can't enumerate all cache keys, we increment cache version
|
||||
$cache_version = get_option('hvac_template_cache_version', 1);
|
||||
update_option('hvac_template_cache_version', $cache_version + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for creating templates
|
||||
*/
|
||||
public function ajax_create_template(): void {
|
||||
// Security check
|
||||
if (!wp_verify_nonce($_POST['nonce'] ?? '', 'hvac_template_nonce')) {
|
||||
wp_send_json_error(['message' => 'Security check failed']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Permission check
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json_error(['message' => 'Authentication required']);
|
||||
return;
|
||||
}
|
||||
|
||||
$template_data = $_POST['template_data'] ?? [];
|
||||
$result = $this->create_template($template_data);
|
||||
|
||||
if ($result['success']) {
|
||||
wp_send_json_success($result);
|
||||
} else {
|
||||
wp_send_json_error($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for getting templates
|
||||
*/
|
||||
public function ajax_get_templates(): void {
|
||||
// Security check
|
||||
if (!wp_verify_nonce($_GET['nonce'] ?? '', 'hvac_template_nonce')) {
|
||||
wp_send_json_error(['message' => 'Security check failed']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Permission check
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json_error(['message' => 'Authentication required']);
|
||||
return;
|
||||
}
|
||||
|
||||
$filters = $_GET['filters'] ?? [];
|
||||
$templates = $this->get_templates($filters);
|
||||
|
||||
wp_send_json_success([
|
||||
'templates' => $templates,
|
||||
'count' => count($templates)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for getting single template
|
||||
*/
|
||||
public function ajax_get_template(): void {
|
||||
// Security check
|
||||
if (!wp_verify_nonce($_GET['nonce'] ?? '', 'hvac_template_nonce')) {
|
||||
wp_send_json_error(['message' => 'Security check failed']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Permission check
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json_error(['message' => 'Authentication required']);
|
||||
return;
|
||||
}
|
||||
|
||||
$template_id = $_GET['template_id'] ?? '';
|
||||
if (empty($template_id)) {
|
||||
wp_send_json_error(['message' => 'Template ID required']);
|
||||
return;
|
||||
}
|
||||
|
||||
$template = $this->get_template($template_id);
|
||||
|
||||
if ($template) {
|
||||
wp_send_json_success(['template' => $template]);
|
||||
} else {
|
||||
wp_send_json_error(['message' => 'Template not found or access denied']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for updating templates
|
||||
*/
|
||||
public function ajax_update_template(): void {
|
||||
// Security check
|
||||
if (!wp_verify_nonce($_POST['nonce'] ?? '', 'hvac_template_nonce')) {
|
||||
wp_send_json_error(['message' => 'Security check failed']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Permission check
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json_error(['message' => 'Authentication required']);
|
||||
return;
|
||||
}
|
||||
|
||||
$template_id = $_POST['template_id'] ?? '';
|
||||
$template_data = $_POST['template_data'] ?? [];
|
||||
|
||||
if (empty($template_id)) {
|
||||
wp_send_json_error(['message' => 'Template ID required']);
|
||||
return;
|
||||
}
|
||||
|
||||
$result = $this->update_template($template_id, $template_data);
|
||||
|
||||
if ($result['success']) {
|
||||
wp_send_json_success($result);
|
||||
} else {
|
||||
wp_send_json_error($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for deleting templates
|
||||
*/
|
||||
public function ajax_delete_template(): void {
|
||||
// Security check
|
||||
if (!wp_verify_nonce($_POST['nonce'] ?? '', 'hvac_template_nonce')) {
|
||||
wp_send_json_error(['message' => 'Security check failed']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Permission check
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json_error(['message' => 'Authentication required']);
|
||||
return;
|
||||
}
|
||||
|
||||
$template_id = $_POST['template_id'] ?? '';
|
||||
|
||||
if (empty($template_id)) {
|
||||
wp_send_json_error(['message' => 'Template ID required']);
|
||||
return;
|
||||
}
|
||||
|
||||
$result = $this->delete_template($template_id);
|
||||
|
||||
if ($result['success']) {
|
||||
wp_send_json_success($result);
|
||||
} else {
|
||||
wp_send_json_error($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for duplicating templates
|
||||
*/
|
||||
public function ajax_duplicate_template(): void {
|
||||
// Security check
|
||||
if (!wp_verify_nonce($_POST['nonce'] ?? '', 'hvac_template_nonce')) {
|
||||
wp_send_json_error(['message' => 'Security check failed']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Permission check
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json_error(['message' => 'Authentication required']);
|
||||
return;
|
||||
}
|
||||
|
||||
$template_id = $_POST['template_id'] ?? '';
|
||||
|
||||
if (empty($template_id)) {
|
||||
wp_send_json_error(['message' => 'Template ID required']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get original template
|
||||
$original_template = $this->get_template($template_id);
|
||||
if (!$original_template) {
|
||||
wp_send_json_error(['message' => 'Template not found']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create duplicate with modified name
|
||||
$duplicate_data = $original_template;
|
||||
$duplicate_data['name'] = $original_template['name'] . ' (Copy)';
|
||||
unset($duplicate_data['id']); // Remove ID so new one is generated
|
||||
|
||||
$result = $this->create_template($duplicate_data);
|
||||
|
||||
if ($result['success']) {
|
||||
wp_send_json_success($result);
|
||||
} else {
|
||||
wp_send_json_error($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue admin scripts for template management
|
||||
*/
|
||||
public function enqueue_admin_scripts(): void {
|
||||
// Only load on relevant pages
|
||||
if (!$this->should_load_admin_scripts()) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_script(
|
||||
'hvac-template-manager',
|
||||
HVAC_PLUGIN_URL . 'assets/js/hvac-template-manager.js',
|
||||
['jquery'],
|
||||
HVAC_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
// Localize script with AJAX configuration
|
||||
wp_localize_script('hvac-template-manager', 'hvacTemplates', [
|
||||
'ajaxurl' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('hvac_template_nonce'),
|
||||
'strings' => [
|
||||
'confirmDelete' => 'Are you sure you want to delete this template?',
|
||||
'templateSaved' => 'Template saved successfully',
|
||||
'templateDeleted' => 'Template deleted successfully',
|
||||
'error' => 'An error occurred. Please try again.',
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if admin scripts should be loaded
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function should_load_admin_scripts(): bool {
|
||||
global $pagenow;
|
||||
|
||||
// Load on event management pages
|
||||
if (in_array($pagenow, ['admin.php', 'edit.php', 'post.php', 'post-new.php'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Load on template management pages
|
||||
$current_page = $_GET['page'] ?? '';
|
||||
if (strpos($current_page, 'hvac') !== false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue