🚨 CRITICAL: Fixed deployment blockers by adding missing core directories: **Community System (CRITICAL)** - includes/community/ - Login_Handler and all community classes - templates/community/ - Community login forms **Certificate System (CRITICAL)** - includes/certificates/ - 8+ certificate classes and handlers - templates/certificates/ - Certificate reports and generation templates **Core Individual Classes (CRITICAL)** - includes/class-hvac-event-summary.php - includes/class-hvac-trainer-profile-manager.php - includes/class-hvac-master-dashboard-data.php - Plus 40+ other individual HVAC classes **Major Feature Systems (HIGH)** - includes/database/ - Training leads database tables - includes/find-trainer/ - Find trainer directory and MapGeo integration - includes/google-sheets/ - Google Sheets integration system - includes/zoho/ - Complete Zoho CRM integration - includes/communication/ - Communication templates system **Template Infrastructure** - templates/attendee/, templates/email-attendees/ - templates/event-summary/, templates/status/ - templates/template-parts/ - Shared template components **Impact:** - 70+ files added covering 10+ missing directories - Resolves ALL deployment blockers and feature breakdowns - Plugin activation should now work correctly - Multi-machine deployment fully supported 🔧 Generated with Claude Code Co-Authored-By: Ben Reed <ben@tealmaker.com>
437 lines
No EOL
14 KiB
PHP
437 lines
No EOL
14 KiB
PHP
<?php
|
|
/**
|
|
* Certificate Template Class
|
|
*
|
|
* Handles certificate template management and customization.
|
|
*
|
|
* @package HVAC_Community_Events
|
|
* @subpackage Certificates
|
|
*/
|
|
|
|
// Exit if accessed directly
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Certificate Template class.
|
|
*
|
|
* Manages certificate templates and provides preview functionality.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
class HVAC_Certificate_Template {
|
|
|
|
/**
|
|
* The single instance of the class.
|
|
*
|
|
* @var HVAC_Certificate_Template
|
|
*/
|
|
protected static $_instance = null;
|
|
|
|
/**
|
|
* Certificate settings instance.
|
|
*
|
|
* @var HVAC_Certificate_Settings
|
|
*/
|
|
protected $settings;
|
|
|
|
/**
|
|
* Main HVAC_Certificate_Template Instance.
|
|
*
|
|
* Ensures only one instance of HVAC_Certificate_Template is loaded or can be loaded.
|
|
*
|
|
* @return HVAC_Certificate_Template - Main instance.
|
|
*/
|
|
public static function instance() {
|
|
if (is_null(self::$_instance)) {
|
|
self::$_instance = new self();
|
|
}
|
|
return self::$_instance;
|
|
}
|
|
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
public function __construct() {
|
|
require_once HVAC_PLUGIN_DIR . 'includes/certificates/class-certificate-settings.php';
|
|
$this->settings = HVAC_Certificate_Settings::instance();
|
|
|
|
// Initialize hooks
|
|
$this->init_hooks();
|
|
}
|
|
|
|
/**
|
|
* Initialize hooks.
|
|
*/
|
|
protected function init_hooks() {
|
|
// Add AJAX handlers for template preview
|
|
add_action('wp_ajax_hvac_preview_certificate', array($this, 'ajax_preview_certificate'));
|
|
|
|
// Add action to register custom upload folder
|
|
add_filter('upload_dir', array($this, 'certificate_upload_dir'));
|
|
}
|
|
|
|
/**
|
|
* Modify the upload directory for certificate files.
|
|
*
|
|
* @param array $dirs Upload directory information.
|
|
*
|
|
* @return array Modified upload directory.
|
|
*/
|
|
public function certificate_upload_dir($dirs) {
|
|
// Only modify for certificate uploads
|
|
if (isset($_POST['certificate_upload']) && $_POST['certificate_upload'] === 'true') {
|
|
$certificate_dir = $this->settings->get_setting('storage_path', 'hvac-certificates');
|
|
|
|
$dirs['subdir'] = '/' . $certificate_dir;
|
|
$dirs['path'] = $dirs['basedir'] . $dirs['subdir'];
|
|
$dirs['url'] = $dirs['baseurl'] . $dirs['subdir'];
|
|
}
|
|
|
|
return $dirs;
|
|
}
|
|
|
|
/**
|
|
* Get available certificate templates.
|
|
*
|
|
* @return array List of certificate templates.
|
|
*/
|
|
public function get_templates() {
|
|
$templates = array(
|
|
'default' => array(
|
|
'name' => __('Default', 'hvac-community-events'),
|
|
'description' => __('Standard certificate template with blue accents', 'hvac-community-events'),
|
|
'background' => HVAC_PLUGIN_URL . 'assets/images/certificate-background.jpg',
|
|
'thumbnail' => HVAC_PLUGIN_URL . 'assets/images/certificate-background-thumb.jpg',
|
|
),
|
|
);
|
|
|
|
// Allow filtering of templates
|
|
return apply_filters('hvac_certificate_templates', $templates);
|
|
}
|
|
|
|
/**
|
|
* Get the current certificate template.
|
|
*
|
|
* @return array The current template settings.
|
|
*/
|
|
public function get_current_template() {
|
|
$template_id = $this->settings->get_setting('template', 'default');
|
|
$templates = $this->get_templates();
|
|
|
|
if (isset($templates[$template_id])) {
|
|
return $templates[$template_id];
|
|
}
|
|
|
|
// Fallback to default
|
|
return $templates['default'];
|
|
}
|
|
|
|
/**
|
|
* Get the path to the certificate background image.
|
|
*
|
|
* @return string|false The path to the background image or false if not found.
|
|
*/
|
|
public function get_background_path() {
|
|
// Check for custom uploaded background first
|
|
$custom_bg = $this->settings->get_setting('custom_background', '');
|
|
|
|
if (!empty($custom_bg)) {
|
|
$upload_dir = wp_upload_dir();
|
|
$file_path = $upload_dir['basedir'] . '/' . $custom_bg;
|
|
|
|
if (file_exists($file_path)) {
|
|
return $file_path;
|
|
}
|
|
}
|
|
|
|
// Fallback to default template background
|
|
$default_bg = HVAC_PLUGIN_DIR . 'assets/images/certificate-background.jpg';
|
|
|
|
if (file_exists($default_bg)) {
|
|
return $default_bg;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get the path to the certificate logo image.
|
|
*
|
|
* @return string|false The path to the logo image or false if not found.
|
|
*/
|
|
public function get_logo_path() {
|
|
// Check for custom uploaded logo first
|
|
$custom_logo = $this->settings->get_setting('custom_logo', '');
|
|
|
|
if (!empty($custom_logo)) {
|
|
$upload_dir = wp_upload_dir();
|
|
$file_path = $upload_dir['basedir'] . '/' . $custom_logo;
|
|
|
|
if (file_exists($file_path)) {
|
|
return $file_path;
|
|
}
|
|
}
|
|
|
|
// Fallback to default logo
|
|
$default_logo = HVAC_PLUGIN_DIR . 'assets/images/certificate-logo.png';
|
|
|
|
if (file_exists($default_logo)) {
|
|
return $default_logo;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Generate a preview certificate for the settings page.
|
|
*
|
|
* @return string Path to the preview certificate file.
|
|
*/
|
|
public function generate_preview() {
|
|
// Load TCPDF if not already included
|
|
if (!class_exists('TCPDF')) {
|
|
require_once HVAC_PLUGIN_DIR . 'vendor/tecnickcom/tcpdf/tcpdf.php';
|
|
}
|
|
|
|
// Create PDF document
|
|
$pdf = new TCPDF(
|
|
$this->settings->get_setting('orientation', 'L'),
|
|
'mm',
|
|
$this->settings->get_setting('paper_size', 'LETTER'),
|
|
true,
|
|
'UTF-8',
|
|
false
|
|
);
|
|
|
|
// Set document information
|
|
$pdf->SetCreator('HVAC Community Events');
|
|
$pdf->SetAuthor('Upskill HVAC');
|
|
$pdf->SetTitle('Certificate Preview');
|
|
|
|
// Set margins
|
|
$pdf->SetMargins(15, 15, 15);
|
|
|
|
// Remove default header/footer
|
|
$pdf->setPrintHeader(false);
|
|
$pdf->setPrintFooter(false);
|
|
|
|
// Set auto page breaks
|
|
$pdf->SetAutoPageBreak(false, 0);
|
|
|
|
// Add a page
|
|
$pdf->AddPage();
|
|
|
|
// Get background image if available
|
|
$bg_path = $this->get_background_path();
|
|
|
|
if ($bg_path) {
|
|
// Add background
|
|
$pdf->Image($bg_path, 0, 0, $pdf->getPageWidth(), $pdf->getPageHeight(), '', '', '', false, 300);
|
|
} else {
|
|
// Create a simple background with border
|
|
$this->render_default_background($pdf);
|
|
}
|
|
|
|
// Add logo if available
|
|
$logo_path = $this->get_logo_path();
|
|
|
|
if ($logo_path) {
|
|
$pdf->Image($logo_path, 15, 15, 40, 0, '', '', '', false, 300);
|
|
}
|
|
|
|
// Render sample content
|
|
$this->render_preview_content($pdf);
|
|
|
|
// Create upload directory if it doesn't exist
|
|
$upload_dir = wp_upload_dir();
|
|
$preview_dir = $upload_dir['basedir'] . '/hvac-certificate-previews';
|
|
|
|
if (!file_exists($preview_dir)) {
|
|
wp_mkdir_p($preview_dir);
|
|
}
|
|
|
|
// Create an htaccess file to prevent direct access
|
|
$htaccess_file = $preview_dir . '/.htaccess';
|
|
if (!file_exists($htaccess_file)) {
|
|
$htaccess_content = "# Prevent direct access to files\n";
|
|
$htaccess_content .= "<Files ~ \".*\">\n";
|
|
$htaccess_content .= " Order Allow,Deny\n";
|
|
$htaccess_content .= " Deny from all\n";
|
|
$htaccess_content .= "</Files>";
|
|
|
|
@file_put_contents($htaccess_file, $htaccess_content);
|
|
}
|
|
|
|
// Define preview file path
|
|
$preview_file = 'certificate-preview-' . time() . '.pdf';
|
|
$preview_path = $preview_dir . '/' . $preview_file;
|
|
|
|
// Save PDF
|
|
$pdf->Output($preview_path, 'F');
|
|
|
|
// Return relative path to preview file
|
|
return 'hvac-certificate-previews/' . $preview_file;
|
|
}
|
|
|
|
/**
|
|
* Render the default background for a certificate.
|
|
*
|
|
* @param TCPDF $pdf The PDF object.
|
|
*/
|
|
protected function render_default_background($pdf) {
|
|
// Get background color
|
|
$bg_color = $this->hex_to_rgb($this->settings->get_setting('bg_color', '#ffffff'));
|
|
|
|
// Fill background
|
|
$pdf->SetFillColor($bg_color[0], $bg_color[1], $bg_color[2]);
|
|
$pdf->Rect(0, 0, $pdf->getPageWidth(), $pdf->getPageHeight(), 'F');
|
|
|
|
// Add border
|
|
$border_color = $this->hex_to_rgb($this->settings->get_setting('border_color', '#0074be'));
|
|
$pdf->SetDrawColor($border_color[0], $border_color[1], $border_color[2]);
|
|
$pdf->SetLineWidth(1.5);
|
|
$pdf->Rect(5, 5, $pdf->getPageWidth() - 10, $pdf->getPageHeight() - 10, 'D');
|
|
|
|
// Add inner border
|
|
$pdf->SetDrawColor(200, 200, 200); // Light gray
|
|
$pdf->SetLineWidth(0.5);
|
|
$pdf->Rect(10, 10, $pdf->getPageWidth() - 20, $pdf->getPageHeight() - 20, 'D');
|
|
}
|
|
|
|
/**
|
|
* Render content for the preview certificate.
|
|
*
|
|
* @param TCPDF $pdf The PDF object.
|
|
*/
|
|
protected function render_preview_content($pdf) {
|
|
// Get title color
|
|
$title_color = $this->hex_to_rgb($this->settings->get_setting('title_color', '#0074be'));
|
|
|
|
// Get text color
|
|
$text_color = $this->hex_to_rgb($this->settings->get_setting('text_color', '#333333'));
|
|
|
|
// Certificate title
|
|
$pdf->SetFont('helvetica', 'B', 30);
|
|
$pdf->SetTextColor($title_color[0], $title_color[1], $title_color[2]);
|
|
$pdf->SetY(30);
|
|
$pdf->Cell(0, 20, $this->settings->get_setting('title_text', 'CERTIFICATE OF COMPLETION'), 0, 1, 'C');
|
|
|
|
// Description text
|
|
$pdf->SetFont('helvetica', '', 12);
|
|
$pdf->SetTextColor($text_color[0], $text_color[1], $text_color[2]);
|
|
$pdf->SetY(55);
|
|
$pdf->Cell(0, 10, 'This certificate is awarded to', 0, 1, 'C');
|
|
|
|
// Attendee name
|
|
$pdf->SetFont('helvetica', 'B', 24);
|
|
$pdf->SetTextColor(0, 0, 0); // Black
|
|
$pdf->Cell(0, 15, 'John Smith', 0, 1, 'C');
|
|
|
|
// Course completion text
|
|
$pdf->SetFont('helvetica', '', 12);
|
|
$pdf->SetTextColor($text_color[0], $text_color[1], $text_color[2]);
|
|
$pdf->Cell(0, 10, 'for successfully completing', 0, 1, 'C');
|
|
|
|
// Event name
|
|
$pdf->SetFont('helvetica', 'B', 18);
|
|
$pdf->SetTextColor($title_color[0], $title_color[1], $title_color[2]);
|
|
$pdf->Cell(0, 15, 'Advanced HVAC Troubleshooting Workshop', 0, 1, 'C');
|
|
|
|
// Event date
|
|
$pdf->SetFont('helvetica', '', 12);
|
|
$pdf->SetTextColor($text_color[0], $text_color[1], $text_color[2]);
|
|
$pdf->Cell(0, 10, 'on June 15, 2025', 0, 1, 'C');
|
|
|
|
// Draw a line
|
|
$pdf->SetDrawColor($title_color[0], $title_color[1], $title_color[2]);
|
|
$pdf->SetLineWidth(0.5);
|
|
$pdf->Line(70, 150, 190, 150);
|
|
|
|
// Instructor name
|
|
$pdf->SetY(155);
|
|
$pdf->SetFont('helvetica', 'B', 12);
|
|
$pdf->SetTextColor(0, 0, 0); // Black
|
|
$pdf->Cell(0, 10, 'Sarah Johnson', 0, 1, 'C');
|
|
|
|
$pdf->SetFont('helvetica', '', 10);
|
|
$pdf->SetTextColor($text_color[0], $text_color[1], $text_color[2]);
|
|
$pdf->Cell(0, 10, 'Instructor', 0, 1, 'C');
|
|
|
|
// Add organization name
|
|
$pdf->SetY(175);
|
|
$pdf->SetFont('helvetica', 'B', 10);
|
|
$pdf->SetTextColor(0, 0, 0); // Black
|
|
$pdf->Cell(0, 10, 'Upskill HVAC', 0, 1, 'C');
|
|
|
|
// Add venue info
|
|
$pdf->SetFont('helvetica', '', 10);
|
|
$pdf->SetTextColor($text_color[0], $text_color[1], $text_color[2]);
|
|
$pdf->Cell(0, 10, 'Technical Training Center, Boston', 0, 1, 'C');
|
|
|
|
// Add certificate details at the bottom
|
|
$pdf->SetFont('helvetica', '', 8);
|
|
$pdf->SetTextColor(128, 128, 128); // Light gray
|
|
$pdf->SetY(195);
|
|
$pdf->Cell(0, 10, 'Certificate #: HVAC-12345 | Issue Date: June 16, 2025', 0, 1, 'C');
|
|
}
|
|
|
|
/**
|
|
* AJAX handler for certificate preview generation.
|
|
*/
|
|
public function ajax_preview_certificate() {
|
|
// Verify nonce
|
|
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hvac_certificate_preview')) {
|
|
wp_send_json_error(array('message' => 'Security check failed'));
|
|
}
|
|
|
|
// Check user capabilities
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(array('message' => 'Insufficient permissions'));
|
|
}
|
|
|
|
// Update settings first
|
|
if (isset($_POST['settings']) && is_array($_POST['settings'])) {
|
|
foreach ($_POST['settings'] as $key => $value) {
|
|
$this->settings->update_setting($key, sanitize_text_field($value));
|
|
}
|
|
}
|
|
|
|
// Generate preview
|
|
$preview_path = $this->generate_preview();
|
|
|
|
// Get full URL to preview
|
|
$upload_dir = wp_upload_dir();
|
|
$preview_url = $upload_dir['baseurl'] . '/' . $preview_path;
|
|
|
|
wp_send_json_success(array(
|
|
'preview_url' => $preview_url,
|
|
'message' => 'Preview generated successfully'
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Convert hexadecimal color to RGB.
|
|
*
|
|
* @param string $hex The hexadecimal color code.
|
|
*
|
|
* @return array RGB values.
|
|
*/
|
|
protected function hex_to_rgb($hex) {
|
|
// Remove # if present
|
|
$hex = ltrim($hex, '#');
|
|
|
|
if (strlen($hex) == 3) {
|
|
$r = hexdec(substr($hex, 0, 1) . substr($hex, 0, 1));
|
|
$g = hexdec(substr($hex, 1, 1) . substr($hex, 1, 1));
|
|
$b = hexdec(substr($hex, 2, 1) . substr($hex, 2, 1));
|
|
} else {
|
|
$r = hexdec(substr($hex, 0, 2));
|
|
$g = hexdec(substr($hex, 2, 2));
|
|
$b = hexdec(substr($hex, 4, 2));
|
|
}
|
|
|
|
return array($r, $g, $b);
|
|
}
|
|
} |