Files
SIGE-WEB-snapshot/wp-content/plugins/sige-events/sige_events.php.backup

9060 lines
409 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Plugin Name: Sige Events
* Plugin URI: https://www.sige.ita.br
* Version: 0.0.1
*/
// check if file is available by user accessing it, otherwise kill process
if (!defined('ABSPATH')) {
die;
}
// Enqueue the HTML5 QR Code library
function sige_enqueue_qrcode_library()
{
wp_enqueue_script('html5-qrcode', plugin_dir_url(__FILE__) . 'js/html5-qrcode.min.js', array(), '2.3.8', true);
}
add_action('admin_enqueue_scripts', 'sige_enqueue_qrcode_library');
function sige_enqueue_tinymce()
{
wp_enqueue_script('tinymce');
wp_enqueue_script('wp-tinymce');
}
add_action('admin_enqueue_scripts', 'sige_enqueue_tinymce');
register_activation_hook(__FILE__, 'sige_events_install');
register_deactivation_hook(__FILE__, 'sige_events_uninstall');
function sige_events_install()
{
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// SQL to create necessary tables
$sql = "
CREATE TABLE {$wpdb->prefix}sige_place (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
place TINYTEXT NOT NULL,
comments TEXT NOT NULL,
PRIMARY KEY (id)
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_speakers (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
research_degree VARCHAR(50) NOT NULL,
full_name TINYTEXT NOT NULL,
email VARCHAR(100) NOT NULL,
institution TINYTEXT NOT NULL,
PRIMARY KEY (id)
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_event_names (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
acronym VARCHAR(50) NOT NULL,
name TINYTEXT NOT NULL,
responsible_for TINYTEXT NOT NULL,
PRIMARY KEY (id)
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_meta_keys (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
meta_key VARCHAR(255) NOT NULL,
status TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY meta_key (meta_key)
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_activities (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
description TEXT,
start_date DATE,
start_time TIME,
end_date DATE,
end_time TIME,
type VARCHAR(50) NOT NULL,
modality VARCHAR(50) NOT NULL,
status VARCHAR(50) NOT NULL,
curriculum TEXT,
comment TEXT,
place_id MEDIUMINT(9),
speaker_id MEDIUMINT(9),
event_name_id MEDIUMINT(9) NOT NULL,
security_credential VARCHAR(20) NOT NULL,
chair TINYTEXT,
target_audience VARCHAR(50),
attendance_control ENUM('yes', 'no') NOT NULL DEFAULT 'no',
slots INT(5) NULL,
activity_matching_key INT(5) NULL,
PRIMARY KEY (id),
KEY place_id (place_id),
KEY speaker_id (speaker_id),
KEY event_name_id (event_name_id),
CONSTRAINT fk_place FOREIGN KEY (place_id) REFERENCES {$wpdb->prefix}sige_place(id) ON DELETE CASCADE,
CONSTRAINT fk_speaker FOREIGN KEY (speaker_id) REFERENCES {$wpdb->prefix}sige_speakers(id) ON DELETE CASCADE,
CONSTRAINT fk_event_name FOREIGN KEY (event_name_id) REFERENCES {$wpdb->prefix}sige_event_names(id) ON DELETE SET NULL
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_enrollments (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
activity_id MEDIUMINT(9) NOT NULL,
user_id BIGINT(20) UNSIGNED NOT NULL,
enrollment_date DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
status VARCHAR(50) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (activity_id) REFERENCES {$wpdb->prefix}sige_activities(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES {$wpdb->prefix}users(ID) ON DELETE CASCADE
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_cancellation_record (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
activity_id MEDIUMINT(9) NOT NULL,
user_id BIGINT(20) UNSIGNED NOT NULL,
date_of_cancelation DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
reasons VARCHAR(50) NULL,
PRIMARY KEY (id),
FOREIGN KEY (activity_id) REFERENCES {$wpdb->prefix}sige_activities(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES {$wpdb->prefix}users(ID) ON DELETE CASCADE
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_activity_notices (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
type VARCHAR(50) NOT NULL,
notice TEXT NOT NULL,
PRIMARY KEY (id)
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_display_options (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
field_name VARCHAR(50) NOT NULL,
activity_type VARCHAR(50) NOT NULL,
display TINYINT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (id)
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_enrollment_button_style (
button_action VARCHAR(50) NOT NULL,
button_label VARCHAR(50) NOT NULL,
background_color VARCHAR(7) NOT NULL,
font_size VARCHAR(10) NOT NULL,
font_family VARCHAR(100) NOT NULL,
font_weight VARCHAR(10) NOT NULL,
PRIMARY KEY (button_action)
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_enrollment_status_style (
status_action VARCHAR(50) NOT NULL,
status_label VARCHAR(50) NOT NULL,
font_color VARCHAR(7) NOT NULL,
font_size VARCHAR(10) NOT NULL,
font_family VARCHAR(100) NOT NULL,
font_weight VARCHAR(10) NOT NULL,
PRIMARY KEY (status_action)
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_email_messages (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
email_sender VARCHAR(100) NOT NULL,
email_subject VARCHAR(255) NOT NULL,
email_message TEXT NOT NULL,
status_action VARCHAR(50) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (status_action) REFERENCES {$wpdb->prefix}sige_enrollment_status_style(status_action) ON DELETE CASCADE
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_enrollment_attendance_control (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
enrollment_id MEDIUMINT(9) NOT NULL,
attended ENUM('yes', 'no') DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (enrollment_id) REFERENCES {$wpdb->prefix}sige_enrollments(id) ON DELETE CASCADE
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_enrollment_online_attendance_control (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
enrollment_id MEDIUMINT(9) NOT NULL,
attended ENUM('yes', 'no') DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (enrollment_id) REFERENCES {$wpdb->prefix}sige_enrollments(id) ON DELETE CASCADE
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_confidentiality_message (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
information_type VARCHAR(255) NOT NULL,
message TEXT NULL,
PRIMARY KEY (id)
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_confidentiality_user_option (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
user_id BIGINT(20) UNSIGNED NOT NULL,
year INT(4) NOT NULL,
confidentiality ENUM('yes', 'no') DEFAULT NULL,
sharing_information ENUM('yes', 'no') DEFAULT NULL,
PRIMARY KEY (id),
KEY user_id (user_id),
CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES {$wpdb->prefix}users(ID) ON DELETE CASCADE
) $charset_collate;
CREATE TABLE {$wpdb->prefix}sige_attendance_email_messages (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
email_sender VARCHAR(100) NOT NULL,
email_subject VARCHAR(255) NOT NULL,
email_message TEXT NOT NULL,
status_action VARCHAR(50) NOT NULL,
PRIMARY KEY (id)
) $charset_collate;
";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// Insert default display options for each activity type
$default_options = [
'Notices',
'Speaker',
'Curriculum Vitae',
'Date',
'Hour',
'Place',
'Modality',
'Enrollment Status',
'Comment',
'Security Credential',
'Target Audience',
'Chair',
'Slots'
];
$activity_types = [
'Main Event',
'Presentation',
'Short-course',
'Lecture',
'Workshop',
'Others'
];
foreach ($default_options as $option) {
foreach ($activity_types as $activity_type) {
if (!$wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$wpdb->prefix}sige_display_options WHERE field_name = %s AND activity_type = %s", $option, $activity_type))) {
$wpdb->insert("{$wpdb->prefix}sige_display_options", ['field_name' => $option, 'activity_type' => $activity_type, 'display' => 1]);
}
}
}
// Insert default button styles
$default_styles = [
['button_action' => 'request_enrollment', 'button_label' => 'Request Enrollment', 'background_color' => '#0073aa', 'font_size' => '14px', 'font_family' => 'Arial, sans-serif', 'font_weight' => 'normal'],
['button_action' => 'cancel_enrollment', 'button_label' => 'Cancel Enrollment', 'background_color' => '#ac1226', 'font_size' => '14px', 'font_family' => 'Arial, sans-serif', 'font_weight' => 'normal']
];
foreach ($default_styles as $style) {
$wpdb->insert("{$wpdb->prefix}sige_enrollment_button_style", $style);
}
// Insert default status styles
$default_status_styles = [
['status_action' => 'Not Requested', 'status_label' => 'Not Requested', 'font_color' => '#000000', 'font_size' => '14px', 'font_family' => 'Arial, sans-serif', 'font_weight' => 'normal'],
['status_action' => 'Enrollment Canceled by User', 'status_label' => 'Enrollment Canceled by User', 'font_color' => '#ac1226', 'font_size' => '14px', 'font_family' => 'Arial, sans-serif', 'font_weight' => 'normal'],
['status_action' => 'Under Analysis', 'status_label' => 'Under Analysis', 'font_color' => '#0073aa', 'font_size' => '14px', 'font_family' => 'Arial, sans-serif', 'font_weight' => 'normal'],
['status_action' => 'Approved', 'status_label' => 'Approved', 'font_color' => '#008000', 'font_size' => '14px', 'font_family' => 'Arial, sans-serif', 'font_weight' => 'normal'],
['status_action' => 'Waiting List', 'status_label' => 'Waiting List', 'font_color' => '#CC9900', 'font_size' => '14px', 'font_family' => 'Arial, sans-serif', 'font_weight' => 'normal'],
['status_action' => 'Not Approved', 'status_label' => 'Not Approved', 'font_color' => '#46384C', 'font_size' => '14px', 'font_family' => 'Arial, sans-serif', 'font_weight' => 'normal']
];
foreach ($default_status_styles as $style) {
$wpdb->insert("{$wpdb->prefix}sige_enrollment_status_style", $style);
}
// Insert default confidentiality messages
$default_confidentiality_messages = [
['information_type' => 'Credential', 'message' => 'The information provided by the user will be used to verify the user\'s credentials.'],
['information_type' => 'Sharing Information', 'message' => 'The information provided by the user will be shared with ours sponsors.']
];
foreach ($default_confidentiality_messages as $message) {
$wpdb->insert("{$wpdb->prefix}sige_confidentiality_message", $message);
}
// Insert default email messages
$default_email_messages = [
['email_sender' => get_bloginfo('admin_email'), 'email_subject' => 'Not Requested', 'email_message' => 'Your enrollment status is Not Requested.', 'status_action' => 'Not Requested'],
['email_sender' => get_bloginfo('admin_email'), 'email_subject' => 'Enrollment Canceled by User', 'email_message' => 'Your enrollment has been canceled by user.', 'status_action' => 'Enrollment Canceled by User'],
['email_sender' => get_bloginfo('admin_email'), 'email_subject' => 'Under Analysis', 'email_message' => 'Your enrollment is under analysis.', 'status_action' => 'Under Analysis'],
['email_sender' => get_bloginfo('admin_email'), 'email_subject' => 'Approved', 'email_message' => 'Your enrollment has been approved.', 'status_action' => 'Approved'],
['email_sender' => get_bloginfo('admin_email'), 'email_subject' => 'Waiting List', 'email_message' => 'You have been placed on the waiting list.', 'status_action' => 'Waiting List'],
['email_sender' => get_bloginfo('admin_email'), 'email_subject' => 'Not Approved', 'email_message' => 'Your enrollment has not been approved.', 'status_action' => 'Not Approved']
];
foreach ($default_email_messages as $message) {
$wpdb->insert("{$wpdb->prefix}sige_email_messages", $message);
}
// Insert default email messages in sige_attendance_email_messages
$default_attendance_email_messages = [
['email_sender' => get_bloginfo('admin_email'), 'email_subject' => 'Attendance Counted', 'email_message' => 'Your attendance at the event was counted.', 'status_action' => 'yes'],
['email_sender' => get_bloginfo('admin_email'), 'email_subject' => 'Attendance Not Counted', 'email_message' => 'Your attendance at the event was not counted.', 'status_action' => 'no']
];
foreach ($default_attendance_email_messages as $message) {
$wpdb->insert("{$wpdb->prefix}sige_attendance_email_messages", $message);
}
// Ensure wp_usermeta has specified meta_keys
$required_meta_keys = [
'forca',
'full_name',
'posto',
'militar',
'instituição',
'nacionalidade',
'efetivo_dcta',
'cidade',
'estado',
'areaatividadeprincipal',
'setordeatuacao',
'cargofuncao',
'ehativa',
'circulo_hierarquico',
'telefone',
'passaporte',
'pais',
'formacao_academica',
'regiao_do_brasil',
'genero'
];
foreach ($required_meta_keys as $meta_key) {
if (!$wpdb->get_var($wpdb->prepare("SELECT meta_key FROM {$wpdb->prefix}usermeta WHERE meta_key = %s", $meta_key))) {
$wpdb->insert("{$wpdb->prefix}usermeta", ['meta_key' => $meta_key, 'meta_value' => '']);
}
}
// Table to store participants feedback
$table_name = $wpdb->prefix . 'sige_feedback';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
participant_name varchar(100),
institution varchar(100),
participant_type varchar(50) NOT NULL,
positive_highlight text,
improvement_aspect text,
suggestions text,
future_interest varchar(3) NOT NULL,
submission_date datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
// Check if the JSON file with saved data exists and restore data if available
$json_file_path = plugin_dir_path(__FILE__) . 'sige_events_data.json';
if (file_exists($json_file_path)) {
$json_data = json_decode(file_get_contents($json_file_path), true);
if ($json_data) {
$tables_to_replace = [
'sige_enrollment_status_style',
'sige_email_messages',
'sige_enrollment_button_style',
'sige_display_options',
'sige_activities',
'sige_enrollments',
'sige_cancellation_record',
'sige_enrollment_attendance_control',
'sige_enrollment_online_attendance_control',
'sige_confidentiality_user_option',
'sige_confidentiality_message',
'sige_attendance_email_messages'
];
// Restore the non-replacement tables first
foreach ($json_data as $table => $records) {
if (!in_array($table, $tables_to_replace)) {
foreach ($records as $record) {
$wpdb->insert("{$wpdb->prefix}$table", $record);
}
}
}
// Restore the replacement tables last
foreach ($tables_to_replace as $table) {
if (isset($json_data[$table])) {
foreach ($json_data[$table] as $record) {
$wpdb->replace("{$wpdb->prefix}$table", $record);
}
}
}
}
}
}
function sige_events_uninstall()
{
global $wpdb;
// Export data to JSON file before dropping tables
$tables = [
'sige_activity_notices',
'sige_display_options',
'sige_enrollment_button_style',
'sige_meta_keys',
'sige_email_messages',
'sige_enrollment_status_style',
'sige_event_names',
'sige_place',
'sige_speakers',
'sige_activities',
'sige_enrollments',
'sige_cancellation_record',
'sige_enrollment_attendance_control',
'sige_enrollment_online_attendance_control',
'sige_confidentiality_message',
'sige_confidentiality_user_option',
'sige_attendance_email_messages'
];
$data = [];
// Save non-replacement tables first
foreach ($tables as $table) {
if (!in_array($table, ['sige_activities', 'sige_enrollments', 'sige_enrollment_attendance_control', 'sige_cancellation_record', 'sige_confidentiality_user_option'])) {
$data[$table] = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}$table", ARRAY_A);
}
}
// Save replacement tables last
foreach (['sige_activities', 'sige_enrollments', 'sige_enrollment_attendance_control', 'sige_cancellation_record', 'sige_confidentiality_user_option'] as $table) {
$data[$table] = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}$table", ARRAY_A);
}
$json_file_path = plugin_dir_path(__FILE__) . 'sige_events_data.json';
file_put_contents($json_file_path, json_encode($data));
// Drop the tables
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_activity_notices");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_display_options");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_enrollment_button_style");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_meta_keys");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_email_messages");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_enrollment_status_style");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_enrollment_attendance_control");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_enrollment_online_attendance_control");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_enrollments");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_cancellation_record");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_activities");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_event_names");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_place");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_speakers");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_confidentiality_message");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_confidentiality_user_option");
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}sige_attendance_email_messages");
}
function export_sige_events_data()
{
global $wpdb;
$tables = [
'sige_activity_notices',
'sige_apoio',
'sige_display_options',
'sige_enrollment_button_style',
'sige_meta_keys',
'sige_email_messages',
'sige_enrollment_status_style',
'sige_event_names',
'sige_place',
'sige_speakers',
'sige_activities',
'sige_enrollments',
'sige_cancellation_record',
'sige_enrollment_attendance_control',
'sige_enrollment_online_attendance_control',
'sige_confidentiality_message',
'sige_confidentiality_user_option',
'sige_attendance_email_messages'
];
$data = [];
foreach ($tables as $table) {
if (!in_array($table, ['sige_activities', 'sige_enrollments', 'sige_enrollment_attendance_control', 'sige_cancellation_record', 'sige_confidentiality_user_option'])) {
$data[$table] = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}$table", ARRAY_A);
}
}
foreach (['sige_activities', 'sige_enrollments', 'sige_enrollment_attendance_control', 'sige_cancellation_record', 'sige_confidentiality_user_option'] as $table) {
$data[$table] = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}$table", ARRAY_A);
}
$current_datetime = new DateTime();
$formatted_datetime = $current_datetime->format('d_m_Y_H_i_s');
$json_file_name = 'sige_events_data_' . $formatted_datetime . '.json';
$json_file_path = plugin_dir_path(__FILE__) . $json_file_name;
file_put_contents($json_file_path, json_encode($data));
}
//add_action('export_sige_events_data_hook', 'export_sige_events_data');
/*
function schedule_daily_export()
{
if (!wp_next_scheduled('export_sige_events_data_hook')) {
$timestamp = strtotime('04:05:00'); // 1:00 AM today
if ($timestamp < time()) {
$timestamp = strtotime('04:05:00 +1 day'); // 1:00 AM tomorrow
}
wp_schedule_event($timestamp, 'daily', 'export_sige_events_data_hook');
}
}
add_action('wp', 'schedule_daily_export');
*/
function unschedule_daily_export()
{
$timestamp = wp_next_scheduled('export_sige_events_data_hook');
if ($timestamp) {
wp_unschedule_event($timestamp, 'export_sige_events_data_hook');
}
}
register_deactivation_hook(__FILE__, 'unschedule_daily_export');
add_action('admin_menu', 'addAdminPageContent');
function addAdminPageContent()
{
add_menu_page('SIGE Events', 'SIGE Events', 'manage_options', 'sige-events', 'SigeEventmenuPage', 'dashicons-welcome-learn-more');
add_submenu_page('sige-events', 'Dashboard', 'Dashboard', 'manage_options', 'dashboard-submenu', 'dashboardSubmenuPage');
add_submenu_page('sige-events', 'Create Activities', 'Create Activities', 'manage_options', 'create-activities-submenu', 'createActivitiesSubmenuPage');
add_submenu_page('sige-events', 'Occasional Emails', 'Occasional Emails', 'manage_options', 'occasional-emails-submenu', 'SendOccasionalEmailsSubmenuPage');
add_submenu_page('sige-events', 'Enrollment Control', 'Enrollment Control', 'manage_options', 'enrollment-submenu', 'enrollmentSubmenuPage');
add_submenu_page('sige-events', 'Attendance Control - Hybrid or In-person', 'Attendance Control (Hybrid or In-person)', 'manage_options', 'attendance-control-not-online-submenu', 'attendanceControlNotOnlineSubmenuPage');
add_submenu_page('sige-events', 'Attendance Control - Online', 'Attendance Control (Online)', 'manage_options', 'attendance-control-online-submenu', 'attendanceControlOnlineSubmenuPage');
add_submenu_page('sige-events', 'Settings', 'Settings', 'manage_options', 'settings-submenu', 'settingsSubmenuPage');
}
function SigeEventmenuPage()
{
echo '<div class="wrap">';
echo '<h2>Welcome to Sige Events</h2>';
// Main Purpose Section
echo '<div class="sige-box">';
echo '<h3>Main Purpose</h3>';
echo '<p>Sige Events is a comprehensive plugin designed to facilitate the management of enrollments for short courses and events. It offers a user-friendly interface and a variety of features that help administrators efficiently handle all aspects of event management.</p>';
echo '<p><strong>Key Features:</strong></p>';
echo '<ul>';
echo '<li><strong>Event Creation and Management:</strong> Easily create and manage different types of activities, including presentations, short courses, lectures, workshops, and more.</li>';
echo '<li><strong>Enrollment Handling:</strong> Manage enrollments, track participant status, and handle approvals and cancellations.</li>';
echo '<li><strong>Email Notifications:</strong> Set up and customize email notifications to keep participants informed about their enrollment status and event updates.</li>';
echo '<li><strong>Data Export:</strong> Export activity and enrollment data to CSV for reporting and analysis purposes.</li>';
echo '<li><strong>Customizable Display Options:</strong> Choose which fields to display on the frontend and customize notices for different types of activities.</li>';
echo '</ul>';
echo '<p>This plugin is an ideal solution for institutions, organizations, or individuals who need a reliable and efficient system to manage their educational or informational events.</p>';
echo '</div>'; // End Main Purpose Section
// Development Team Section
echo '<div class="sige-box">';
echo '<h3>Development Team</h3>';
echo '<p>The development of Sige Events was a collaborative effort involving the following contributors:</p>';
echo '<ul>';
echo '<li><strong>Leandro Geraldo da Costa:</strong> Project Lead and Developer.</li>';
echo '<li><strong>Caio:</strong> Frontend Specialist.</li>';
echo '<li><strong>Munhoz:</strong> Backend Developer.</li>';
echo '<li><strong>Thales</strong> </li>';
echo '</ul>';
echo '</div>'; // End Development Team Section
// Shortcode Usage Section
echo '<div class="sige-box">';
echo '<h3>Shortcode Usage</h3>';
echo '<p>To display the open activities on any page or post, use the following shortcode:</p>';
echo '<code>[open_activities]</code>';
echo '<p>To display the enrollment Controls on any page or post, use the following shortcode:</p>';
echo '<code>[enrollments]</code>';
echo '<p>To display to Security and Defense Commission the enrollment Controls for SIGE events on any page or post, use the following shortcode:</p>';
echo '<code>[enrollmentsSecurityAndDefenseSIGE]</code>';
echo '<p>To display to Security and Defense Commission the enrollment Controls for SERFA events on any page or post, use the following shortcode:</p>';
echo '<code>[enrollmentsSecurityAndDefenseSERFA]</code>';
echo '<p>To display to Security and Defense Commission the enrollment Controls for ALL events on any page or post, use the following shortcode:</p>';
echo '<code>[enrollmentsSecurityAndDefense]</code>';
echo '<p>To manage attendance control on any page or post, use the following shortcode:</p>';
echo '<code>[frontend_attendance_control]</code>';
echo '<p>To generate the QR CODE for user purpose, use the following shortcode:</p>';
echo '<code>[userbadge_qr_code]</code>';
echo '<p>To generate the dashboard for management purpose, use the following shortcode:</p>';
echo '<code>[Dashboard]</code>';
echo '<p>To manage attendance control automatic on any page or post, use the following shortcode</p>';
echo '<code>[frontend_attendance_control_automatic]</code>';
echo '<p>To manage label edition for badges on any page or post, use the following shortcode</p>';
echo '<code>[generate_attendance_pdf]</code>';
echo '</div>'; // End Shortcode Usage Section
// Available Functions Section
echo '<div class="sige-box">';
echo '<h3>Available Functions and Their Purposes</h3>';
echo '<ul>';
echo '<li><strong>sige_events_install:</strong> Function to create the necessary database tables and insert default options when the plugin is activated.</li>';
echo '<li><strong>sige_events_uninstall:</strong> Function to drop the database tables when the plugin is deactivated.</li>';
echo '<li><strong>export_sige_events_data:</strong> Function to export the database tables in Json in certain amount of time automatically.</li>';
echo '<li><strong>addAdminPageContent:</strong> Function to add the admin menu and submenu pages for managing the plugin.</li>';
echo '<li><strong>SigeEventmenuPage:</strong> Function to display the main content of the SIGE Events submenu page.</li>';
echo '<li><strong>dashboardSubmenuPage:</strong> Function to display the content of the Dashboard submenu page.</li>';
echo '<li><strong>createActivitiesSubmenuPage:</strong> Function to display and manage available activities in the Available Activities submenu page.</li>';
echo '<li><strong>enrollmentSubmenuPage:</strong> Function to display and manage enrollments in the Enrollments submenu page.</li>';
echo '<li><strong>emailSettingsSubmenuPage:</strong> Function to manage email settings in the Email Settings submenu page.</li>';
echo '<li><strong>attendanceControlNotOnlineSubmenuPage:</strong> Function to manage attendance control in the Attendance Control submenu page.</li>';
echo '<li><strong>export_activities_to_csv:</strong> Function to export activities to a CSV file.</li>';
echo '<li><strong>enqueue_datatables_assets_admin:</strong> Function to enqueue DataTables assets for enhanced table interactions in the admin area.</li>';
echo '<li><strong>frontendDisplayOpenActivities:</strong> Shortcode function to display open activities on the frontend. Usage: <code>[open_activities]</code></li>';
echo '<li><strong>frontendEnrollmentControl:</strong> Function to display enrollments on the frontend. Usage: <code>[enrollments]</code></li>';
echo '<li><strong>frontendEnrollmentControlSecurityAndDefense:</strong> Function To display to Security and Defense Commission the enrollment Controls for ALL events on any page or post. Usage: <code>[enrollmentsSecurityAndDefenseSIGE]</code></li>';
echo '<li><strong>frontendEnrollmentControlSecurityAndDefenseSIGE:</strong> Function to display enrollments on the frontend. Usage: <code>[enrollmentsSecurityAndDefenseSIGE]</code></li>';
echo '<li><strong>frontendEnrollmentControlSecurityAndDefenseSERFA:</strong> Function to display enrollments on the frontend. Usage: <code>[enrollmentsSecurityAndDefenseSERFA]</code></li>';
echo '<li><strong>frontendAttendanceControl:</strong> Function to display attendance control on the frontend. Usage: <code>[frontend_attendance_control]</code></li>';
echo '<li><strong>frontendAttendanceControlAutomatic:</strong> Function to display attendance control automatic on the frontend. Usage: <code>[frontend_attendance_control_automatic]</code></li>';
echo '<li><strong>generate_attendance_pdf:</strong> Function to generate the user label for badges. Usage: <code>[generate_attendance_pdf]</code></li>';
echo '<li><strong>send_email_notification:</strong> Function used to send email to user whenever some enrollment status was changed</li>';
echo '<li><strong>displayMainOptions:</strong> Function to display the Main Options tab in the Settings submenu page.</li>';
echo '<li><strong>displayDashboardOptions:</strong> Function to display the Dashboard Options tab in the Settings submenu page.</li>';
echo '<li><strong>displayActivityOptions:</strong> Function to display and manage activity-related options in the Activity Options tab in the Settings submenu page.</li>';
echo '<li><strong>displayEnrollmentOptions:</strong> Function to display and manage enrollment-related options in the Enrollment Options tab in the Settings submenu page.</li>';
echo '<li><strong>displayEmailOptions:</strong> Function to display the Email Options tab in the Settings submenu page.</li>';
echo '<li><strong>displayMiscellaneous:</strong> Function to display the Miscellaneous tab in the Settings submenu page.</li>';
echo '<li><strong>settingsSubmenuPage:</strong> Function to display the content of the Settings submenu page and handle tab navigation.</li>';
echo '</ul>';
echo '</div>'; // End Available Functions Section
echo '</div>';
}
// Add this CSS to your plugin to apply the styles
function sige_events_admin_styles()
{
echo '<style>
.sige-box {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
background: #f9f9f9;
border: 1px solid #ccc;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
}
</style>';
}
add_action('admin_head', 'sige_events_admin_styles');
function dashboardSubmenuPage()
{
global $wpdb;
// Fetch data for the first graph (unique users by region)
$query1 = "
SELECT um.meta_value as regiao_do_brasil, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'regiao_do_brasil'
GROUP BY um.meta_value
";
$results1 = $wpdb->get_results($query1, ARRAY_A);
// Prepare data for the first chart
$regions = ['Norte', 'Nordeste', 'Centro-Oeste', 'Sudeste', 'Sul'];
$data1 = array_fill_keys($regions, 0);
foreach ($results1 as $row) {
if (in_array($row['regiao_do_brasil'], $regions)) {
$data1[$row['regiao_do_brasil']] = (int) $row['count'];
}
}
// Convert data to JSON for Chart.js
$labels1 = json_encode(array_keys($data1));
$counts1 = json_encode(array_values($data1));
// Fetch data for the second graph (formacao_academica by region)
$query2 = "
SELECT
fa.meta_value as formacao_academica,
rb.meta_value as regiao_do_brasil,
COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta fa ON e.user_id = fa.user_id AND fa.meta_key = 'formacao_academica'
LEFT JOIN {$wpdb->prefix}usermeta rb ON e.user_id = rb.user_id AND rb.meta_key = 'regiao_do_brasil'
GROUP BY fa.meta_value, rb.meta_value
";
$results2 = $wpdb->get_results($query2, ARRAY_A);
// Prepare data for the second chart
$formacoes = ['Aluno de Graduação', 'Aluno de Pós-Graduação', 'Professor da Educação Básica', 'Professor/Pesquisador', 'Outros'];
$regions = ['Norte', 'Nordeste', 'Centro-Oeste', 'Sudeste', 'Sul'];
$data2 = [];
foreach ($formacoes as $formacao) {
$data2[$formacao] = array_fill_keys($regions, 0);
}
foreach ($results2 as $row) {
if (in_array($row['formacao_academica'], $formacoes)) {
$region = $row['regiao_do_brasil'];
if (array_key_exists($region, $data2[$row['formacao_academica']])) {
$data2[$row['formacao_academica']][$region] += (int) $row['count'];
}
}
}
// Convert data to JSON for Chart.js
$labels2 = json_encode(array_keys($data2['Aluno de Graduação']));
$datasets2 = [];
foreach ($data2 as $formacao => $counts) {
$datasets2[] = [
'label' => $formacao,
'data' => array_values($counts),
'backgroundColor' => 'rgba(' . rand(0, 255) . ', ' . rand(0, 255) . ', ' . rand(0, 255) . ', 0.2)',
'borderColor' => 'rgba(' . rand(0, 255) . ', ' . rand(0, 255) . ', ' . rand(0, 255) . ', 1)',
'borderWidth' => 1
];
}
$datasets2 = json_encode($datasets2);
// Fetch data for the third graph (In-person vs Online Enrollment)
$query3_in_person = "
SELECT DISTINCT e.user_id
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE a.modality IN ('In-person', 'Hybrid')
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User','Waiting List','Under Analysis')
";
$query3_online = "
SELECT COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE e.user_id NOT IN (
SELECT DISTINCT e.user_id
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE a.modality IN ('In-person', 'Hybrid')
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User','Waiting List','Under Analysis')
)
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User', 'Waiting List','Under Analysis')
";
$in_person_users = $wpdb->get_col($query3_in_person);
$online_count = $wpdb->get_var($query3_online);
// Prepare data for the third chart
$in_person_count = count($in_person_users);
$labels3 = json_encode(['In-person Enrollment', 'Online Enrollment']);
$counts3 = json_encode([$in_person_count, (int) $online_count]);
// Fetch data for the fourth graph (circulo_hierárquico distribution for In-person users)
$query4 = "
SELECT um.meta_value as circulo_hierarquico, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'circulo_hierárquico'
WHERE e.user_id IN (" . implode(',', array_map('intval', $in_person_users)) . ")
GROUP BY um.meta_value
";
$results4 = $wpdb->get_results($query4, ARRAY_A);
// Prepare data for the fourth chart
$circulos = ['Praça', 'Graduado', 'Praça Especial', 'Oficial Subalterno', 'Oficial Intermediário', 'Oficial Superior', 'Oficial General'];
$data4 = array_fill_keys($circulos, 0);
foreach ($results4 as $row) {
if (in_array($row['circulo_hierarquico'], $circulos)) {
$data4[$row['circulo_hierarquico']] = (int) $row['count'];
}
}
// Convert data to JSON for Chart.js
$labels4 = json_encode(array_keys($data4));
$counts4 = json_encode(array_values($data4));
// Fetch data for the fifth graph (militar In-person vs Online Enrollment)
$query5_in_person = "
SELECT DISTINCT e.user_id
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'militar'
WHERE a.modality IN ('In-person', 'Hybrid')
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User','Waiting List','Under Analysis')
AND um.meta_value = 'Sim'
";
$query5_online = "
SELECT COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'militar'
WHERE e.user_id NOT IN (
SELECT DISTINCT e.user_id
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'militar'
WHERE a.modality IN ('In-person', 'Hybrid')
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User','Waiting List','Under Analysis')
AND um.meta_value = 'Sim'
)
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User','Waiting List','Under Analysis')
AND um.meta_value = 'Sim'
";
$in_person_users_militar = $wpdb->get_col($query5_in_person);
$online_count_militar = $wpdb->get_var($query5_online);
// Prepare data for the fifth chart
$in_person_count_militar = count($in_person_users_militar);
$labels5 = json_encode(['In-person Enrollment Militar', 'Online Enrollment Militar']);
$counts5 = json_encode([$in_person_count_militar, (int) $online_count_militar]);
// Fetch data for the sixth graph (non-militar In-person vs Online Enrollment)
$query6_in_person = "
SELECT DISTINCT e.user_id
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'militar'
WHERE a.modality IN ('In-person', 'Hybrid')
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User','Waiting List','Under Analysis')
AND um.meta_value = 'Não'
";
$query6_online = "
SELECT COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'militar'
WHERE e.user_id NOT IN (
SELECT DISTINCT e.user_id
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'militar'
WHERE a.modality IN ('In-person', 'Hybrid')
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User','Waiting List','Under Analysis')
AND um.meta_value = 'Não'
)
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User','Waiting List','Under Analysis')
AND um.meta_value = 'Não'
";
$in_person_users_non_militar = $wpdb->get_col($query6_in_person);
$online_count_non_militar = $wpdb->get_var($query6_online);
// Prepare data for the sixth chart
$in_person_count_non_militar = count($in_person_users_non_militar);
$labels6 = json_encode(['In-person Enrollment Non-Militar', 'Online Enrollment Non-Militar']);
$counts6 = json_encode([$in_person_count_non_militar, (int) $online_count_non_militar]);
// Fetch data for the seventh graph (Brasileiros vs Estrangeiro by distinct users)
$query7 = "
SELECT um.meta_value as nacionalidade, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'nacionalidade'
WHERE e.status NOT IN ('Not Approved', 'Enrollment Canceled by User')
GROUP BY um.meta_value
";
$results7 = $wpdb->get_results($query7, ARRAY_A);
// Prepare data for the seventh chart
$nationalities = ['Brasileiro', 'Estrangeiro'];
$data7 = array_fill_keys($nationalities, 0);
foreach ($results7 as $row) {
if (in_array($row['nacionalidade'], $nationalities)) {
$data7[$row['nacionalidade']] = (int) $row['count'];
}
}
// Convert data to JSON for Chart.js
$labels7 = json_encode(array_keys($data7));
$counts7 = json_encode(array_values($data7));
// Fetch data for the eighth graph (Gender distribution by distinct users)
$query8 = "
SELECT um.meta_value as genero, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'genero'
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE a.modality IN ('In-person', 'Hybrid','Online')
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User')
GROUP BY um.meta_value
";
$results8 = $wpdb->get_results($query8, ARRAY_A);
// Prepare data for the eighth chart
$genders = ['Feminino', 'Masculino'];
$data8 = array_fill_keys($genders, 0);
foreach ($results8 as $row) {
if (in_array($row['genero'], $genders)) {
$data8[$row['genero']] = (int) $row['count'];
}
}
// Convert data to JSON for Chart.js
$labels8 = json_encode(array_keys($data8));
$counts8 = json_encode(array_values($data8));
// Fetch data for the ninth graph (Gender distribution of military users by distinct users)
$query9 = "
SELECT um1.meta_value as genero, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'genero'
LEFT JOIN {$wpdb->prefix}usermeta um2 ON e.user_id = um2.user_id AND um2.meta_key = 'militar'
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE a.modality IN ('In-person', 'Hybrid','Online')
AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User')
AND um2.meta_value = 'Sim'
GROUP BY um1.meta_value
";
$results9 = $wpdb->get_results($query9, ARRAY_A);
// Prepare data for the ninth chart
$genders_military = ['Feminino', 'Masculino'];
$data9 = array_fill_keys($genders_military, 0);
foreach ($results9 as $row) {
if (in_array($row['genero'], $genders_military)) {
$data9[$row['genero']] = (int) $row['count'];
}
}
// Convert data to JSON for Chart.js
$labels9 = json_encode(array_keys($data9));
$counts9 = json_encode(array_values($data9));
// Tenth chart
$query10 = "
SELECT DISTINCT e.user_id,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Sim' THEN 1 ELSE 0 END) as military_dcta,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Não' THEN 1 ELSE 0 END) as military_outside,
SUM(CASE WHEN um1.meta_value = 'Não' THEN 1 ELSE 0 END) as civilians
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'militar'
LEFT JOIN {$wpdb->prefix}usermeta um2 ON e.user_id = um2.user_id AND um2.meta_key = 'efetivo_dcta'
WHERE a.type = 'Main Event'
AND a.modality IN ('Hybrid', 'In-person')
AND e.status IN ('Approved', 'Waiting List', 'Under Analysis')
GROUP BY e.user_id
";
$results10 = $wpdb->get_results($query10, ARRAY_A);
// Prepare data for the tenth chart by processing unique users
$military_dcta_count = 0;
$military_outside_count = 0;
$civilian_count = 0;
$processed_user_ids = [];
foreach ($results10 as $row) {
// Count only unique user_ids in each category
if (!in_array($row['user_id'], $processed_user_ids)) {
if ($row['military_dcta'] > 0) {
$military_dcta_count++;
} elseif ($row['military_outside'] > 0) {
$military_outside_count++;
} elseif ($row['civilians'] > 0) {
$civilian_count++;
}
$processed_user_ids[] = $row['user_id']; // Track processed user_ids
}
}
// Calculate the total in-person count
$total_in_person_count = $military_dcta_count + $military_outside_count + $civilian_count;
// Labels and data for the chart
$labels10 = json_encode(['Military DCTA', 'Military Outside', 'Civilian', 'Total In Person']);
$counts10 = json_encode([$military_dcta_count, $military_outside_count, $civilian_count, $total_in_person_count]);
// Eleventh chart: Total In-person Enrollment attendance of Main Event
$query11 = "
SELECT DISTINCT e.user_id, ac.attended
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE a.type = 'Main Event'
AND a.modality IN ('Hybrid', 'In-person')
AND e.status = 'Approved'
";
$results11 = $wpdb->get_results($query11, ARRAY_A);
$attended_yes = [];
$attended_no_or_empty = [];
foreach ($results11 as $row) {
$user_id = $row['user_id'];
if ($row['attended'] === 'yes' && !in_array($user_id, $attended_yes)) {
$attended_yes[] = $user_id;
} elseif (($row['attended'] === 'no' || $row['attended'] === '' || is_null($row['attended'])) && !in_array($user_id, $attended_no_or_empty)) {
$attended_no_or_empty[] = $user_id;
}
}
$attended_yes_count = count($attended_yes);
$attended_no_or_empty_count = count($attended_no_or_empty);
$labels11 = json_encode(['Attended (Yes)', 'Did Not Attend (No or Empty)']);
$counts11 = json_encode([$attended_yes_count, $attended_no_or_empty_count]);
// Twelfth chart: Total In-person Enrollment attendance of Short-Courses (unique IDs, filtering for 'Approved')
$query12 = "
SELECT DISTINCT e.user_id, ac.attended, a.name as course_name
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE a.type = 'Short-course'
AND a.modality IN ('Hybrid', 'In-person')
AND e.status = 'Approved'
";
// Execute the query
$results12 = $wpdb->get_results($query12, ARRAY_A);
// Initialize arrays to store unique users for each short course
$short_courses = [];
$attended_yes = [];
$attended_no_or_empty = [];
// Process the results to group users by course and attendance status
foreach ($results12 as $row) {
$course_name = $row['course_name'];
$user_id = $row['user_id'];
// Initialize the course arrays if not already present
if (!isset($short_courses[$course_name])) {
$short_courses[$course_name] = ['attended_yes' => [], 'attended_no_or_empty' => []];
}
// If the user attended 'yes', add to attended_yes if not already present
if ($row['attended'] === 'yes' && !in_array($user_id, $short_courses[$course_name]['attended_yes'])) {
$short_courses[$course_name]['attended_yes'][] = $user_id;
}
// If the user attended 'no', '', or is not in the attendance table, add to attended_no_or_empty if not already present
elseif (($row['attended'] === 'no' || $row['attended'] === '' || is_null($row['attended'])) && !in_array($user_id, $short_courses[$course_name]['attended_no_or_empty'])) {
$short_courses[$course_name]['attended_no_or_empty'][] = $user_id;
}
}
// Prepare the data for the twelfth chart
$labels12 = [];
$attended_yes_data = [];
$attended_no_or_empty_data = [];
$course_legend = []; // For legend to map short-course names
$counter = 1;
foreach ($short_courses as $course_name => $data) {
// Create shortened course labels (Short-course 1, Short-course 2, ...)
$course_label = "Short-course " . $counter++;
$course_legend[$course_label] = $course_name; // Add to legend
$labels12[] = $course_label; // Single label for each course
$attended_yes_data[] = count($data['attended_yes']); // Count of attended 'Yes'
$attended_no_or_empty_data[] = count($data['attended_no_or_empty']); // Count of attended 'No' or empty
}
// Convert the data to JSON format for the chart
$labels12 = json_encode($labels12);
$attended_yes_data = json_encode($attended_yes_data);
$attended_no_or_empty_data = json_encode($attended_no_or_empty_data);
echo '<div class="wrap"><h2>Dashboard</h2>';
echo '<div class="dashboard-grid" style="display: flex; flex-wrap: wrap; overflow-x: auto; gap: 20px;">';
// First chart
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="regionChart" width="400" height="200"></canvas>
</div>';
// Second chart
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="formacaoChart" width="400" height="200"></canvas>
</div>';
// Third chart
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="enrollmentChart" width="400" height="200"></canvas>
</div>';
// Fourth chart
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="circuloChart" width="400" height="200"></canvas>
</div>';
// Fifth chart
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="militarChart" width="400" height="200"></canvas>
</div>';
// Sixth chart
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="nonMilitarChart" width="400" height="200"></canvas>
</div>';
// Seventh chart (Brasileiros vs Estrangeiro)
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="nationalityChart" width="400" height="200"></canvas>
</div>';
// Eigth chart (Homens vs Mulheres total)
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="genderChart" width="400" height="200"></canvas>
</div>';
// Nineth chart (Homens vs Mulheres militares)
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="genderMilitaryChart" width="400" height="200"></canvas>
</div>';
// Tenth chart
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="totalCiviliansMilitariesDCTA_Outside" width="400" height="200"></canvas>
</div>';
// Eleventh chart
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="totalEnrollmentAttendanceMainEvent" width="400" height="200"></canvas>
</div>';
// Twelfth chart
echo '<div class="dashboard-item" style="flex: 1 1 25%; min-width: 400px; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); padding: 20px;">
<canvas id="totalEnrollmentAttendanceShortCourses" width="400" height="200"></canvas>
</div>';
echo '</div>';
// Fetch summary counts for the first table
$summary_counts1 = $wpdb->get_results("
SELECT
a.name as activity_name,
a.slots,
COUNT(e.id) as total_requests,
SUM(CASE WHEN e.status = 'Enrollment Canceled by User' THEN 1 ELSE 0 END) as canceled_by_user,
SUM(CASE WHEN e.status = 'Waiting List' THEN 1 ELSE 0 END) as waiting_list,
SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as approved,
SUM(CASE WHEN e.status = 'Not Approved' THEN 1 ELSE 0 END) as not_approved,
SUM(CASE WHEN e.status = 'Under Analysis' THEN 1 ELSE 0 END) as under_analysis,
a.slots - SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as available_slots,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Sim' THEN 1 ELSE 0 END) as military_dcta,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Não' THEN 1 ELSE 0 END) as military_outside,
SUM(CASE WHEN um1.meta_value = 'Não' THEN 1 ELSE 0 END) as civilians
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'militar'
LEFT JOIN {$wpdb->prefix}usermeta um2 ON e.user_id = um2.user_id AND um2.meta_key = 'efetivo_dcta'
WHERE a.type = 'Main Event' AND a.modality = 'Hybrid'
GROUP BY a.name, a.slots
");
ob_start();
// Display first summary counts table
echo '<h3>Hybrid Enrollment Summary</h3>';
echo '<div class="responsive-table">';
echo '<table id="summary-table-1" class="display" style="width: 100%; margin: 0; padding: 0; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); text-align: center;">
<thead>
<tr>
<th>Activity Name</th>
<th>Enrollment Canceled by User</th>
<th>Waiting List</th>
<th>Approved</th>
<th>Not Approved</th>
<th>Under Analysis</th>
<th>Military (DCTA)</th>
<th>Military (Outside)</th>
<th>Civilians</th>
<th>Total Enrollment Requests</th>
<th>Enrollment Availables</th>
<th>Slots</th>
</tr>
</thead>
<tbody>';
if ($summary_counts1) {
foreach ($summary_counts1 as $summary) {
echo '<tr>
<td>' . esc_html($summary->activity_name) . '</td>
<td>' . esc_html($summary->canceled_by_user) . '</td>
<td>' . esc_html($summary->waiting_list) . '</td>
<td>' . esc_html($summary->approved) . '</td>
<td>' . esc_html($summary->not_approved) . '</td>
<td>' . esc_html($summary->under_analysis) . '</td>
<td>' . esc_html($summary->military_dcta) . '</td>
<td>' . esc_html($summary->military_outside) . '</td>
<td>' . esc_html($summary->civilians) . '</td>
<td>' . esc_html($summary->total_requests) . '</td>
<td>' . esc_html($summary->available_slots) . '</td>
<td>' . esc_html($summary->slots) . '</td>
</tr>';
}
} else {
echo '<tr><td colspan="12" style="text-align: center;">No data found</td></tr>';
}
echo '</tbody></table>';
echo '</div>';
// Fetch summary counts for the second table
$summary_counts2 = $wpdb->get_results("
SELECT
a.name as activity_name,
a.slots,
COUNT(e.id) as total_requests,
SUM(CASE WHEN e.status = 'Enrollment Canceled by User' THEN 1 ELSE 0 END) as canceled_by_user,
SUM(CASE WHEN e.status = 'Waiting List' THEN 1 ELSE 0 END) as waiting_list,
SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as approved,
SUM(CASE WHEN e.status = 'Not Approved' THEN 1 ELSE 0 END) as not_approved,
SUM(CASE WHEN e.status = 'Under Analysis' THEN 1 ELSE 0 END) as under_analysis,
a.slots - SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as available_slots,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Sim' THEN 1 ELSE 0 END) as military_dcta,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Não' THEN 1 ELSE 0 END) as military_outside,
SUM(CASE WHEN um1.meta_value = 'Não' THEN 1 ELSE 0 END) as civilians
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'militar'
LEFT JOIN {$wpdb->prefix}usermeta um2 ON e.user_id = um2.user_id AND um2.meta_key = 'efetivo_dcta'
WHERE a.type = 'Main Event' AND a.modality = 'In-person'
GROUP BY a.name, a.slots
");
// Display second summary counts table
echo '<h3>In-person Enrollment Summary</h3>';
echo '<div class="responsive-table">';
echo '<table id="summary-table-2" class="display" style="width: 100%; margin: 0; padding: 0; background-color: #f0f0f0; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); text-align: center;">
<thead>
<tr>
<th>Activity Name</th>
<th>Enrollment Canceled by User</th>
<th>Waiting List</th>
<th>Approved</th>
<th>Not Approved</th>
<th>Under Analysis</th>
<th>Military (DCTA)</th>
<th>Military (Outside)</th>
<th>Civilians</th>
<th>Total Enrollment Requests</th>
<th>Enrollment Availables</th>
<th>Slots</th>
</tr>
</thead>
<tbody>';
if ($summary_counts2) {
foreach ($summary_counts2 as $summary) {
echo '<tr>
<td>' . esc_html($summary->activity_name) . '</td>
<td>' . esc_html($summary->canceled_by_user) . '</td>
<td>' . esc_html($summary->waiting_list) . '</td>
<td>' . esc_html($summary->approved) . '</td>
<td>' . esc_html($summary->not_approved) . '</td>
<td>' . esc_html($summary->under_analysis) . '</td>
<td>' . esc_html($summary->military_dcta) . '</td>
<td>' . esc_html($summary->military_outside) . '</td>
<td>' . esc_html($summary->civilians) . '</td>
<td>' . esc_html($summary->total_requests) . '</td>
<td>' . esc_html($summary->available_slots) . '</td>
<td>' . esc_html($summary->slots) . '</td>
</tr>';
}
} else {
echo '<tr><td colspan="12" style="text-align: center;">No data found</td></tr>';
}
echo '</tbody></table>';
echo '</div>';
ob_end_flush();
echo '
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
// First chart
var ctx1 = document.getElementById("regionChart").getContext("2d");
var regionChart = new Chart(ctx1, {
type: "bar",
data: {
labels: ' . $labels1 . ',
datasets: [{
label: "Users by Region",
data: ' . $counts1 . ',
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-Person Enrollments by Regions of Brazil"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Second chart
var ctx2 = document.getElementById("formacaoChart").getContext("2d");
var formacaoChart = new Chart(ctx2, {
type: "bar",
data: {
labels: ' . $labels2 . ',
datasets: ' . $datasets2 . '
},
options: {
plugins: {
title: {
display: true,
text: "Total In-Person Enrollments by Academic Background"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Third chart
var ctx3 = document.getElementById("enrollmentChart").getContext("2d");
var enrollmentChart = new Chart(ctx3, {
type: "bar",
data: {
labels: ' . $labels3 . ',
datasets: [{
label: "Enrollment Types",
data: ' . $counts3 . ',
backgroundColor: [
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)"
],
borderColor: [
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-Person and Online Enrollments (Unique Users - Status: Approved)"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Fourth chart
var ctx4 = document.getElementById("circuloChart").getContext("2d");
var circuloChart = new Chart(ctx4, {
type: "bar",
data: {
labels: ' . $labels4 . ',
datasets: [{
label: "Circulo Hierárquico Distribution",
data: ' . $counts4 . ',
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)",
"rgba(201, 203, 207, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)",
"rgba(201, 203, 207, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total Enrollments of Militaries by hierarquical circle"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Fifth chart
var ctx5 = document.getElementById("militarChart").getContext("2d");
var militarChart = new Chart(ctx5, {
type: "bar",
data: {
labels: ' . $labels5 . ',
datasets: [{
label: "Militar Enrollment Types",
data: ' . $counts5 . ',
backgroundColor: [
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)"
],
borderColor: [
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-Person and Online Enrollments of Militaries (Unique Users - Status: Approved)"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Sixth chart
var ctx6 = document.getElementById("nonMilitarChart").getContext("2d");
var nonMilitarChart = new Chart(ctx6, {
type: "bar",
data: {
labels: ' . $labels6 . ',
datasets: [{
label: "Non-Militar Enrollment Types",
data: ' . $counts6 . ',
backgroundColor: [
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)"
],
borderColor: [
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-Person and Online Enrollments of Civilians (Unique Users - Status: Approved)"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Seventh chart (Brasileiros vs Estrangeiro)
var ctx7 = document.getElementById("nationalityChart").getContext("2d");
var nationalityChart = new Chart(ctx7, {
type: "bar",
data: {
labels: ' . $labels7 . ',
datasets: [{
label: "Users by Nationality",
data: ' . $counts7 . ',
backgroundColor: [
"rgba(75, 192, 192, 0.2)",
"rgba(255, 99, 132, 0.2)"
],
borderColor: [
"rgba(75, 192, 192, 1)",
"rgba(255, 99, 132, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-person and Online Enrollments by Nationality"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Eighth chart
var ctx8 = document.getElementById("genderChart").getContext("2d");
var genderChart = new Chart(ctx8, {
type: "bar",
data: {
labels: ' . $labels8 . ',
datasets: [{
label: "Users by Gender",
data: ' . $counts8 . ',
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-person and Online Enrollments by Gender"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Ninth chart
var ctx9 = document.getElementById("genderMilitaryChart").getContext("2d");
var genderMilitaryChart = new Chart(ctx9, {
type: "bar",
data: {
labels: ' . $labels9 . ',
datasets: [{
label: "Military Users by Gender",
data: ' . $counts9 . ',
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-person and Online Military Enrollments by Gender"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Tenth chart
var ctx10 = document.getElementById("totalCiviliansMilitariesDCTA_Outside").getContext("2d");
var totalCiviliansMilitariesDCTA_OutsideChart = new Chart(ctx10, {
type: "bar",
data: {
labels: ' . $labels10 . ',
datasets: [{
label: "Total In-Person Distribution",
data: ' . $counts10 . ',
backgroundColor: [
"rgba(75, 192, 192, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(153, 102, 255, 0.2)"
],
borderColor: [
"rgba(75, 192, 192, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(153, 102, 255, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-person Enrollment (Military DCTA, Military Outside, Civilian, Total)"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Eleventh chart
var ctx11 = document.getElementById("totalEnrollmentAttendanceMainEvent").getContext("2d");
var totalEnrollmentAttendanceMainEventChart = new Chart(ctx11, {
type: "bar",
data: {
labels: ' . $labels11 . ',
datasets: [{
label: "In-person Attendance of Main Event",
data: ' . $counts11 . ',
backgroundColor: [
"rgba(75, 192, 192, 0.2)",
"rgba(255, 99, 132, 0.2)"
],
borderColor: [
"rgba(75, 192, 192, 1)",
"rgba(255, 99, 132, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-person Enrollment Attendance of Main Event (Users Approved)"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
var ctx12 = document.getElementById("totalEnrollmentAttendanceShortCourses").getContext("2d");
var totalEnrollmentAttendanceShortCoursesChart = new Chart(ctx12, {
type: "bar",
data: {
labels: ' . $labels12 . ', // Single label per course
datasets: [{
label: "Attended (Yes)",
data: ' . $attended_yes_data . ',
backgroundColor: "rgba(75, 192, 192, 0.2)", // Color for Attended (Yes)
borderColor: "rgba(75, 192, 192, 1)",
borderWidth: 1
}, {
label: "Did Not Attend",
data: ' . $attended_no_or_empty_data . ',
backgroundColor: "rgba(255, 99, 132, 0.2)", // Color for Did Not Attend (No or Empty)
borderColor: "rgba(255, 99, 132, 1)",
borderWidth: 1
}]
},
options: {
plugins: {
title: {
display: true,
text: "Total In-person Enrollment Attendance of Short-Courses"
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Legend showing the mapping of Short-course names
var courseLegend = ' . json_encode($course_legend) . ';
var legendDiv = document.createElement("div");
legendDiv.style.marginTop = "20px";
legendDiv.innerHTML = "<strong>Short-course Legend:</strong><br>";
for (var key in courseLegend) {
if (courseLegend.hasOwnProperty(key)) {
legendDiv.innerHTML += key + ": " + courseLegend[key] + "<br>";
}
}
document.getElementById("totalEnrollmentAttendanceShortCourses").parentNode.appendChild(legendDiv);
});
</script>
';
}
function createActivitiesSubmenuPage()
{
global $wpdb;
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['new_activity'])) {
$name = sanitize_text_field($_POST['activity_name']);
$description = sanitize_textarea_field($_POST['activity_description']);
$start_date = sanitize_text_field($_POST['start_date']);
$start_time = sanitize_text_field($_POST['start_time']);
$end_date = sanitize_text_field($_POST['end_date']);
$end_time = sanitize_text_field($_POST['end_time']);
$type = sanitize_text_field($_POST['activity_type']);
$modality = sanitize_text_field($_POST['activity_modality']);
$status = sanitize_text_field($_POST['activity_status']);
$curriculum = esc_url_raw($_POST['curriculum']);
$comment = sanitize_textarea_field($_POST['comment']);
$place_id = intval($_POST['place']);
$speaker_id = intval($_POST['speaker']);
$event_name_id = intval($_POST['event_name']);
$security_credential = sanitize_text_field($_POST['security_credential']);
$chair = sanitize_text_field($_POST['chair']);
$target_audience = sanitize_text_field($_POST['target_audience']);
$attendance_control = sanitize_text_field($_POST['attendance_control']);
$slots = sanitize_text_field($_POST['slots']);
$activity_matching_key = intval($_POST['activity_matching_key']);
if (strtotime($end_date) < strtotime($start_date)) {
echo '<div class="notice notice-error"><p>The end date cannot be before the start date.</p></div>';
} else {
$wpdb->insert(
"{$wpdb->prefix}sige_activities",
[
'name' => $name,
'description' => $description,
'start_date' => $start_date,
'start_time' => $start_time,
'end_date' => $end_date,
'end_time' => $end_time,
'type' => $type,
'modality' => $modality,
'status' => $status,
'curriculum' => $curriculum,
'comment' => $comment,
'place_id' => $place_id,
'speaker_id' => $speaker_id,
'event_name_id' => $event_name_id,
'security_credential' => $security_credential,
'chair' => $chair,
'target_audience' => $target_audience,
'attendance_control' => $attendance_control,
'slots' => $slots,
'activity_matching_key' => $activity_matching_key
]
);
}
}
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['update_activity'])) {
$id = intval($_POST['activity_id']);
$name = sanitize_text_field($_POST['activity_name']);
$description = sanitize_textarea_field($_POST['activity_description']);
$start_date = sanitize_text_field($_POST['start_date']);
$start_time = sanitize_text_field($_POST['start_time']);
$end_date = sanitize_text_field($_POST['end_date']);
$end_time = sanitize_text_field($_POST['end_time']);
$type = sanitize_text_field($_POST['activity_type']);
$modality = sanitize_text_field($_POST['activity_modality']);
$status = sanitize_text_field($_POST['activity_status']);
$curriculum = esc_url_raw($_POST['curriculum']);
$comment = sanitize_textarea_field($_POST['comment']);
$place_id = intval($_POST['place']);
$speaker_id = intval($_POST['speaker']);
$event_name_id = intval($_POST['event_name']);
$security_credential = sanitize_text_field($_POST['security_credential']);
$chair = sanitize_text_field($_POST['chair']);
$target_audience = sanitize_text_field($_POST['target_audience']);
$attendance_control = sanitize_text_field($_POST['attendance_control']);
$slots = sanitize_text_field($_POST['slots']);
$activity_matching_key = intval($_POST['activity_matching_key']);
if (strtotime($end_date) < strtotime($start_date)) {
echo '<div class="notice notice-error"><p>The end date cannot be before the start date.</p></div>';
} else {
$wpdb->update(
"{$wpdb->prefix}sige_activities",
[
'name' => $name,
'description' => $description,
'start_date' => $start_date,
'start_time' => $start_time,
'end_date' => $end_date,
'end_time' => $end_time,
'type' => $type,
'modality' => $modality,
'status' => $status,
'curriculum' => $curriculum,
'comment' => $comment,
'place_id' => $place_id,
'speaker_id' => $speaker_id,
'event_name_id' => $event_name_id,
'security_credential' => $security_credential,
'chair' => $chair,
'target_audience' => $target_audience,
'attendance_control' => $attendance_control,
'slots' => $slots,
'activity_matching_key' => $activity_matching_key
],
['id' => $id]
);
$redirect_url = admin_url('admin.php?page=create-activities-submenu');
echo '<script>window.location.href="' . $redirect_url . '";</script>';
exit;
}
}
if (isset($_GET['delete_activity'])) {
$id = intval($_GET['delete_activity']);
$wpdb->delete("{$wpdb->prefix}sige_activities", ['id' => $id]);
}
$edit_activity = null;
if (isset($_GET['edit_activity'])) {
$edit_id = intval($_GET['edit_activity']);
$edit_activity = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}sige_activities WHERE id = $edit_id");
}
$places = $wpdb->get_results("SELECT id, place FROM {$wpdb->prefix}sige_place");
$speakers = $wpdb->get_results("SELECT id, full_name FROM {$wpdb->prefix}sige_speakers");
$event_names = $wpdb->get_results("SELECT id, name FROM {$wpdb->prefix}sige_event_names");
echo '<div class="wrap"><h2>Create & Manage Activities</h2>
<form method="post" style="box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); background: #f9f9f9; border: 1px solid #ccc; padding: 20px; border-radius: 8px;">
<style>
.sige-activity-form th,
.sige-activity-form td {
padding: 10px 5px;
vertical-align: bottom;
}
.sige-activity-form th {
text-align: left;
padding-right: 10px;
}
.sige-activity-form td {
max-width: none;
}
.sige-activity-form input[type="text"],
.sige-activity-form input[type="date"],
.sige-activity-form input[type="time"],
.sige-activity-form select,
.sige-activity-form textarea {
width: 100%;
box-sizing: border-box;
}
.sige-activity-form select[name="activity_type"],
.sige-activity-form select[name="activity_modality"],
.sige-activity-form select[name="activity_status"] {
max-width: none;
}
.sige-activity-form .full-width {
width: 100%;
}
.button-edit,
.button-delete {
width: 70px; /* Adjust this to your desired width */
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
const startDate = document.querySelector("input[name=\'start_date\']");
const endDate = document.querySelector("input[name=\'end_date\']");
startDate.addEventListener("focus", function() {
const today = new Date().toISOString().split("T")[0];
if (startDate.value ==="") {
startDate.value = today;
}
});
endDate.addEventListener("focus", function() {
if (endDate.value ==="") {
endDate.value = startDate.value;
}
});
startDate.addEventListener("change", function() {
if (endDate.value < startDate.value || endDate.value ==="") {
endDate.value = startDate.value;
}
});
document.querySelector("form").addEventListener("submit", function(event) {
if (new Date(endDate.value) < new Date(startDate.value)) {
event.preventDefault();
alert("The end date cannot be before the start date.");
}
});
});
</script>';
if ($edit_activity) {
echo '<input type="hidden" name="activity_id" value="' . esc_attr($edit_activity->id) . '" />';
echo '<input type="hidden" name="update_activity" value="1" />';
} else {
echo '<input type="hidden" name="new_activity" value="1" />';
}
echo '
<table class="form-table sige-activity-form" style="width: 100%;">
<tr valign="top">
<th scope="row">Activity Name</th>
<td><input type="text" name="activity_name" value="' . ($edit_activity ? esc_attr($edit_activity->name) : '') . '" required /></td>
<th scope="row">Activity Description</th>
<td><textarea rows="1" name="activity_description" >' . ($edit_activity ? esc_textarea($edit_activity->description) : '') . '</textarea></td>
</tr>
<tr valign="top">
<th scope="row">Start Date</th>
<td><input type="date" name="start_date" value="' . ($edit_activity ? esc_attr($edit_activity->start_date) : '') . '" required /></td>
<th scope="row">Start Time</th>
<td><input type="time" name="start_time" value="' . ($edit_activity ? esc_attr($edit_activity->start_time) : '') . '" /></td>
</tr>
<tr valign="top">
<th scope="row">End Date</th>
<td><input type="date" name="end_date" value="' . ($edit_activity ? esc_attr($edit_activity->end_date) : '') . '" /></td>
<th scope="row">End Time</th>
<td><input type="time" name="end_time" value="' . ($edit_activity ? esc_attr($edit_activity->end_time) : '') . '" /></td>
</tr>
<tr valign="top">
<th scope="row">Activity Type</th>
<td>
<select name="activity_type" required>
<option value="Main Event"' . ($edit_activity && $edit_activity->type == 'Main Event' ? ' selected' : '') . '>Main Event</option>
<option value="Presentation"' . ($edit_activity && $edit_activity->type == 'Presentation' ? ' selected' : '') . '>Presentation</option>
<option value="Short-course"' . ($edit_activity && $edit_activity->type == 'Short-course' ? ' selected' : '') . '>Short-course</option>
<option value="Lecture"' . ($edit_activity && $edit_activity->type == 'Lecture' ? ' selected' : '') . '>Lecture</option>
<option value="Workshop"' . ($edit_activity && $edit_activity->type == 'Workshop' ? ' selected' : '') . '>Workshop</option>
<option value="Others"' . ($edit_activity && $edit_activity->type == 'Others' ? ' selected' : '') . '>Others</option>
</select>
</td>
<th scope="row">Activity Modality</th>
<td>
<select name="activity_modality" required>
<option value="Online"' . ($edit_activity && $edit_activity->modality == 'Online' ? ' selected' : '') . '>Online</option>
<option value="In-person"' . ($edit_activity && $edit_activity->modality == 'In-person' ? ' selected' : '') . '>In-person</option>
<option value="Hybrid"' . ($edit_activity && $edit_activity->modality == 'Hybrid' ? ' selected' : '') . '>Hybrid</option>
<option value="Others"' . ($edit_activity && $edit_activity->modality == 'Others' ? ' selected' : '') . '>Others</option>
</select>
</td>
</tr>
<tr valign="top">
<th scope="row">Subscription Status</th>
<td>
<select name="activity_status" required>
<option value="Open"' . ($edit_activity && $edit_activity->status == 'Open' ? ' selected' : '') . '>Open</option>
<option value="Closed"' . ($edit_activity && $edit_activity->status == 'Closed' ? ' selected' : '') . '>Closed</option>
<option value="Not applicable"' . ($edit_activity && $edit_activity->status == 'Not applicable' ? ' selected' : '') . '>Not applicable</option>
</select>
</td>
<th scope="row">Place</th>
<td>
<select name="place" required>';
foreach ($places as $place) {
echo '<option value="' . esc_attr($place->id) . '"' . ($edit_activity && $edit_activity->place_id == $place->id ? ' selected' : '') . '>' . esc_html($place->place) . '</option>';
}
echo ' </select>
</td>
</tr>
<tr valign="top">
<th scope="row">Speaker</th>
<td>
<select name="speaker">';
foreach ($speakers as $speaker) {
echo '<option value="' . esc_attr($speaker->id) . '"' . ($edit_activity && $edit_activity->speaker_id == $speaker->id ? ' selected' : '') . '>' . esc_html($speaker->full_name) . '</option>';
}
echo ' </select>
</td>
<th scope="row">Event Name</th>
<td>
<select name="event_name">';
foreach ($event_names as $event_name) {
echo '<option value="' . esc_attr($event_name->id) . '"' . ($edit_activity && $edit_activity->event_name_id == $event_name->id ? ' selected' : '') . '>' . esc_html($event_name->name) . '</option>';
}
echo ' </select>
</td>
</tr>
<tr valign="top">
<th scope="row">Chair</th>
<td><input type="text" name="chair" value="' . ($edit_activity ? esc_attr($edit_activity->chair) : '') . '" /></td>
<th scope="row">Curriculum</th>
<td><input type="url" name="curriculum" class="full-width" placeholder="https://curriculumsite.yourdomain.country" value="' . ($edit_activity ? esc_url($edit_activity->curriculum) : '') . '"/></td>
</tr>
<tr valign="top">
<th scope="row">Security Credential</th>
<td>
<select name="security_credential" required>
<option value="Required"' . ($edit_activity && $edit_activity->security_credential == 'Required' ? ' selected' : '') . '>Required</option>
<option value="Not Required"' . ($edit_activity && $edit_activity->security_credential == 'Not Required' ? ' selected' : '') . '>Not Required</option>
</select>
</td>
<th scope="row">Target Audience</th>
<td>
<select name="target_audience" required>
<option value="Military"' . ($edit_activity && $edit_activity->target_audience == 'Military' ? ' selected' : '') . '>Military</option>
<option value="Civilian"' . ($edit_activity && $edit_activity->target_audience == 'Civilian' ? ' selected' : '') . '>Civilian</option>
<option value="Military and Civilian"' . ($edit_activity && $edit_activity->target_audience == 'Military and Civilian' ? ' selected' : '') . '>Military and Civilian</option>
</select>
</td>
</tr>
<tr valign="top">
<th scope="row">Attendance Control</th>
<td>
<select name="attendance_control" required>
<option value="yes"' . ($edit_activity && $edit_activity->attendance_control == 'yes' ? ' selected' : '') . '>Yes</option>
<option value="no"' . ($edit_activity && $edit_activity->attendance_control == 'no' ? ' selected' : '') . '>No</option>
</select>
</td>
<th scope="row">Comment</th>
<td colspan="3"><textarea rows="1" textarea name="comment">' . ($edit_activity ? esc_textarea($edit_activity->comment) : '') . '</textarea></td>
</tr>
<tr valign="top">
<th scope="row">Slots</th>
<td><input type="number" name="slots" value="' . ($edit_activity ? esc_attr($edit_activity->slots) : '') . '" /></td>
</tr>
<tr valign="top">
<th scope="row">Matching Key</th>
<td><input type="number" name="activity_matching_key" value="' . ($edit_activity ? esc_attr($edit_activity->activity_matching_key) : '') . '" /></td>
</tr>
</table>
<input type="submit" name="' . ($edit_activity ? 'update_activity' : 'new_activity') . '" value="' . ($edit_activity ? 'Update Activity' : 'Add Activity') . '" class="button button-primary" />
</form></div>';
// Add the JavaScript for showing/hiding slots based on attendance control
echo '
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
var attendanceControl = document.querySelector(\'select[name="attendance_control"]\');
var slotsRow = document.querySelector(\'tr:has(input[name="slots"])\');
function toggleSlotsVisibility() {
if (attendanceControl.value === "yes") {
slotsRow.style.display = "";
} else {
slotsRow.style.display = "none";
}
}
toggleSlotsVisibility();
attendanceControl.addEventListener("change", toggleSlotsVisibility);
});
</script>';
$activities = $wpdb->get_results("
SELECT a.*, p.place, s.full_name as speaker, e.name as event_name
FROM {$wpdb->prefix}sige_activities a
LEFT JOIN {$wpdb->prefix}sige_place p ON a.place_id = p.id
LEFT JOIN {$wpdb->prefix}sige_speakers s ON a.speaker_id = s.id
LEFT JOIN {$wpdb->prefix}sige_event_names e ON a.event_name_id = e.id
");
if ($activities) {
$types = ['Main Event', 'Presentation', 'Short-course', 'Lecture', 'Workshop', 'Others'];
$modalities = ['Online', 'In-person', 'Hybrid', 'Others'];
$statuses = ['Open', 'Closed', 'Not applicable'];
if ($activities) {
echo '<form method="post" action="">
<input type="hidden" name="export_activities_csv" value="1" />
<input type="submit" value="Export to CSV" class="button button-secondary" />
</form>';
}
echo '<h3>Existing Activities</h3>';
echo '<div style="max-width: 100%; overflow-x: auto; padding-right: 20px;">';
echo '<table id="activities-table" class="display" style="width: 100%; min-width: 1000px;">
<thead>
<tr>
<th style="width: 100px;">Activity Name</th>
<th style="min-width: 200px;">Activity Description</th>
<th style="width: 70px;">Activity ID</th>
<th style="width: 70px;">Start Date</th>
<th style="width: 70px;">Start Time</th>
<th style="width: 70px;">End Date</th>
<th style="width: 70px;">End Time</th>
<th style="width: 70px;">Type</th>
<th style="width: 90px;">Modality</th>
<th style="width: 70px;">Status</th>
<th style="width: 100px;">Place</th>
<th style="width: 100px;">Speaker</th>
<th style="width: 70px;">Event Name</th>
<th style="width: 80px;">Chair</th>
<th style="min-width: 100px;">Curriculum</th>
<th style="min-width: 100px;">Security Credential</th>
<th style="min-width: 100px;">Target Audience</th>
<th style="min-width: 100px;">Attendance Control</th>
<th style="width: 70px;">Slots</th>
<th style="width: 70px;">Activity Matching Key</th>
<th style="min-width: 200px;">Comment</th>
<th style="width: 70px;"></th>
<th style="width: 70px;"></th>
</tr>
</thead>
<tbody>';
foreach ($activities as $activity) {
echo '<tr>
<td>' . esc_html($activity->name) . '</td>
<td>' . esc_html($activity->description) . '</td>
<td>' . esc_html($activity->id) . '</td>
<td>' . esc_html($activity->start_date) . '</td>
<td>' . esc_html($activity->start_time) . '</td>
<td>' . esc_html($activity->end_date) . '</td>
<td>' . esc_html($activity->end_time) . '</td>
<td>' . esc_html($activity->type) . '</td>
<td>' . esc_html($activity->modality) . '</td>
<td>' . esc_html($activity->status) . '</td>
<td>' . esc_html($activity->place) . '</td>
<td>' . esc_html($activity->speaker) . '</td>
<td>' . esc_html($activity->event_name) . '</td>
<td>' . esc_html($activity->chair) . '</td>
<td>' . esc_html($activity->curriculum) . '</td>
<td>' . esc_html($activity->security_credential) . '</td>
<td>' . esc_html($activity->target_audience) . '</td>
<td>' . esc_html($activity->attendance_control) . '</td>
<td>' . esc_html($activity->slots) . '</td>
<td>' . esc_html($activity->activity_matching_key) . '</td>
<td>' . esc_html($activity->comment) . '</td>
<td><a href="' . admin_url('admin.php?page=create-activities-submenu&edit_activity=' . $activity->id) . '" class="button button-edit">Edit</a></td>
<td><a href="' . admin_url('admin.php?page=create-activities-submenu&delete_activity=' . $activity->id) . '" class="button button-delete" onclick="return confirm(\'Are you sure you want to delete this activity?\')">Delete</a></td>
</tr>';
}
echo '</tbody>
</table>
</div>';
echo '<script>
jQuery(document).ready(function($) {
$("#activities-table").DataTable({
"scrollX": true,
"autoWidth": false,
"pageLength": 10, // Set the default number of entries to show
"lengthMenu": [ [10, 25, 50, 100, 200, 500, -1], [10, 25, 50, 100, 200, 500, "All"] ] // Add custom options for the number of entries
});
});
</script>';
}
}
function frontendDashboard()
{
if (!is_user_logged_in()) {
return '
<div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
background-color: #808080; color: #fff; padding: 20px;
box-shadow: 0 0 15px rgba(0,0,0,0.3); z-index: 1000; text-align: center; border-radius: 10px;">
<p>You need to be logged in to view the registrations that have been made.</p>
</div>';
}
if (!current_user_can('administrator') && !current_user_can('contributor')) {
return '
<div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
background-color: #808080; color: #fff; padding: 20px;
box-shadow: 0 0 15px rgba(0,0,0,0.3); z-index: 1000; text-align: center; border-radius: 10px;">
<p>You do not have the required permissions to handle the attendance control.</p>
</div>';
}
global $wpdb;
// ---------- 1) SELECTOR DE ATIVIDADE ----------
// Lista de atividades com rótulo: "name (YYYY) - modality"
$activities = $wpdb->get_results("
SELECT id, name, modality, start_date, type
FROM {$wpdb->prefix}sige_activities
ORDER BY COALESCE(start_date, '1970-01-01') DESC, id DESC
", ARRAY_A);
$selected_activity_id = isset($_GET['activity_id']) ? intval($_GET['activity_id']) : 0;
$selected_activity = null;
$selected_activity_modality = null;
$selected_activity_type = null;
if ($selected_activity_id > 0) {
$selected_activity = $wpdb->get_row(
$wpdb->prepare("
SELECT id, name, modality, start_date, type
FROM {$wpdb->prefix}sige_activities
WHERE id = %d
", $selected_activity_id),
ARRAY_A
);
if ($selected_activity) {
$selected_activity_modality = $selected_activity['modality'];
$selected_activity_type = $selected_activity['type'];
} else {
$selected_activity_id = 0; // id inválido -> zera seleção
}
}
ob_start();
echo '<div class="wrap"><h2>Dashboard</h2>';
// Formulário (GET) com auto-submit no change
echo '<form method="get" id="activity-filter-form" style="margin: 10px 0 20px;">';
echo '<label for="activity_id" style="margin-right:8px; font-weight:600;">Selecione a atividade:</label>';
echo '<select name="activity_id" id="activity_id" onchange="this.form.submit()" style="min-width:360px; padding:6px;">';
echo '<option value="0">-- Selecione --</option>';
foreach ($activities as $act) {
$year = '';
if (!empty($act['start_date'])) {
$ts = strtotime($act['start_date']);
if ($ts) {
$year = date('Y', $ts);
}
}
$label = esc_html($act['name']) . ($year ? " ({$year})" : "") . " - " . esc_html($act['modality']);
$sel = ($selected_activity_id === intval($act['id'])) ? 'selected' : '';
echo '<option value="' . intval($act['id']) . '" ' . $sel . '>' . $label . '</option>';
}
echo '</select>';
echo '</form>';
if ($selected_activity_id === 0) {
echo '<p style="margin-top:10px;">Selecione uma atividade para visualizar os gráficos e tabelas.</p>';
echo '</div>'; // .wrap
return ob_get_clean();
}
// Aviso solicitado quando a atividade é presencial
if ($selected_activity_modality === 'In-person') {
echo '<div style="margin: 10px 0 20px; padding: 10px 12px; background:#fff3cd; border:1px solid #ffeeba; border-radius:6px; color:#856404;">
<strong>Aviso:</strong> Dados indisponíveis para modalidade online. Motivo: atividade presencial.
</div>';
}
// ---------- 2) VARIÁVEIS AUXILIARES ----------
// Cláusulas de filtro por atividade (reutilizáveis)
$WHERE_ACTIVITY = $wpdb->prepare(" e.activity_id = %d ", $selected_activity_id);
// Status usados no seu código original (mantidos)
$STATUS_EXCLUDE_Q3 = "('Not Approved','Enrollment Canceled by User','Waiting List','Under Analysis')";
$STATUS_EXCLUDE_Q7_Q8_Q9 = "('Not Approved','Enrollment Canceled by User')";
// Para dividir "presencial vs online" dentro da MESMA atividade (sem olhar outras)
// Conta usuários distintos APENAS desta atividade (Approved, etc.)
$total_users_this_activity_approved = intval($wpdb->get_var("
SELECT COUNT(DISTINCT e.user_id)
FROM {$wpdb->prefix}sige_enrollments e
WHERE {$WHERE_ACTIVITY}
AND e.status NOT IN {$STATUS_EXCLUDE_Q3}
"));
// ---------- 3) Q1 Região (AGORA filtrando pela atividade) ----------
$query1 = "
SELECT um.meta_value as regiao_do_brasil, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um
ON e.user_id = um.user_id AND um.meta_key = 'regiao_do_brasil'
WHERE {$WHERE_ACTIVITY}
GROUP BY um.meta_value
";
$results1 = $wpdb->get_results($query1, ARRAY_A);
$regions = ['Norte', 'Nordeste', 'Centro-Oeste', 'Sudeste', 'Sul'];
$data1 = array_fill_keys($regions, 0);
foreach ($results1 as $row) {
if (in_array($row['regiao_do_brasil'], $regions, true)) {
$data1[$row['regiao_do_brasil']] = (int)$row['count'];
}
}
$labels1 = json_encode(array_keys($data1));
$counts1 = json_encode(array_values($data1));
// ---------- 4) Q2 Formação x Região (AGORA filtrando pela atividade) ----------
$query2 = "
SELECT
fa.meta_value as formacao_academica,
rb.meta_value as regiao_do_brasil,
COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta fa ON e.user_id = fa.user_id AND fa.meta_key = 'formacao_academica'
LEFT JOIN {$wpdb->prefix}usermeta rb ON e.user_id = rb.user_id AND rb.meta_key = 'regiao_do_brasil'
WHERE {$WHERE_ACTIVITY}
GROUP BY fa.meta_value, rb.meta_value
";
$results2 = $wpdb->get_results($query2, ARRAY_A);
$formacoes = ['Aluno de Graduação', 'Aluno de Pós-Graduação', 'Professor da Educação Básica', 'Professor/Pesquisador', 'Outros'];
$regions2 = ['Norte', 'Nordeste', 'Centro-Oeste', 'Sudeste', 'Sul'];
$data2 = [];
foreach ($formacoes as $f) {
$data2[$f] = array_fill_keys($regions2, 0);
}
foreach ($results2 as $row) {
if (in_array($row['formacao_academica'], $formacoes, true)) {
$region = $row['regiao_do_brasil'];
if (array_key_exists($region, $data2[$row['formacao_academica']])) {
$data2[$row['formacao_academica']][$region] += (int)$row['count'];
}
}
}
$labels2 = json_encode(array_keys($data2['Aluno de Graduação']));
$datasets2_arr = [];
foreach ($data2 as $formacao => $counts) {
$datasets2_arr[] = [
'label' => $formacao,
'data' => array_values($counts),
// cores aleatórias como no seu código
'backgroundColor' => 'rgba(' . rand(0, 255) . ', ' . rand(0, 255) . ', ' . rand(0, 255) . ', 0.2)',
'borderColor' => 'rgba(' . rand(0, 255) . ', ' . rand(0, 255) . ', ' . rand(0, 255) . ', 1)',
'borderWidth' => 1
];
}
$datasets2 = json_encode($datasets2_arr);
// ---------- 5) Q3 Presencial vs Online (apenas desta atividade) ----------
// Base: aprovados (ou equivalentes) desta atividade
$in_person_modalities = ['In-person', 'Hybrid'];
$in_person_count = in_array($selected_activity_modality, $in_person_modalities, true) ? $total_users_this_activity_approved : 0;
$online_count = ($selected_activity_modality === 'Online') ? $total_users_this_activity_approved : 0;
$labels3 = json_encode(['In-person Enrollment', 'Online Enrollment']);
$counts3 = json_encode([$in_person_count, $online_count]);
// ---------- 6) Q4 Círculo hierárquico (apenas usuários desta atividade; mantém seus status) ----------
$query4 = "
SELECT um.meta_value as circulo_hierarquico, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'circulo_hierárquico'
WHERE {$WHERE_ACTIVITY}
AND e.status NOT IN {$STATUS_EXCLUDE_Q3}
GROUP BY um.meta_value
";
$results4 = $wpdb->get_results($query4, ARRAY_A);
$circulos = ['Praça', 'Graduado', 'Praça Especial', 'Oficial Subalterno', 'Oficial Intermediário', 'Oficial Superior', 'Oficial General'];
$data4 = array_fill_keys($circulos, 0);
foreach ($results4 as $row) {
if (in_array($row['circulo_hierarquico'], $circulos, true)) {
$data4[$row['circulo_hierarquico']] = (int)$row['count'];
}
}
$labels4 = json_encode(array_keys($data4));
$counts4 = json_encode(array_values($data4));
// ---------- 7) Q5 Militar: Presencial vs Online (desta atividade) ----------
$in_person_users_militar = intval($wpdb->get_var("
SELECT COUNT(DISTINCT e.user_id)
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key='militar'
WHERE {$WHERE_ACTIVITY}
AND e.status NOT IN {$STATUS_EXCLUDE_Q3}
AND um.meta_value = 'Sim'
"));
// Distribuição por modalidade da atividade selecionada
$in_person_count_militar = in_array($selected_activity_modality, $in_person_modalities, true) ? $in_person_users_militar : 0;
$online_count_militar = ($selected_activity_modality === 'Online') ? $in_person_users_militar : 0;
$labels5 = json_encode(['In-person Enrollment Militar', 'Online Enrollment Militar']);
$counts5 = json_encode([$in_person_count_militar, $online_count_militar]);
// ---------- 8) Q6 Não-militar: Presencial vs Online (desta atividade) ----------
$in_person_users_non_militar = intval($wpdb->get_var("
SELECT COUNT(DISTINCT e.user_id)
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key='militar'
WHERE {$WHERE_ACTIVITY}
AND e.status NOT IN {$STATUS_EXCLUDE_Q3}
AND um.meta_value = 'Não'
"));
$in_person_count_non_militar = in_array($selected_activity_modality, $in_person_modalities, true) ? $in_person_users_non_militar : 0;
$online_count_non_militar = ($selected_activity_modality === 'Online') ? $in_person_users_non_militar : 0;
$labels6 = json_encode(['In-person Enrollment Non-Militar', 'Online Enrollment Non-Militar']);
$counts6 = json_encode([$in_person_count_non_militar, $online_count_non_militar]);
// ---------- 9) Q7 Nacionalidade (desta atividade) ----------
$query7 = "
SELECT um.meta_value as nacionalidade, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'nacionalidade'
WHERE {$WHERE_ACTIVITY}
AND e.status NOT IN {$STATUS_EXCLUDE_Q7_Q8_Q9}
GROUP BY um.meta_value
";
$results7 = $wpdb->get_results($query7, ARRAY_A);
$nationalities = ['Brasileiro', 'Estrangeiro'];
$data7 = array_fill_keys($nationalities, 0);
foreach ($results7 as $row) {
if (in_array($row['nacionalidade'], $nationalities, true)) {
$data7[$row['nacionalidade']] = (int)$row['count'];
}
}
$labels7 = json_encode(array_keys($data7));
$counts7 = json_encode(array_values($data7));
// ---------- 10) Q8 Gênero (desta atividade) ----------
$query8 = "
SELECT um.meta_value as genero, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'genero'
WHERE {$WHERE_ACTIVITY}
AND e.status NOT IN {$STATUS_EXCLUDE_Q7_Q8_Q9}
GROUP BY um.meta_value
";
$results8 = $wpdb->get_results($query8, ARRAY_A);
$genders = ['Feminino', 'Masculino'];
$data8 = array_fill_keys($genders, 0);
foreach ($results8 as $row) {
if (in_array($row['genero'], $genders, true)) {
$data8[$row['genero']] = (int)$row['count'];
}
}
$labels8 = json_encode(array_keys($data8));
$counts8 = json_encode(array_values($data8));
// ---------- 11) Q9 Militar por gênero (desta atividade) ----------
$query9 = "
SELECT um1.meta_value as genero, COUNT(DISTINCT e.user_id) as count
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'genero'
LEFT JOIN {$wpdb->prefix}usermeta um2 ON e.user_id = um2.user_id AND um2.meta_key = 'militar'
WHERE {$WHERE_ACTIVITY}
AND e.status NOT IN {$STATUS_EXCLUDE_Q7_Q8_Q9}
AND um2.meta_value = 'Sim'
GROUP BY um1.meta_value
";
$results9 = $wpdb->get_results($query9, ARRAY_A);
$genders_military = ['Feminino', 'Masculino'];
$data9 = array_fill_keys($genders_military, 0);
foreach ($results9 as $row) {
if (in_array($row['genero'], $genders_military, true)) {
$data9[$row['genero']] = (int)$row['count'];
}
}
$labels9 = json_encode(array_keys($data9));
$counts9 = json_encode(array_values($data9));
// ---------- 12) Q10 DCTA / fora / civil + total (desta atividade; presenciais) ----------
$results10 = $wpdb->get_results("
SELECT DISTINCT e.user_id,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Sim' THEN 1 ELSE 0 END) as military_dcta,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Não' THEN 1 ELSE 0 END) as military_outside,
SUM(CASE WHEN um1.meta_value = 'Não' THEN 1 ELSE 0 END) as civilians
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'militar'
LEFT JOIN {$wpdb->prefix}usermeta um2 ON e.user_id = um2.user_id AND um2.meta_key = 'efetivo_dcta'
WHERE {$WHERE_ACTIVITY}
AND e.status IN ('Approved','Waiting List','Under Analysis')
GROUP BY e.user_id
", ARRAY_A);
$military_dcta_count = 0;
$military_outside_count = 0;
$civilian_count = 0;
foreach ($results10 as $row) {
if ($row['military_dcta'] > 0) $military_dcta_count++;
elseif ($row['military_outside'] > 0) $military_outside_count++;
elseif ($row['civilians'] > 0) $civilian_count++;
}
$total_in_person_count = $military_dcta_count + $military_outside_count + $civilian_count;
$labels10 = json_encode(['Military DCTA', 'Military Outside', 'Civilian', 'Total In Person']);
$counts10 = json_encode([$military_dcta_count, $military_outside_count, $civilian_count, $total_in_person_count]);
// ---------- 13) Q11 Presença Main Event (somente se a atividade selecionada for Main Event) ----------
$labels11 = json_encode(['Attended (Yes)', 'Did Not Attend (No or Empty)']);
$counts11 = json_encode([0, 0]);
$show_q11 = ($selected_activity_type === 'Main Event' && in_array($selected_activity_modality, $in_person_modalities, true));
if ($show_q11) {
$results11 = $wpdb->get_results($wpdb->prepare("
SELECT DISTINCT e.user_id, ac.attended
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.activity_id = %d
AND e.status = 'Approved'
", $selected_activity_id), ARRAY_A);
$attended_yes = [];
$attended_no_or_empty = [];
foreach ($results11 as $row) {
$uid = $row['user_id'];
if ($row['attended'] === 'yes') {
if (!in_array($uid, $attended_yes, true)) $attended_yes[] = $uid;
} else { // 'no' / '' / NULL
if (!in_array($uid, $attended_no_or_empty, true)) $attended_no_or_empty[] = $uid;
}
}
$labels11 = json_encode(['Attended (Yes)', 'Did Not Attend (No or Empty)']);
$counts11 = json_encode([count($attended_yes), count($attended_no_or_empty)]);
}
// ---------- 14) Q12 Presença Short-courses (somente se a atividade selecionada for Short-course) ----------
$labels12 = json_encode([]);
$attended_yes_data = json_encode([]);
$attended_no_or_empty_data = json_encode([]);
$course_legend = [];
$show_q12 = ($selected_activity_type === 'Short-course' && in_array($selected_activity_modality, $in_person_modalities, true));
if ($show_q12) {
$results12 = $wpdb->get_results($wpdb->prepare("
SELECT DISTINCT e.user_id, ac.attended, a.name as course_name
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE e.activity_id = %d
AND e.status = 'Approved'
", $selected_activity_id), ARRAY_A);
$short_courses = []; // para compatibilidade com seu layout original
foreach ($results12 as $row) {
$course = $row['course_name'];
$uid = $row['user_id'];
if (!isset($short_courses[$course])) {
$short_courses[$course] = ['attended_yes' => [], 'attended_no_or_empty' => []];
}
if ($row['attended'] === 'yes') {
if (!in_array($uid, $short_courses[$course]['attended_yes'], true))
$short_courses[$course]['attended_yes'][] = $uid;
} else {
if (!in_array($uid, $short_courses[$course]['attended_no_or_empty'], true))
$short_courses[$course]['attended_no_or_empty'][] = $uid;
}
}
$labels12_arr = [];
$yes_arr = [];
$no_arr = [];
$legend = [];
$i = 1;
foreach ($short_courses as $course_name => $data) {
$label = "Short-course " . $i++;
$labels12_arr[] = $label;
$yes_arr[] = count($data['attended_yes']);
$no_arr[] = count($data['attended_no_or_empty']);
$legend[$label] = $course_name;
}
$labels12 = json_encode($labels12_arr);
$attended_yes_data = json_encode($yes_arr);
$attended_no_or_empty_data = json_encode($no_arr);
$course_legend = $legend;
}
// ---------- 15) GRID + CHARTS (seu HTML original, intacto) ----------
echo '<div class="dashboard-grid" style="display:flex; flex-wrap:wrap; overflow-x:auto; gap:20px;">';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="regionChart" width="400" height="200"></canvas>
</div>';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="formacaoChart" width="400" height="200"></canvas>
</div>';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="enrollmentChart" width="400" height="200"></canvas>
</div>';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="circuloChart" width="400" height="200"></canvas>
</div>';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="militarChart" width="400" height="200"></canvas>
</div>';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="nonMilitarChart" width="400" height="200"></canvas>
</div>';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="nationalityChart" width="400" height="200"></canvas>
</div>';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="genderChart" width="400" height="200"></canvas>
</div>';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="genderMilitaryChart" width="400" height="200"></canvas>
</div>';
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="totalCiviliansMilitariesDCTA_Outside" width="400" height="200"></canvas>
</div>';
if ($show_q11) {
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="totalEnrollmentAttendanceMainEvent" width="400" height="200"></canvas>
</div>';
}
if ($show_q12) {
echo '<div class="dashboard-item" style="flex:1 1 25%; min-width:400px; background:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); padding:20px;">
<canvas id="totalEnrollmentAttendanceShortCourses" width="400" height="200"></canvas>
</div>';
}
echo '</div>'; // grid
// ---------- 16) TABELAS (filtradas pela atividade selecionada) ----------
// Híbrido Main Event (mostrará "No data found" se a atividade escolhida não for híbrida/main event)
$summary_counts1 = $wpdb->get_results($wpdb->prepare("
SELECT
a.name as activity_name,
a.slots,
COUNT(e.id) as total_requests,
SUM(CASE WHEN e.status = 'Enrollment Canceled by User' THEN 1 ELSE 0 END) as canceled_by_user,
SUM(CASE WHEN e.status = 'Waiting List' THEN 1 ELSE 0 END) as waiting_list,
SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as approved,
SUM(CASE WHEN e.status = 'Not Approved' THEN 1 ELSE 0 END) as not_approved,
SUM(CASE WHEN e.status = 'Under Analysis' THEN 1 ELSE 0 END) as under_analysis,
a.slots - SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as available_slots,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Sim' THEN 1 ELSE 0 END) as military_dcta,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Não' THEN 1 ELSE 0 END) as military_outside,
SUM(CASE WHEN um1.meta_value = 'Não' THEN 1 ELSE 0 END) as civilians
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'militar'
LEFT JOIN {$wpdb->prefix}usermeta um2 ON e.user_id = um2.user_id AND um2.meta_key = 'efetivo_dcta'
WHERE a.modality = 'Hybrid' AND a.id = %d
GROUP BY a.name, a.slots
", $selected_activity_id));
echo '<h3>Hybrid Enrollment Summary</h3>';
echo '<div class="responsive-table">';
echo '<table id="summary-table-1" class="display" style="width:100%; margin:0; padding:0; background-color:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); text-align:center;">
<thead>
<tr>
<th>Activity Name</th>
<th>Enrollment Canceled by User</th>
<th>Waiting List</th>
<th>Approved</th>
<th>Not Approved</th>
<th>Under Analysis</th>
<th>Military (DCTA)</th>
<th>Military (Outside)</th>
<th>Civilians</th>
<th>Total Enrollment Requests</th>
<th>Enrollment Availables</th>
<th>Slots</th>
</tr>
</thead>
<tbody>';
if ($summary_counts1) {
foreach ($summary_counts1 as $summary) {
echo '<tr>
<td>' . esc_html($summary->activity_name) . '</td>
<td>' . esc_html($summary->canceled_by_user) . '</td>
<td>' . esc_html($summary->waiting_list) . '</td>
<td>' . esc_html($summary->approved) . '</td>
<td>' . esc_html($summary->not_approved) . '</td>
<td>' . esc_html($summary->under_analysis) . '</td>
<td>' . esc_html($summary->military_dcta) . '</td>
<td>' . esc_html($summary->military_outside) . '</td>
<td>' . esc_html($summary->civilians) . '</td>
<td>' . esc_html($summary->total_requests) . '</td>
<td>' . esc_html($summary->available_slots) . '</td>
<td>' . esc_html($summary->slots) . '</td>
</tr>';
}
} else {
echo '<tr><td colspan="12" style="text-align:center;">No data found</td></tr>';
}
echo '</tbody></table></div>';
// In-person Main Event (filtrado pela atividade)
$summary_counts2 = $wpdb->get_results($wpdb->prepare("
SELECT
a.name as activity_name,
a.slots,
COUNT(e.id) as total_requests,
SUM(CASE WHEN e.status = 'Enrollment Canceled by User' THEN 1 ELSE 0 END) as canceled_by_user,
SUM(CASE WHEN e.status = 'Waiting List' THEN 1 ELSE 0 END) as waiting_list,
SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as approved,
SUM(CASE WHEN e.status = 'Not Approved' THEN 1 ELSE 0 END) as not_approved,
SUM(CASE WHEN e.status = 'Under Analysis' THEN 1 ELSE 0 END) as under_analysis,
a.slots - SUM(CASE WHEN e.status = 'Approved' THEN 1 ELSE 0 END) as available_slots,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Sim' THEN 1 ELSE 0 END) as military_dcta,
SUM(CASE WHEN um1.meta_value = 'Sim' AND um2.meta_value = 'Não' THEN 1 ELSE 0 END) as military_outside,
SUM(CASE WHEN um1.meta_value = 'Não' THEN 1 ELSE 0 END) as civilians
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}usermeta um1 ON e.user_id = um1.user_id AND um1.meta_key = 'militar'
LEFT JOIN {$wpdb->prefix}usermeta um2 ON e.user_id = um2.user_id AND um2.meta_key = 'efetivo_dcta'
WHERE a.modality = 'In-person' AND a.id = %d
GROUP BY a.name, a.slots
", $selected_activity_id));
echo '<h3>In-person Enrollment Summary</h3>';
echo '<div class="responsive-table">';
echo '<table id="summary-table-2" class="display" style="width:100%; margin:0; padding:0; background-color:#f0f0f0; border:1px solid #ccc; box-shadow:0 2px 4px rgba(0,0,0,.1); text-align:center;">
<thead>
<tr>
<th>Activity Name</th>
<th>Enrollment Canceled by User</th>
<th>Waiting List</th>
<th>Approved</th>
<th>Not Approved</th>
<th>Under Analysis</th>
<th>Military (DCTA)</th>
<th>Military (Outside)</th>
<th>Civilians</th>
<th>Total Enrollment Requests</th>
<th>Enrollment Availables</th>
<th>Slots</th>
</tr>
</thead>
<tbody>';
if ($summary_counts2) {
foreach ($summary_counts2 as $summary) {
echo '<tr>
<td>' . esc_html($summary->activity_name) . '</td>
<td>' . esc_html($summary->canceled_by_user) . '</td>
<td>' . esc_html($summary->waiting_list) . '</td>
<td>' . esc_html($summary->approved) . '</td>
<td>' . esc_html($summary->not_approved) . '</td>
<td>' . esc_html($summary->under_analysis) . '</td>
<td>' . esc_html($summary->military_dcta) . '</td>
<td>' . esc_html($summary->military_outside) . '</td>
<td>' . esc_html($summary->civilians) . '</td>
<td>' . esc_html($summary->total_requests) . '</td>
<td>' . esc_html($summary->available_slots) . '</td>
<td>' . esc_html($summary->slots) . '</td>
</tr>';
}
} else {
echo '<tr><td colspan="12" style="text-align:center;">No data found</td></tr>';
}
echo '</tbody></table></div>';
// ---------- 17) JS (seu Chart.js original, só consumindo as variáveis novas) ----------
echo '
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
var ctx1 = document.getElementById("regionChart").getContext("2d");
new Chart(ctx1, {
type: "bar",
data: { labels: ' . $labels1 . ', datasets: [{ label:"Users by Region", data: ' . $counts1 . ',
backgroundColor:["rgba(255,99,132,0.2)","rgba(54,162,235,0.2)","rgba(255,206,86,0.2)","rgba(75,192,192,0.2)","rgba(153,102,255,0.2)"],
borderColor:["rgba(255,99,132,1)","rgba(54,162,235,1)","rgba(255,206,86,1)","rgba(75,192,192,1)","rgba(153,102,255,1)"],
borderWidth:1
}]},
options:{plugins:{title:{display:true,text:["Total In-Person Enrollments by Regions of Brazil","(Unique Users - Status: Approved, Under Analysis, and Waiting List)"]}},scales:{y:{beginAtZero:true}}}
});
var ctx2 = document.getElementById("formacaoChart").getContext("2d");
new Chart(ctx2, { type:"bar", data:{ labels: ' . $labels2 . ', datasets: ' . $datasets2 . '},
options:{plugins:{title:{display:true,text:["Total In-Person Enrollments by Academic Background","(Unique Users - Status: Approved, Under Analysis, and Waiting List)"]}},scales:{y:{beginAtZero:true}}}
});
var ctx3 = document.getElementById("enrollmentChart").getContext("2d");
new Chart(ctx3, { type:"bar",
data:{ labels: ' . $labels3 . ', datasets:[{ label:"Enrollment Types", data: ' . $counts3 . ',
backgroundColor:["rgba(75,192,192,0.2)","rgba(153,102,255,0.2)"],
borderColor:["rgba(75,192,192,1)","rgba(153,102,255,1)"], borderWidth:1
}]},
options:{plugins:{title:{display:true,text:["Total In-Person and Online Enrollments","(Unique Users - Status: Approved)"]}},scales:{y:{beginAtZero:true}}}
});
var ctx4 = document.getElementById("circuloChart").getContext("2d");
new Chart(ctx4, { type:"bar",
data:{ labels: ' . $labels4 . ', datasets:[{ label:"Circulo Hierárquico Distribution", data: ' . $counts4 . ',
backgroundColor:["rgba(255,99,132,0.2)","rgba(54,162,235,0.2)","rgba(255,206,86,0.2)","rgba(75,192,192,0.2)","rgba(153,102,255,0.2)","rgba(255,159,64,0.2)","rgba(201,203,207,0.2)"],
borderColor:["rgba(255,99,132,1)","rgba(54,162,235,1)","rgba(255,206,86,1)","rgba(75,192,192,1)","rgba(153,102,255,1)","rgba(255,159,64,1)","rgba(201,203,207,1)"],
borderWidth:1
}]},
options:{plugins:{title:{display:true,text:["Total Enrollments of Militaries by hierarquical circle","(Unique Users - Status: Approved)"]}},scales:{y:{beginAtZero:true}}}
});
var ctx5 = document.getElementById("militarChart").getContext("2d");
new Chart(ctx5, { type:"bar",
data:{ labels: ' . $labels5 . ', datasets:[{ label:"Militar Enrollment Types", data: ' . $counts5 . ',
backgroundColor:["rgba(75,192,192,0.2)","rgba(153,102,255,0.2)"],
borderColor:["rgba(75,192,192,1)","rgba(153,102,255,1)"], borderWidth:1
}]},
options:{plugins:{title:{display:true,text:["Total In-Person and Online Enrollments of Militaries","(Unique Users - Status: Approved)"]}},scales:{y:{beginAtZero:true}}}
});
var ctx6 = document.getElementById("nonMilitarChart").getContext("2d");
new Chart(ctx6, { type:"bar",
data:{ labels: ' . $labels6 . ', datasets:[{ label:"Non-Militar Enrollment Types", data: ' . $counts6 . ',
backgroundColor:["rgba(75,192,192,0.2)","rgba(153,102,255,0.2)"],
borderColor:["rgba(75,192,192,1)","rgba(153,102,255,1)"], borderWidth:1
}]},
options:{plugins:{title:{display:true,text:["Total In-Person and Online Enrollments of Civilians","(Unique Users - Status: Approved)"]}},scales:{y:{beginAtZero:true}}}
});
var ctx7 = document.getElementById("nationalityChart").getContext("2d");
new Chart(ctx7, { type:"bar",
data:{ labels: ' . $labels7 . ', datasets:[{ label:"Users by Nationality", data: ' . $counts7 . ',
backgroundColor:["rgba(75,192,192,0.2)","rgba(255,99,132,0.2)"],
borderColor:["rgba(75,192,192,1)","rgba(255,99,132,1)"], borderWidth:1
}]},
options:{plugins:{title:{display:true,text:["Total In-person and Online Enrollments by Nationality","(Unique Users - Status: Approved, Under Analysis, and Waiting List)"]}},scales:{y:{beginAtZero:true}}}
});
var ctx8 = document.getElementById("genderChart").getContext("2d");
new Chart(ctx8, { type:"bar",
data:{ labels: ' . $labels8 . ', datasets:[{ label:"Users by Gender", data: ' . $counts8 . ',
backgroundColor:["rgba(255,99,132,0.2)","rgba(54,162,235,0.2)"],
borderColor:["rgba(255,99,132,1)","rgba(54,162,235,1)"], borderWidth:1
}]},
options:{plugins:{title:{display:true,text:["Total In-person and Online Enrollments by Gender","(Unique Users - Status: Approved, Under Analysis, and Waiting List)"]}},scales:{y:{beginAtZero:true}}}
});
var ctx9 = document.getElementById("genderMilitaryChart").getContext("2d");
new Chart(ctx9, { type:"bar",
data:{ labels: ' . $labels9 . ', datasets:[{ label:"Military Users by Gender", data: ' . $counts9 . ',
backgroundColor:["rgba(255,99,132,0.2)","rgba(54,162,235,0.2)"],
borderColor:["rgba(255,99,132,1)","rgba(54,162,235,1)"], borderWidth:1
}]},
options:{plugins:{title:{display:true,text:["Total In-person and Online Military Enrollments by Gender","(Unique Users - Status: Approved, Under Analysis, and Waiting List)"]}},scales:{y:{beginAtZero:true}}}
});
var ctx10 = document.getElementById("totalCiviliansMilitariesDCTA_Outside").getContext("2d");
new Chart(ctx10, { type:"bar",
data:{ labels: ' . $labels10 . ', datasets:[{ label:"Total In-Person Distribution", data: ' . $counts10 . ',
backgroundColor:["rgba(75,192,192,0.2)","rgba(54,162,235,0.2)","rgba(255,206,86,0.2)","rgba(153,102,255,0.2)"],
borderColor:["rgba(75,192,192,1)","rgba(54,162,235,1)","rgba(255,206,86,1)","rgba(153,102,255,1)"], borderWidth:1
}]},
options:{plugins:{title:{display:true,text:["Total In-person Enrollment (Military DCTA, Military Outside, Civilian, Total)","(Unique Users - Status: Approved, Under Analysis, and Waiting List)"]}},scales:{y:{beginAtZero:true}}}
});
' . ($show_q11 ? '
var ctx11 = document.getElementById("totalEnrollmentAttendanceMainEvent").getContext("2d");
new Chart(ctx11, { type:"bar",
data:{ labels: ' . $labels11 . ', datasets:[{ label:"In-person Attendance of Main Event", data: ' . $counts11 . ',
backgroundColor:["rgba(75,192,192,0.2)","rgba(255,99,132,0.2)"],
borderColor:["rgba(75,192,192,1)","rgba(255,99,132,1)"], borderWidth:1
}]},
options:{plugins:{title:{display:true,text:"Total In-person Enrollment Attendance of Main Event (Users Approved)"}},scales:{y:{beginAtZero:true}}}
});
' : '') . '
' . ($show_q12 ? '
var ctx12 = document.getElementById("totalEnrollmentAttendanceShortCourses").getContext("2d");
new Chart(ctx12, { type:"bar",
data:{ labels: ' . $labels12 . ', datasets:[
{ label:"Attended (Yes)", data: ' . $attended_yes_data . ', backgroundColor:"rgba(75,192,192,0.2)", borderColor:"rgba(75,192,192,1)", borderWidth:1 },
{ label:"Did Not Attend", data: ' . $attended_no_or_empty_data . ', backgroundColor:"rgba(255,99,132,0.2)", borderColor:"rgba(255,99,132,1)", borderWidth:1 }
]},
options:{plugins:{title:{display:true,text:["Total In-person Enrollment Attendance of Short-Courses","(Unique User - Status: Approved)"]}},scales:{y:{beginAtZero:true}}}
});
// legenda cursos
var courseLegend = ' . json_encode($course_legend) . ';
if (courseLegend && Object.keys(courseLegend).length){
var legendDiv = document.createElement("div");
legendDiv.style.marginTop = "20px";
legendDiv.innerHTML = "<strong>Short-course Legend:</strong><br>";
for (var key in courseLegend) {
if (courseLegend.hasOwnProperty(key)) {
legendDiv.innerHTML += key + ": " + courseLegend[key] + "<br>";
}
}
document.getElementById("totalEnrollmentAttendanceShortCourses").parentNode.appendChild(legendDiv);
}' : '') . '
});
</script>
';
echo '</div>'; // .wrap
return ob_get_clean();
}
add_shortcode('Dashboard', 'frontendDashboard');
require_once plugin_dir_path(__FILE__) . 'includes/apoio.php';
require_once plugin_dir_path(__FILE__) . 'includes/data_sharing.php';
require_once plugin_dir_path(__FILE__) . 'includes/enrollments.php';
function enrollmentSubmenuPage()
{
global $wpdb;
$current_user = wp_get_current_user();
$user_id = $current_user->ID;
// Define the additional meta keys
$additional_meta_keys = [
'forca',
'full_name',
'posto',
'militar',
'instituição',
'nacionalidade',
'efetivo_dcta',
'cidade',
'estado',
'areaatividadeprincipal',
'setordeatuacao',
'cargofuncao',
'ehativa',
'circulo_hierarquico',
'pais',
'formacao_academica',
'regiao_do_brasil',
'genero'
];
// Handle saving additional features selection
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['additional_features'])) {
$selected_meta_keys = array_intersect($additional_meta_keys, $_POST['additional_features']);
update_user_meta($user_id, 'selected_additional_features', $selected_meta_keys);
} else {
$selected_meta_keys = get_user_meta($user_id, 'selected_additional_features', true);
if (!$selected_meta_keys) {
$selected_meta_keys = [];
}
}
// Handle status update
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['apply_status']) && isset($_POST['selected_enrollments'])) {
$new_status = sanitize_text_field($_POST['new_status']);
$selected_enrollments = array_map('intval', $_POST['selected_enrollments']);
//error_log('New Status: ' . $new_status);
//error_log('Selected Enrollments: ' . print_r($selected_enrollments, true));
if (!empty($selected_enrollments)) {
foreach ($selected_enrollments as $enrollment_id) {
//error_log('Processing enrollment ID: ' . $enrollment_id);
$updated = $wpdb->update(
"{$wpdb->prefix}sige_enrollments",
['status' => $new_status],
['id' => $enrollment_id]
);
if ($updated === false) {
echo '<div class="notice notice-error"><p>Error updating enrollment ID ' . $enrollment_id . '.</p></div>';
//error_log('Error updating enrollment ID: ' . $enrollment_id);
} else {
//error_log('Enrollment ID ' . $enrollment_id . ' updated to status: ' . $new_status);
}
if ($new_status == 'Not Approved') {
// Fetch event_name_id, modality, and type of the updated enrollment
$activity_info = $wpdb->get_row($wpdb->prepare(
"SELECT a.event_name_id, a.modality, a.type, e.user_id
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE e.id = %d",
$enrollment_id
));
//error_log('Activity Info: ' . print_r($activity_info, true));
// Proceed only if the activity type is "Main Event"
if ($activity_info && $activity_info->type === 'Main Event') {
$event_name_id = $activity_info->event_name_id;
$main_event_modality = $activity_info->modality;
$enrollment_user_id = $activity_info->user_id;
//error_log('Event Name ID: ' . $event_name_id);
//error_log('Main Event Modality: ' . $main_event_modality);
//error_log('User ID for Enrollment: ' . $enrollment_user_id);
// Determine the condition for updating related activities
$modality_condition = ($main_event_modality == 'Online') ? "AND a.modality = 'Online'" : "AND a.modality != 'Online'";
//error_log('Modality Condition: ' . $modality_condition);
// Update status of related activities based on the main event modality
$update_result = $wpdb->query($wpdb->prepare(
"UPDATE {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
SET e.status = 'Not Approved'
WHERE a.event_name_id = %d $modality_condition AND e.user_id = %d",
$event_name_id,
$enrollment_user_id
));
if ($update_result === false) {
//error_log('Error updating related activities for user ID: ' . $enrollment_user_id);
} else {
//error_log('Related activities updated for user ID: ' . $enrollment_user_id);
}
} else {
//error_log('Activity is not a Main Event or no activity info found.');
}
}
}
echo '<div class="notice notice-success"><p>Enrollment status updated successfully.</p></div>';
//error_log('Enrollment status updated successfully.');
} else {
echo '<div class="notice notice-error"><p>Please select at least one enrollment.</p></div>';
//error_log('No enrollments selected.');
}
}
// Fetch enrollments with additional meta data if selected
$meta_selects = '';
$meta_joins = '';
foreach ($selected_meta_keys as $meta_key) {
$meta_selects .= ", um_$meta_key.meta_value as $meta_key";
$meta_joins .= " LEFT JOIN {$wpdb->prefix}usermeta um_$meta_key ON um_$meta_key.user_id = u.ID AND um_$meta_key.meta_key = '$meta_key'";
}
$query = "
SELECT e.*, a.name as activity_name, a.modality, en.acronym, u.user_email $meta_selects
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}sige_event_names en ON a.event_name_id = en.id
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
$meta_joins
";
$enrollments = $wpdb->get_results($query);
// Process the unserialization of meta fields if necessary
foreach ($enrollments as &$enrollment) {
foreach ($additional_meta_keys as $meta_key) {
if (isset($enrollment->$meta_key)) {
// Unserialize the value if it's serialized
$unserialized_value = maybe_unserialize($enrollment->$meta_key);
// If the result is an array, extract the first element
if (is_array($unserialized_value)) {
$enrollment->$meta_key = $unserialized_value[0];
} else {
$enrollment->$meta_key = $unserialized_value;
}
}
}
}
// Log the corrected enrollments data
//error_log('Corrected Enrollments Data: ' . print_r($enrollments, true));
// Display additional features form
echo '<h3>Additional Features</h3>';
echo '<button id="toggle-features" class="button button-secondary">Expand Features</button>';
echo '<div id="features-container" style="display: none; width: 100%; margin-top: 20px;">';
echo '<form method="post" action="" style="width: 100%;">';
foreach ($additional_meta_keys as $meta_key) {
$checked = in_array($meta_key, $selected_meta_keys) ? 'checked' : '';
echo '<label style="display: block; margin-bottom: 10px;"><input type="checkbox" name="additional_features[]" value="' . $meta_key . '" ' . $checked . '> ' . ucfirst(str_replace('_', ' ', $meta_key)) . '</label>';
}
echo '<input type="submit" value="Apply" class="button button-primary" style="margin-top: 20px;">';
echo '</form>';
echo '</div>';
// Display the enrollments table
echo '<h3>Existing Enrollments</h3>';
echo '<div style="padding-right: 20px;">';
echo '<form method="post" action="">';
echo '<input type="hidden" id="selected-meta-keys" value="' . esc_attr(json_encode(array_values($selected_meta_keys))) . '">';
echo '<button id="export-csv" class="button button-secondary" style="margin-bottom: 20px;">Export to CSV</button>';
echo '<table id="enrollments-table" class="display">
<thead>
<tr>
<th style="text-align: center;"><input type="checkbox" id="select_all"> Select All</th>
<th>Acronym</th>
<th>Activity Name</th>
<th>Modality</th>
<th>User Email</th>
<th>Enrollment Date</th>
<th>Status</th>';
foreach ($selected_meta_keys as $meta_key) {
echo '<th>' . ucfirst(str_replace('_', ' ', $meta_key)) . '</th>';
}
echo '</tr></thead><tbody>';
if ($enrollments) {
foreach ($enrollments as $enrollment) {
$row_style = '';
$checkbox_disabled = '';
if ($enrollment->status == 'Enrollment Canceled by User') {
$row_style = 'style="background-color: #f38d8d;"';
$checkbox_disabled = 'disabled';
} elseif ($enrollment->status == 'Waiting List') {
$row_style = 'style="background-color: #e3db69;"';
} elseif ($enrollment->status == 'Approved') {
$row_style = 'style="background-color: #33ff7a;"';
} elseif ($enrollment->status == 'Not Approved') {
$row_style = 'style="background-color: #bc97cd;"';
} elseif ($enrollment->status == 'Under Analysis') {
$row_style = 'style="background-color: #5ecac7;"';
}
$formatted_date = date('d-m-Y', strtotime($enrollment->enrollment_date));
echo "<tr $row_style>
<td style='text-align: center;'><input type='checkbox' name='selected_enrollments[]' value='{$enrollment->id}' $checkbox_disabled></td>
<td style='font-weight: bold;'>{$enrollment->acronym}</td>
<td style='font-weight: bold;'>{$enrollment->activity_name}</td>
<td style='font-weight: bold;'>{$enrollment->modality}</td>
<td style='font-weight: bold;'>{$enrollment->user_email}</td>
<td style='font-weight: bold;'>$formatted_date</td>
<td style='font-weight: bold;'>{$enrollment->status}</td>";
foreach ($selected_meta_keys as $meta_key) {
echo '<td style="font-weight: bold;">' . esc_html($enrollment->$meta_key) . '</td>';
}
echo '</tr>';
}
} else {
echo '<tr><td colspan="7" style="text-align: center; font-weight: bold;">No enrollments found</td></tr>';
}
echo '</tbody></table>';
if (isset($_POST['apply_status'])) {
$new_status = $_POST['new_status'];
$selected_enrollments = $_POST['selected_enrollments'];
if (!empty($selected_enrollments) && !empty($new_status)) {
foreach ($selected_enrollments as $enrollment_id) {
// Atualize o status da inscrição no banco de dados
$wpdb->update(
"{$wpdb->prefix}sige_enrollments",
array('status' => $new_status),
array('id' => $enrollment_id)
);
// Obtenha o ID do usuário e o ID da atividade associados à inscrição
$enrollment_data = $wpdb->get_row($wpdb->prepare("
SELECT user_id, activity_id
FROM {$wpdb->prefix}sige_enrollments
WHERE id = %d", $enrollment_id));
// Envie a notificação por e-mail
send_email_notification($enrollment_data->user_id, $new_status, $enrollment_data->activity_id);
}
}
}
if ($enrollments) {
echo '<div style="margin-top: 20px;">
<select name="new_status" required>
<option value="Waiting List">Waiting List</option>
<option value="Not Approved">Not Approved</option>
<option value="Approved">Approved</option>
</select>
<input type="submit" name="apply_status" value="Apply" class="button button-primary">';
echo '</div>';
}
echo '</form>';
echo '</div>';
// Add the color legend
echo '<div style="margin-top: 20px; display: flex; align-items: center;">
<h3 style="margin-right: 20px;">Legend:</h3>';
echo '<div style="display: flex; flex-wrap: wrap; gap: 10px;">
<span style="background-color: #f38d8d; padding: 5px; border-radius: 3px; width: 150px; text-align: center;">Enrollment Canceled by User</span>
<span style="background-color: #e3db69; padding: 5px; border-radius: 3px; width: 150px; text-align: center;">Waiting List</span>
<span style="background-color: #33ff7a; padding: 5px; border-radius: 3px; color: white; width: 150px; text-align: center;">Approved</span>
<span style="background-color: #bc97cd; padding: 5px; border-radius: 3px; width: 150px; text-align: center;">Not Approved</span>
<span style="background-color: #5ecac7; padding: 5px; border-radius: 3px; width: 150px; text-align: center;">Under Analysis</span>
</div></div>';
echo '<script>
jQuery(document).ready(function($) {
$("#enrollments-table").DataTable({
"scrollX": true,
"autoWidth": false,
"pageLength": 10, // Set the default number of entries to show
"lengthMenu": [ [10, 25, 50, 100, 200, 500, -1], [10, 25, 50, 100, 200, 500, "All"] ] // Add custom options for the number of entries
});
$("#select_all").click(function() {
$("input[type=checkbox]").not(":disabled").prop("checked", this.checked);
});
$("#toggle-features").click(function() {
$("#features-container").slideToggle();
$(this).text(function(i, text){
return text === "Expand Features" ? "Collapse Features" : "Expand Features";
});
});
$("#export-csv").click(function(e) {
e.preventDefault();
const selectedMetaKeys = JSON.parse($("#selected-meta-keys").val());
const now = new Date();
const formattedDate = `${("0" + now.getDate()).slice(-2)}_${("0" + (now.getMonth() + 1)).slice(-2)}_${now.getFullYear()}_${("0" + now.getHours()).slice(-2)}_${("0" + now.getMinutes()).slice(-2)}_${("0" + now.getSeconds()).slice(-2)}`;
const filename = `enrollments_${formattedDate}.csv`;
let csvContent = "data:text/csv;charset=utf-8,";
csvContent += "Acronym;Activity Name;Modality;User Email;Enrollment Date;Status"; // Change comma to semicolon
// Add selected meta keys to CSV header
if (selectedMetaKeys.length > 0) {
selectedMetaKeys.forEach(function(metaKey) {
csvContent += ";" + metaKey.charAt(0).toUpperCase() + metaKey.slice(1).replace(/_/g, " "); // Change comma to semicolon
});
}
csvContent += "\n";
$("#enrollments-table tbody tr").each(function() {
const row = $(this);
const acronym = row.find("td:nth-child(2)").text().trim();
const activityName = row.find("td:nth-child(3)").text().trim();
const modality = row.find("td:nth-child(4)").text().trim();
const userEmail = row.find("td:nth-child(5)").text().trim();
const enrollmentDate = row.find("td:nth-child(6)").text().trim();
const status = row.find("td:nth-child(7)").text().trim();
let rowData = `${acronym};${activityName};${modality};${userEmail};${enrollmentDate};${status}`; // Change comma to semicolon
if (selectedMetaKeys.length > 0) {
selectedMetaKeys.forEach(function(metaKey, index) {
rowData += ";" + row.find("td:nth-child(" + (8 + index) + ")").text().trim(); // Change comma to semicolon
});
}
csvContent += rowData + "\n";
});
const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
});
</script>';
}
// Function to display Email Options content
function emailSettingsSubmenuPage()
{
global $wpdb;
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['save_email_settings'])) {
$id = sanitize_text_field($_POST['id']);
$email_sender = sanitize_email($_POST['email_sender']);
$email_subject = sanitize_text_field($_POST['email_subject']);
// Allow more HTML tags
$allowed_tags = array(
'p' => array(),
'a' => array(
'href' => array(),
'title' => array(),
),
'strong' => array(),
'em' => array(),
'br' => array(),
'ul' => array(),
'ol' => array(),
'li' => array(),
'span' => array(
'style' => array(),
),
'div' => array(
'style' => array(),
),
);
$email_message = wp_kses($_POST['notice'], $allowed_tags);
if ($id === 'yes' || $id === 'no') {
$table = "{$wpdb->prefix}sige_attendance_email_messages";
$real_status_action = $id === 'yes' ? 'yes' : 'no';
$existing_entry = $wpdb->get_var($wpdb->prepare("SELECT id FROM $table WHERE status_action = %s", $real_status_action));
if ($existing_entry) {
$wpdb->update(
$table,
[
'email_sender' => $email_sender,
'email_subject' => $email_subject,
'email_message' => $email_message
],
['id' => $existing_entry]
);
} else {
$wpdb->insert(
$table,
[
'status_action' => $real_status_action,
'email_sender' => $email_sender,
'email_subject' => $email_subject,
'email_message' => $email_message
]
);
}
} else {
$table = strpos($id, 'attendance_') === 0 ? "{$wpdb->prefix}sige_attendance_email_messages" : "{$wpdb->prefix}sige_email_messages";
$real_id = strpos($id, 'attendance_') === 0 ? substr($id, 11) : $id;
$wpdb->update(
$table,
[
'email_sender' => $email_sender,
'email_subject' => $email_subject,
'email_message' => $email_message
],
['id' => $real_id]
);
}
echo '<div class="notice notice-success"><p>Email settings saved successfully.</p></div>';
}
$email_messages = $wpdb->get_results("SELECT id, status_action, email_sender, email_subject, email_message FROM {$wpdb->prefix}sige_email_messages", ARRAY_A);
$attendance_messages = $wpdb->get_results("SELECT CONCAT('attendance_', id) AS id, status_action, email_sender, email_subject, email_message FROM {$wpdb->prefix}sige_attendance_email_messages", ARRAY_A);
$messages = array_merge($email_messages, $attendance_messages);
$status_action_mapping = [
'yes' => 'Attended',
'no' => 'Not Attended'
];
echo '<div class="wrap"><h2>Email Settings</h2><form method="post" id="email_settings_form"><table class="form-table">';
echo '<tr valign="top">
<th scope="row">Choose Status Action</th>
<td>
<select name="id" id="status_action_select" required>';
foreach ($messages as $message) {
$display_status_action = isset($status_action_mapping[$message['status_action']]) ? $status_action_mapping[$message['status_action']] : $message['status_action'];
echo '<option value="' . esc_attr($message['id']) . '">' . esc_html($display_status_action) . '</option>';
}
echo ' </select>
</td>
</tr>';
$default_email_sender = $messages[0]['email_sender'];
$default_email_subject = $messages[0]['email_subject'];
$default_email_message = $messages[0]['email_message'];
echo '<tr valign="top">
<th scope="row">Email Sender</th>
<td><input type="email" name="email_sender" id="email_sender" value="' . esc_attr($default_email_sender) . '" style="width: 100%;" required /></td>
</tr>
<tr valign="top">
<th scope="row">Email Subject</th>
<td><input type="text" name="email_subject" id="email_subject" value="' . esc_attr($default_email_subject) . '" style="width: 100%;" required /></td>
</tr>
<tr valign="top">
<th scope="row">Email Message</th>
<td>';
wp_editor($default_email_message, 'notice', array(
'textarea_name' => 'notice',
'textarea_rows' => 10,
'wpautop' => false,
'media_buttons' => true,
'teeny' => false,
'tinymce' => array(
'valid_elements' => '*[*]',
'extended_valid_elements' => 'p[*],a[*],span[*],div[*]',
),
'quicktags' => true,
'editor_class' => 'wp-editor-area'
));
echo '</td>
</tr>
</table><input type="submit" name="save_email_settings" value="Save Settings" class="button button-primary" /></form></div>';
echo '<script>
document.addEventListener("DOMContentLoaded", function() {
const messages = ' . json_encode($messages) . ';
const selectElement = document.getElementById("status_action_select");
const emailSenderInput = document.getElementById("email_sender");
const emailSubjectInput = document.getElementById("email_subject");
selectElement.addEventListener("change", function() {
const selectedId = this.value;
let selectedMessage;
if (selectedId === "yes") {
selectedMessage = messages.find(message => message.status_action === "Attended");
} else if (selectedId === "no") {
selectedMessage = messages.find(message => message.status_action === "Not Attended");
} else {
selectedMessage = messages.find(message => message.id == selectedId);
}
if (selectedMessage) {
emailSenderInput.value = selectedMessage.email_sender;
emailSubjectInput.value = selectedMessage.email_subject;
tinymce.get("notice").setContent(selectedMessage.email_message);
}
});
});
</script>';
}
function export_activities_to_csv()
{
if (isset($_POST['export_activities_csv'])) {
global $wpdb;
$activities = $wpdb->get_results("
SELECT a.*, p.place, s.full_name as speaker, e.name as event_name
FROM {$wpdb->prefix}sige_activities a
LEFT JOIN {$wpdb->prefix}sige_place p ON a.place_id = p.id
LEFT JOIN {$wpdb->prefix}sige_speakers s ON a.speaker_id = s.id
LEFT JOIN {$wpdb->prefix}sige_event_names e ON a.event_name_id = e.id
");
if ($activities) {
$filename = "activities_" . date('Ymd_His') . ".csv";
header('Content-Type: text/csv');
header('Content-Disposition: attachment;filename=' . $filename);
$output = fopen('php://output', 'w');
// Set the column headers
fputcsv($output, array(
'Activity Name',
'Description',
'Start Date',
'Start Time',
'End Date',
'End Time',
'Type',
'Modality',
'Status',
'Speaker',
'Curriculum',
'Place',
'Event Name',
'Security Credential',
'Chair',
'Target Audience',
'Slots',
'Matching Key'
));
// Output each row of the data
foreach ($activities as $activity) {
fputcsv($output, array(
$activity->name,
$activity->description,
$activity->start_date,
$activity->start_time,
$activity->end_date,
$activity->end_time,
$activity->type,
$activity->modality,
$activity->status,
$activity->speaker,
$activity->curriculum,
$activity->place,
$activity->event_name,
$activity->security_credential,
$activity->chair,
$activity->target_audience,
$activity->slots,
$activity->activity_matching_key
));
}
fclose($output);
exit;
}
}
}
add_action('admin_init', 'export_activities_to_csv');
function enqueue_jquery_ui()
{
wp_enqueue_script('jquery-ui-tabs');
wp_enqueue_style('jquery-ui-css', 'https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css');
}
add_action('wp_enqueue_scripts', 'enqueue_jquery_ui');
function enqueue_datatables_assets_admin()
{
wp_enqueue_script('jquery');
wp_enqueue_script('datatables-js', 'https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js', array('jquery'), null, true);
wp_enqueue_style('datatables-css', 'https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css');
wp_enqueue_script('datatables-fixedcolumns-js', 'https://cdn.datatables.net/fixedcolumns/3.3.3/js/dataTables.fixedColumns.min.js', array('datatables-js'), null, true);
wp_enqueue_style('datatables-fixedcolumns-css', 'https://cdn.datatables.net/fixedcolumns/3.3.3/css/fixedColumns.dataTables.min.css');
}
add_action('admin_enqueue_scripts', 'enqueue_datatables_assets_admin');
function enqueue_datatables_assets_frontend()
{
wp_enqueue_script('jquery');
wp_enqueue_script('datatables-js', 'https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js', array('jquery'), null, true);
wp_enqueue_style('datatables-css', 'https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css');
wp_enqueue_script('datatables-fixedcolumns-js', 'https://cdn.datatables.net/fixedcolumns/3.3.3/js/dataTables.fixedColumns.min.js', array('datatables-js'), null, true);
wp_enqueue_style('datatables-fixedcolumns-css', 'https://cdn.datatables.net/fixedcolumns/3.3.3/css/fixedColumns.dataTables.min.css');
}
add_action('wp_enqueue_scripts', 'enqueue_datatables_assets_frontend');
function enqueue_html5_qrcode_script()
{
wp_enqueue_script('html5-qrcode', 'https://unpkg.com/html5-qrcode@2.3.8/html5-qrcode.min.js', [], null, true);
}
add_action('admin_enqueue_scripts', 'enqueue_html5_qrcode_script');
add_action('wp_enqueue_scripts', 'enqueue_html5_qrcode_script');
// Handle AJAX request to save confidentiality response
function save_confidentiality_response()
{
global $wpdb;
if (isset($_POST['user_id']) && isset($_POST['year']) && isset($_POST['response'])) {
$user_id = intval($_POST['user_id']);
$year = intval($_POST['year']);
$response = sanitize_text_field($_POST['response']);
$wpdb->insert(
"{$wpdb->prefix}sige_confidentiality_user_option",
[
'user_id' => $user_id,
'year' => $year,
'sharing_information' => $response
]
);
}
wp_die();
}
add_action('wp_ajax_save_confidentiality_response', 'save_confidentiality_response');
add_action('wp_ajax_nopriv_save_confidentiality_response', 'save_confidentiality_response');
function send_email_notification($user_id, $status, $activity_id)
{
global $wpdb;
$user = get_userdata($user_id);
$email_to = $user->user_email;
// Check if status is 'yes' or 'no'
if ($status === 'yes' || $status === 'no') {
$email_data = $wpdb->get_row($wpdb->prepare("
SELECT email_subject, email_message FROM {$wpdb->prefix}sige_attendance_email_messages
WHERE status_action = %s", $status));
} else {
$email_data = $wpdb->get_row($wpdb->prepare("
SELECT email_subject, email_message FROM {$wpdb->prefix}sige_email_messages
WHERE status_action = %s", $status));
}
$activity_data = $wpdb->get_row($wpdb->prepare("
SELECT name, start_date, start_time, end_time
FROM {$wpdb->prefix}sige_activities WHERE id = %d", $activity_id));
$first_name = get_user_meta($user_id, "first_name", true);
$last_name = get_user_meta($user_id, "last_name", true);
$full_name = get_user_meta($user_id, "full_name", true);
$nacionalidade = get_user_meta($user_id, "nacionalidade", true);
// Replace placeholders with user data
$email_data->email_message = str_replace("[first_name]", $first_name, $email_data->email_message);
$email_data->email_message = str_replace("[last_name]", $last_name, $email_data->email_message);
$email_data->email_message = str_replace("[full_name]", $full_name, $email_data->email_message);
// Replace placeholders with activity data
foreach ($activity_data as $key => $value) {
$email_data->email_message = str_replace($key, $value, $email_data->email_message);
}
// Filter email content based on 'nacionalidade'
if ($nacionalidade === 'Estrangeiro') {
// Remove content for 'brasileiro'
$email_data->email_message = preg_replace('/\[brasileiro\/start\](.*?)\[brasileiro\/finish\]/s', '', $email_data->email_message);
// Keep content for 'estrangeiro'
$email_data->email_message = preg_replace('/\[estrangeiro\/start\](.*?)\[estrangeiro\/finish\]/s', '$1', $email_data->email_message);
} else {
// Remove content for 'estrangeiro'
$email_data->email_message = preg_replace('/\[estrangeiro\/start\](.*?)\[estrangeiro\/finish\]/s', '', $email_data->email_message);
// Keep content for 'brasileiro'
$email_data->email_message = preg_replace('/\[brasileiro\/start\](.*?)\[brasileiro\/finish\]/s', '$1', $email_data->email_message);
}
if ($email_data) {
$email_subject = $email_data->email_subject;
$email_message = $email_data->email_message;
// Preserve necessary HTML tags for proper formatting
//$email_message = strip_tags($email_message, '<p><br>');
// Set content type to HTML and charset to UTF-8
$headers = array('Content-Type: text/html; charset=UTF-8');
$sent = wp_mail($email_to, $email_subject, $email_message, $headers);
if ($sent == false) {
usleep(500_000);
wp_mail($email_to, $email_subject, $email_message, $headers);
}
}
return $sent;
}
function SendOccasionalEmailsSubmenuPage()
{
global $wpdb;
// Get all unique activity IDs and statuses from sige_enrollments
$activity_ids = $wpdb->get_results("SELECT DISTINCT activity_id, a.name, a.modality FROM {$wpdb->prefix}sige_enrollments e JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id");
$statuses = $wpdb->get_col("SELECT DISTINCT status FROM {$wpdb->prefix}sige_enrollments");
// Handle form submission for filtering
$selected_activity_id = isset($_POST['activity_id']) ? $_POST['activity_id'] : 'All';
$selected_status = isset($_POST['status']) ? $_POST['status'] : 'All';
$query = "SELECT e.*, u.user_email, a.name, a.modality FROM {$wpdb->prefix}sige_enrollments e JOIN {$wpdb->prefix}users u ON e.user_id = u.ID JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id";
$conditions = [];
if ($selected_activity_id !== 'All') {
$conditions[] = $wpdb->prepare("e.activity_id = %d", $selected_activity_id);
}
if ($selected_status !== 'All') {
$conditions[] = $wpdb->prepare("e.status = %s", $selected_status);
}
if (!empty($conditions)) {
$query .= ' WHERE ' . implode(' AND ', $conditions);
}
$enrollments = $wpdb->get_results($query);
echo '<div class="wrap"><h2>Manage Enrollments</h2>';
// Email form
echo '<form method="post" id="send_email_form">
<table class="form-table">
<tr valign="top">
<th scope="row">Email Subject</th>
<td><input type="text" name="email_subject" id="email_subject" style="width: 100%;" required /></td>
</tr>
<tr valign="top">
<th scope="row">Email Message</th>
<td>';
// Start output buffering to capture wp_editor output
ob_start();
wp_editor('', 'email_message', array(
'textarea_name' => 'email_message',
'textarea_rows' => 15,
'media_buttons' => true,
'teeny' => false,
'quicktags' => true,
'editor_class' => 'wp-editor-area',
'tinymce' => array(
'toolbar1' => 'formatselect | bold italic underline | alignleft aligncenter alignright alignjustify | bullist numlist | removeformat | undo redo | wp_help',
'toolbar2' => 'forecolor backcolor | link unlink | image media | code',
'plugins' => 'lists link image code fullscreen paste',
'menubar' => false,
'statusbar' => true,
),
));
$editor_content = ob_get_clean();
echo $editor_content;
echo '</td>
</tr>
</table>
<div style="text-align: right;">
<input type="button" id="send_emails" value="Send" class="button button-primary" />
</div>
<hr style="border: 2px solid black; margin-top: 10px;">
<div id="email_results"></div>
</form>';
// Filter form
echo '<form method="post" action="">
<label for="activity_id">Filter by Activity ID:</label>
<select name="activity_id" id="activity_id">
<option value="All"' . selected($selected_activity_id, 'All', false) . '>All</option>';
foreach ($activity_ids as $activity) {
$activity_name_modality = esc_html($activity->name . ' (' . $activity->modality . ')');
echo '<option value="' . esc_attr($activity->activity_id) . '"' . selected($selected_activity_id, $activity->activity_id, false) . '>' . $activity_name_modality . '</option>';
}
echo '</select>
<label for="status">Filter by Status:</label>
<select name="status" id="status">
<option value="All"' . selected($selected_status, 'All', false) . '>All</option>';
foreach ($statuses as $status) {
echo '<option value="' . esc_attr($status) . '"' . selected($selected_status, $status, false) . '>' . esc_html($status) . '</option>';
}
echo '</select>
<input type="submit" value="Filter" class="button button-primary" />
</form>';
// Enrollments table
echo '<table id="enrollments-table" class="display" style="width: 100%; min-width: 1000px;">
<thead>
<tr>
<th style="width: 150px;">Enrollment Date</th>
<th style="width: 100px;">User ID</th>
<th style="width: 150px;">Email</th>
<th style="width: 100px;">Activity ID</th>
<th style="width: 200px;">Name</th>
<th style="width: 100px;">Modality</th>
<th style="width: 100px;">Status</th>
</tr>
</thead>
<tbody>';
foreach ($enrollments as $enrollment) {
echo '<tr>
<td>' . esc_html($enrollment->enrollment_date) . '</td>
<td>' . esc_html($enrollment->user_id) . '</td>
<td>' . esc_html($enrollment->user_email) . '</td>
<td>' . esc_html($enrollment->activity_id) . '</td>
<td>' . esc_html($enrollment->name) . '</td>
<td>' . esc_html($enrollment->modality) . '</td>
<td>' . esc_html($enrollment->status) . '</td>
</tr>';
}
echo '</tbody>
</table>';
// Updated JavaScript code
echo '<script>
jQuery(document).ready(function($) {
$("#enrollments-table").DataTable({
"scrollX": true,
"autoWidth": false,
"pageLength": 10,
"lengthMenu": [ [10, 25, 50, 100, 200, 500, -1], [10, 25, 50, 100, 200, 500, "All"] ]
});
$("#send_emails").on("click", function() {
const emailSubject = $("#email_subject").val();
const emailMessage = tinymce.get("email_message").getContent(); // Get content from wp_editor
const rows = $("#enrollments-table").DataTable().rows({ filter: "applied" }).nodes();
let successfulEmails = 0;
let failedEmails = 0;
let emailsSent = {};
let uniqueEmails = [];
$(rows).each(function(index, row) {
const userEmail = $(row).find("td").eq(2).text().trim();
if (!emailsSent[userEmail]) {
emailsSent[userEmail] = true;
uniqueEmails.push(userEmail);
}
});
// Log the collected unique emails to the server
$.post(ajaxurl, {
action: "log_collected_emails",
emails: uniqueEmails
}, function(response) {
console.log("Emails logged on server.");
});
uniqueEmails.forEach(function(userEmail, index) {
setTimeout(() => {
sendEmail(userEmail, emailSubject, emailMessage, function(success) {
if (success) {
successfulEmails++;
} else {
failedEmails++;
}
if (successfulEmails + failedEmails === uniqueEmails.length) {
$("#email_results").html("Total Emails Attempted: " + uniqueEmails.length + "; Successful Emails: " + successfulEmails + "; Failed Emails: " + failedEmails);
}
});
}, index * 10); // Adjust the delay as needed
});
});
function sendEmail(to, subject, message, callback) {
$.post(ajaxurl, {
action: "send_custom_email",
to: to,
subject: subject,
message: message
}, function(response) {
console.log("Email response for " + to + ": ", response);
callback(response.success);
});
}
});
</script>';
echo '</div>';
}
// Register the Ajax handlers
add_action('wp_ajax_send_custom_email', 'send_custom_email');
add_action('wp_ajax_log_collected_emails', 'log_collected_emails');
// Function to handle sending emails
function send_custom_email()
{
// Check for required parameters
if (!isset($_POST['to'], $_POST['subject'], $_POST['message'])) {
wp_send_json_error('Missing email parameters.');
}
$to = sanitize_email($_POST['to']);
$subject = sanitize_text_field($_POST['subject']);
$message = wp_kses_post($_POST['message']); // Allow HTML content with allowed tags
// Set content type to HTML and charset to UTF-8
$headers = array('Content-Type: text/html; charset=UTF-8');
// Send the email
$sent = wp_mail($to, $subject, $message, $headers);
if ($sent) {
wp_send_json_success();
} else {
usleep(500_000);
$sent = wp_mail($to, $subject, $message, $headers);
if (!$sent) {
wp_send_json_error('Failed to send email.');
}
}
}
// Function to log collected emails
function log_collected_emails()
{
if (!isset($_POST['emails']) || !is_array($_POST['emails'])) {
wp_send_json_error('No emails to log.');
}
$emails = $_POST['emails'];
// Sanitize the collected emails
$sanitized_emails = array_map('sanitize_email', $emails);
wp_send_json_success();
}
function displayMainOptions()
{
echo '<div class="wrap"><h2>Main Options</h2><p>Content for Main Options tab.</p></div>';
}
function displayDashboardOptions()
{
echo '<div class="wrap"><h2>Dashboard Options</h2><p>Content for Dashboard Options tab.</p></div>';
}
function displayActivityOptions()
{
global $wpdb;
echo '<div class="wrap"><h2>Activity Options</h2>';
// Wrap all sections in a single div for unified scroll
echo '<div style="overflow-x: auto;">';
// Places Options
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['save_place'])) {
$place = sanitize_text_field($_POST['place']);
$comments = sanitize_textarea_field($_POST['comments']);
$place_id = isset($_POST['place_id']) ? intval($_POST['place_id']) : 0;
if ($place_id > 0) {
$wpdb->update(
"{$wpdb->prefix}sige_place",
['place' => $place, 'comments' => $comments],
['id' => $place_id]
);
$redirect_url = admin_url('admin.php?page=settings-submenu&tab=activity_options');
echo '<script>window.location.href="' . $redirect_url . '";</script>';
exit;
} else {
$wpdb->insert(
"{$wpdb->prefix}sige_place",
['place' => $place, 'comments' => $comments]
);
}
echo '<div class="notice notice-success"><p>Place saved successfully.</p></div>';
}
if (isset($_GET['edit_place'])) {
$edit_place_id = intval($_GET['edit_place']);
$edit_place = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}sige_place WHERE id = %d", $edit_place_id));
}
if (isset($_GET['delete_place'])) {
$delete_place_id = intval($_GET['delete_place']);
$wpdb->delete("{$wpdb->prefix}sige_place", ['id' => $delete_place_id]);
echo '<div class="notice notice-success"><p>Place deleted successfully.</p></div>';
}
echo '<h3>Places Options</h3>';
echo '<form method="post" style="width: fit-content; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); background: #f9f9f9; border: 1px solid #ccc; border-radius: 8px; padding: 20px;">
<style>
.sige-places-form th,
.sige-places-form td {
padding: 10px 5px;
vertical-align: top;
}
.sige-places-form th {
text-align: left;
padding-right: 10px;
}
.sige-places-form td {
width: 100%;
}
.sige-places-form textarea {
width: 100%;
box-sizing: border-box;
}
.actions-cell {
text-align: right;
}
</style>
<table class="form-table sige-places-form" style="width: 100%;">
<tr valign="top">
<th scope="row">Place</th>
<td><input type="text" name="place" value="' . (isset($edit_place) ? esc_attr($edit_place->place) : '') . '" required /></td>
</tr>
<tr valign="top">
<th scope="row">Comments</th>
<td><textarea name="comments" required>' . (isset($edit_place) ? esc_textarea($edit_place->comments) : '') . '</textarea></td>
</tr>
</table>';
if (isset($edit_place)) {
echo '<input type="hidden" name="place_id" value="' . esc_attr($edit_place->id) . '" />';
}
echo '<input type="submit" name="save_place" value="' . (isset($edit_place) ? 'Update Place' : 'Save Place') . '" class="button button-primary" />
</form>';
$places = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}sige_place");
if ($places) {
echo '<h3>Existing Places</h3>';
echo '<table id="places-table" class="display" style="width: 100%;">
<thead>
<tr>
<th style="width: 100px;">Place</th>
<th>Comments</th>
<th>Actions</th>
</tr>
</thead>
<tbody>';
foreach ($places as $place) {
echo "<tr>
<td>{$place->place}</td>
<td style='text-align: justify;'>{$place->comments}</td>
<td class='actions-cell'>
<a href='?page=settings-submenu&tab=activity_options&edit_place={$place->id}' class='button button-edit'>Edit</a>
<a href='?page=settings-submenu&tab=activity_options&delete_place={$place->id}' class='button button-delete' onclick='return confirm(\"Are you sure you want to delete this place?\")'>Delete</a>
</td>
</tr>";
}
echo '</tbody></table>';
}
echo '<script>
jQuery(document).ready(function($) {
$("#places-table").DataTable();
});
</script>';
// Add separator line
echo '<hr style="border: 3px solid #000; margin: 20px 0;">';
// Speakers Options
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['save_speaker'])) {
$research_degree = sanitize_text_field($_POST['research_degree']);
$full_name = sanitize_text_field($_POST['full_name']);
$email = sanitize_email($_POST['email']);
$institution = sanitize_text_field($_POST['institution']);
$speaker_id = isset($_POST['speaker_id']) ? intval($_POST['speaker_id']) : 0;
if ($speaker_id > 0) {
$wpdb->update(
"{$wpdb->prefix}sige_speakers",
[
'research_degree' => $research_degree,
'full_name' => $full_name,
'email' => $email,
'institution' => $institution
],
['id' => $speaker_id]
);
$redirect_url = admin_url('admin.php?page=settings-submenu&tab=activity_options');
echo '<script>window.location.href="' . $redirect_url . '";</script>';
exit;
} else {
$wpdb->insert(
"{$wpdb->prefix}sige_speakers",
[
'research_degree' => $research_degree,
'full_name' => $full_name,
'email' => $email,
'institution' => $institution
]
);
}
echo '<div class="notice notice-success"><p>Speaker saved successfully.</p></div>';
}
if (isset($_GET['edit_speaker'])) {
$edit_speaker_id = intval($_GET['edit_speaker']);
$edit_speaker = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}sige_speakers WHERE id = %d", $edit_speaker_id));
}
if (isset($_GET['delete_speaker'])) {
$delete_speaker_id = intval($_GET['delete_speaker']);
$wpdb->delete("{$wpdb->prefix}sige_speakers", ['id' => $delete_speaker_id]);
echo '<div class="notice notice-success"><p>Speaker deleted successfully.</p></div>';
}
echo '<h3>Register Speakers</h3>';
echo '<form method="post" style="width: fit-content; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); background: #f9f9f9; border: 1px solid #ccc; border-radius: 8px; padding: 20px;">
<style>
.sige-speakers-form th,
.sige-speakers-form td {
padding: 10px 5px;
vertical-align: top;
}
.sige-speakers-form th {
text-align: left;
padding-right: 10px;
}
.sige-speakers-form td {
width: 100%;
}
.sige-speakers-form textarea {
width: 100%;
box-sizing: border-box;
}
.actions-cell {
text-align: right;
}
</style>
<table class="form-table sige-speakers-form" style="width: 100%;">
<tr valign="top">
<th scope="row">Research Degree</th>
<td><input type="text" name="research_degree" value="' . (isset($edit_speaker) ? esc_attr($edit_speaker->research_degree) : '') . '" required /></td>
</tr>
<tr valign="top">
<th scope="row">Full Name</th>
<td><input type="text" name="full_name" value="' . (isset($edit_speaker) ? esc_attr($edit_speaker->full_name) : '') . '" style="min-width: 500px;" required /></td>
</tr>
<tr valign="top">
<th scope="row">Email</th>
<td><input type="email" name="email" value="' . (isset($edit_speaker) ? esc_attr($edit_speaker->email) : '') . '" placeholder="example@example.com" style="min-width: 500px;" required /></td>
</tr>
<tr valign="top">
<th scope="row">Institution</th>
<td><input type="text" name="institution" value="' . (isset($edit_speaker) ? esc_attr($edit_speaker->institution) : '') . '" style="min-width: 500px;" required /></td>
</tr>
</table>';
if (isset($edit_speaker)) {
echo '<input type="hidden" name="speaker_id" value="' . esc_attr($edit_speaker->id) . '" />';
}
echo '<input type="submit" name="save_speaker" value="' . (isset($edit_speaker) ? 'Update Speaker' : 'Save Speaker') . '" class="button button-primary" />
</form>';
$speakers = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}sige_speakers");
if ($speakers) {
echo '<h3>Existing Speakers</h3>';
echo '<table id="speakers-table" class="display" style="width: 100%;">
<thead>
<tr>
<th style="width: 100px;">Research Degree</th>
<th>Full Name</th>
<th>Email</th>
<th>Institution</th>
<th>Actions</th>
</tr>
</thead>
<tbody>';
foreach ($speakers as $speaker) {
echo "<tr>
<td>{$speaker->research_degree}</td>
<td>{$speaker->full_name}</td>
<td>{$speaker->email}</td>
<td>{$speaker->institution}</td>
<td class='actions-cell'>
<a href='?page=settings-submenu&tab=activity_options&edit_speaker={$speaker->id}' class='button button-edit'>Edit</a>
<a href='?page=settings-submenu&tab=activity_options&delete_speaker={$speaker->id}' class='button button-delete' onclick='return confirm(\"Are you sure you want to delete this speaker?\")'>Delete</a>
</td>
</tr>";
}
echo '</tbody></table>';
}
echo '<script>
jQuery(document).ready(function($) {
$("#speakers-table").DataTable();
});
</script>';
// Add separator line
echo '<hr style="border: 3px solid #000; margin: 20px 0;">';
// Major Event Options
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['save_major_event'])) {
$acronym = sanitize_text_field($_POST['acronym']);
$name = sanitize_text_field($_POST['name']);
$responsible_for = sanitize_text_field($_POST['responsible_for']);
$major_event_id = isset($_POST['major_event_id']) ? intval($_POST['major_event_id']) : 0;
if ($major_event_id > 0) {
$wpdb->update(
"{$wpdb->prefix}sige_event_names",
[
'acronym' => $acronym,
'name' => $name,
'responsible_for' => $responsible_for
],
['id' => $major_event_id]
);
$redirect_url = admin_url('admin.php?page=settings-submenu&tab=activity_options');
echo '<script>window.location.href="' . $redirect_url . '";</script>';
exit;
} else {
$wpdb->insert(
"{$wpdb->prefix}sige_event_names",
[
'acronym' => $acronym,
'name' => $name,
'responsible_for' => $responsible_for
]
);
}
echo '<div class="notice notice-success"><p>Event Name saved successfully.</p></div>';
}
if (isset($_GET['edit_major_event'])) {
$edit_major_event_id = intval($_GET['edit_major_event']);
$edit_major_event = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}sige_event_names WHERE id = %d", $edit_major_event_id));
}
if (isset($_GET['delete_major_event'])) {
$delete_major_event_id = intval($_GET['delete_major_event']);
$wpdb->delete("{$wpdb->prefix}sige_event_names", ['id' => $delete_major_event_id]);
echo '<div class="notice notice-success"><p>Event Name deleted successfully.</p></div>';
}
echo '<h3>Register Event Name</h3>';
echo '<form method="post" style="width: fit-content; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); background: #f9f9f9; border: 1px solid #ccc; border-radius: 8px; padding: 20px;">
<style>
.sige-major-events-form th,
.sige-major-events-form td {
padding: 10px 5px;
vertical-align: top;
}
.sige-major-events-form th {
text-align: left;
padding-right: 10px;
}
.sige-major-events-form td {
width: 100%;
}
.sige-major-events-form textarea {
width: 100%;
box-sizing: border-box;
}
.actions-cell {
text-align: right;
}
</style>
<table class="form-table sige-major-events-form" style="width: 100%;">
<tr valign="top">
<th scope="row">Acronym</th>
<td><input type="text" name="acronym" value="' . (isset($edit_major_event) ? esc_attr($edit_major_event->acronym) : '') . '" required /></td>
</tr>
<tr valign="top">
<th scope="row">Name</th>
<td><input type="text" name="name" value="' . (isset($edit_major_event) ? esc_attr($edit_major_event->name) : '') . '" style="min-width: 500px;" required /></td>
</tr>
<tr valign="top">
<th scope="row">Responsible For</th>
<td><input type="text" name="responsible_for" value="' . (isset($edit_major_event) ? esc_attr($edit_major_event->responsible_for) : '') . '" style="min-width: 500px;" required /></td>
</tr>
</table>';
if (isset($edit_major_event)) {
echo '<input type="hidden" name="major_event_id" value="' . esc_attr($edit_major_event->id) . '" />';
}
echo '<input type="submit" name="save_major_event" value="' . (isset($edit_major_event) ? 'Update Event Name' : 'Save Event Data') . '" class="button button-primary" />
</form>';
$major_events = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}sige_event_names");
if ($major_events) {
echo '<h3>Existing Event Names</h3>';
echo '<table id="major-events-table" class="display" style="width: 100%;">
<thead>
<tr>
<th style="width: 100px;">Acronym</th>
<th>Name</th>
<th>Responsible For</th>
<th>Actions</th>
</tr>
</thead>
<tbody>';
foreach ($major_events as $major_event) {
echo "<tr>
<td>{$major_event->acronym}</td>
<td>{$major_event->name}</td>
<td>{$major_event->responsible_for}</td>
<td class='actions-cell'>
<a href='?page=settings-submenu&tab=activity_options&edit_major_event={$major_event->id}' class='button button-edit'>Edit</a>
<a href='?page=settings-submenu&tab=activity_options&delete_major_event={$major_event->id}' class='button button-delete' onclick='return confirm(\"Are you sure you want to delete this event name?\")'>Delete</a>
</td>
</tr>";
}
echo '</tbody></table>';
}
echo '<script>
jQuery(document).ready(function($) {
$("#major-events-table").DataTable();
});
</script>';
// End of unified div
echo '</div>';
echo '</div>'; // End of Activity Options section
}
function displayEnrollmentOptions()
{
global $wpdb;
echo '<div class="wrap"><h2>Enrollment Options</h2>';
// Wrap Display and Notice Options in a single div for unified scroll
echo '<div style="overflow-x: auto;">';
// Display Options
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['save_display_options'])) {
// Set all display options to 0 first
$wpdb->query("UPDATE {$wpdb->prefix}sige_display_options SET display = 0");
// Update only the checked options to 1
if (!empty($_POST['display_options'])) {
foreach ($_POST['display_options'] as $field_name => $display) {
foreach ($display as $activity_type => $value) {
$wpdb->update(
"{$wpdb->prefix}sige_display_options",
['display' => intval($value)],
['field_name' => sanitize_text_field($field_name), 'activity_type' => sanitize_text_field($activity_type)]
);
}
}
}
echo '<div class="notice notice-success"><p>Display options saved successfully.</p></div>';
}
$display_options = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}sige_display_options");
$activity_types = ['Main Event', 'Presentation', 'Short-course', 'Lecture', 'Workshop', 'Others'];
echo '<h3>Display Options</h3>';
echo '<form method="post" style="width: fit-content;">
<style>
.display-options-container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.display-options-container p {
padding: 5px;
margin: 0;
}
</style>
<table class="form-table">
<tr valign="top">
<th scope="row">Activity Type</th>
<td>
<select name="activity_type" id="activity_type">';
foreach ($activity_types as $type) {
echo '<option value="' . esc_attr($type) . '">' . esc_html($type) . '</option>';
}
echo ' </select>
</td>
</tr>
<tr valign="top">
<th scope="row">Display Options</th>
<td>
<div class="display-options-container" id="display-options-container">';
foreach ($activity_types as $type) {
echo '<div class="activity-type-options" data-activity-type="' . esc_attr($type) . '" style="display: none;">';
foreach ($display_options as $option) {
if ($option->activity_type == $type) {
echo '<p>
<label>
<input type="checkbox" name="display_options[' . esc_attr($option->field_name) . '][' . esc_attr($type) . ']" value="1"' . checked($option->display, 1, false) . '>
' . esc_html($option->field_name) . '
</label>
</p>';
}
}
echo '</div>';
}
echo ' </div>
</td>
</tr>
</table>
<input type="submit" name="save_display_options" value="Save Display Options" class="button button-primary" />
</form>';
// Add separator line
echo '<hr style="border: 3px solid #000; margin: 20px 0;">';
echo '<div style="display: flex; flex-direction: row; gap: 20px;">';
// Button Style Section
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['save_button_style'])) {
$selected_button_action = sanitize_text_field($_POST['button_action']);
$button_styles = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}sige_enrollment_button_style", ARRAY_A);
foreach ($button_styles as $style) {
$button_action = $style['button_action'];
$button_label = sanitize_text_field($_POST['button_label'][$button_action]);
$background_color = sanitize_text_field($_POST['background_color'][$button_action]);
$font_size = sanitize_text_field($_POST['font_size'][$button_action]);
$font_family = str_replace('"', '', sanitize_text_field($_POST['font_family'][$button_action]));
$font_weight = sanitize_text_field($_POST['font_weight'][$button_action]);
$wpdb->update(
"{$wpdb->prefix}sige_enrollment_button_style",
[
'button_label' => $button_label,
'background_color' => $background_color,
'font_size' => $font_size,
'font_family' => $font_family,
'font_weight' => $font_weight
],
['button_action' => $button_action]
);
}
echo '<div class="notice notice-success"><p>Button styles saved successfully.</p></div>';
}
$button_styles = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}sige_enrollment_button_style", ARRAY_A);
$selected_button_action = isset($_POST['button_action']) ? sanitize_text_field($_POST['button_action']) : $button_styles[0]['button_action'];
$font_families = [
'Arial, sans-serif' => 'Arial',
'Georgia, serif' => 'Georgia',
'Times New Roman, serif' => 'Times New Roman',
'Courier New, monospace' => 'Courier New',
'Tahoma, sans-serif' => 'Tahoma',
'Verdana, sans-serif' => 'Verdana',
'Lucida Sans, sans-serif' => 'Lucida Sans',
'Impact, sans-serif' => 'Impact',
'Calibri, sans-serif' => 'Calibri',
'Garamond, serif' => 'Garamond',
'Comic Sans MS, cursive, sans-serif' => 'Comic Sans MS',
'Trebuchet MS, sans-serif' => 'Trebuchet MS',
'Arial Black, sans-serif' => 'Arial Black',
'Palatino, serif' => 'Palatino',
'Gill Sans, sans-serif' => 'Gill Sans',
'Helvetica, sans-serif' => 'Helvetica',
'Lucida Bright, serif' => 'Lucida Bright',
'Futura, sans-serif' => 'Futura',
'Franklin Gothic Medium, sans-serif' => 'Franklin Gothic Medium',
'Candara, sans-serif' => 'Candara'
];
$font_sizes = range(8, 42);
echo '<div style="flex: 1;">';
echo '<h3>Button Style</h3>';
echo '<form method="post" style="width: fit-content;">';
echo '<table class="form-table">';
echo '<tr valign="top">
<th scope="row">Button Action</th>
<td>
<select name="button_action" id="button_action">';
foreach ($button_styles as $style) {
echo '<option value="' . esc_attr($style['button_action']) . '"' . selected($style['button_action'], $selected_button_action, false) . '>' . esc_html($style['button_action']) . '</option>';
}
echo '</select>
</td>
</tr>';
echo '<tr valign="top">
<th scope="row">Button Label</th>
<td>';
foreach ($button_styles as $style) {
$display_style = $style['button_action'] === $selected_button_action ? 'display: block;' : 'display: none;';
echo '<input type="text" name="button_label[' . esc_attr($style['button_action']) . ']" value="' . esc_attr($style['button_label']) . '" class="button-label-input" data-action="' . esc_attr($style['button_action']) . '" style="' . $display_style . '" required />';
}
echo '</td>
</tr>';
foreach ($button_styles as $style) {
$display_style = $style['button_action'] === $selected_button_action ? 'display: table-row;' : 'display: none;';
echo '<tr valign="top" class="button-style-row" data-action="' . esc_attr($style['button_action']) . '" style="' . $display_style . '">
<th scope="row">Background Color</th>
<td><input type="color" name="background_color[' . esc_attr($style['button_action']) . ']" value="' . esc_attr($style['background_color']) . '" required /></td>
</tr>
<tr valign="top" class="button-style-row" data-action="' . esc_attr($style['button_action']) . '" style="' . $display_style . '">
<th scope="row">Font Size</th>
<td>
<select name="font_size[' . esc_attr($style['button_action']) . ']" required>';
foreach ($font_sizes as $size) {
echo '<option value="' . esc_attr($size . 'px') . '" ' . selected($style['font_size'], $size . 'px', false) . '>' . esc_html($size . 'px') . '</option>';
}
echo '</select></td>
</tr>
<tr valign="top" class="button-style-row" data-action="' . esc_attr($style['button_action']) . '" style="' . $display_style . '">
<th scope="row">Font Family</th>
<td>
<select name="font_family[' . esc_attr($style['button_action']) . ']" class="font-family-dropdown" required size="5">';
foreach ($font_families as $font_value => $font_label) {
$selected = selected(str_replace('"', '', $style['font_family']), $font_value, false);
echo '<option value="' . esc_attr($font_value) . '"' . $selected . '>' . esc_html($font_label) . '</option>';
}
echo '</select>
</td>
</tr>
<tr valign="top" class="button-style-row" data-action="' . esc_attr($style['button_action']) . '" style="' . $display_style . '">
<th scope="row">Font Weight</th>
<td>
<select name="font_weight[' . esc_attr($style['button_action']) . ']" required>
<option value="normal"' . selected($style['font_weight'], 'normal', false) . '>Normal</option>
<option value="bold"' . selected($style['font_weight'], 'bold', false) . '>Bold</option>
</select>
</td>
</tr>';
}
echo '</table>
<input type="submit" name="save_button_style" value="Save Button Style" class="button button-primary" />
</form>';
echo '</div>';
// Status Style Section
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['save_status_style'])) {
$status_styles = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}sige_enrollment_status_style", ARRAY_A);
foreach ($status_styles as $style) {
$status_action = $style['status_action'];
$status_label = sanitize_text_field($_POST['status_label'][$status_action]);
$font_color = sanitize_text_field($_POST['font_color'][$status_action]);
$font_size = sanitize_text_field($_POST['font_size'][$status_action]);
$font_family = str_replace('"', '', sanitize_text_field($_POST['font_family'][$status_action]));
$font_weight = sanitize_text_field($_POST['font_weight'][$status_action]);
$wpdb->update(
"{$wpdb->prefix}sige_enrollment_status_style",
[
'status_label' => $status_label,
'font_color' => $font_color,
'font_size' => $font_size,
'font_family' => $font_family,
'font_weight' => $font_weight
],
['status_action' => $status_action]
);
}
echo '<div class="notice notice-success"><p>Status styles saved successfully.</p></div>';
}
$status_styles = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}sige_enrollment_status_style", ARRAY_A);
$selected_status_action = isset($_POST['status_action']) ? sanitize_text_field($_POST['status_action']) : $status_styles[0]['status_action'];
echo '<div style="flex: 1;">';
echo '<h3>Status Style</h3>';
echo '<form method="post" style="width: fit-content;">';
echo '<table class="form-table">';
echo '<tr valign="top">
<th scope="row">Status Action</th>
<td>
<select name="status_action" id="status_action">';
foreach ($status_styles as $style) {
echo '<option value="' . esc_attr($style['status_action']) . '"' . selected($style['status_action'], $selected_status_action, false) . '>' . esc_html($style['status_action']) . '</option>';
}
echo '</select>
</td>
</tr>';
echo '<tr valign="top">
<th scope="row">Status Label</th>
<td>';
foreach ($status_styles as $style) {
$display_style = $style['status_action'] === $selected_status_action ? 'display: block;' : 'display: none;';
echo '<input type="text" name="status_label[' . esc_attr($style['status_action']) . ']" value="' . esc_attr($style['status_label']) . '" class="status-label-input" data-action="' . esc_attr($style['status_action']) . '" style="' . $display_style . '" required />';
}
echo '</td>
</tr>';
foreach ($status_styles as $style) {
$display_style = $style['status_action'] === $selected_status_action ? 'display: table-row;' : 'display: none;';
echo '<tr valign="top" class="status-style-row" data-action="' . esc_attr($style['status_action']) . '" style="' . $display_style . '">
<th scope="row">Font Color</th>
<td><input type="color" name="font_color[' . esc_attr($style['status_action']) . ']" value="' . esc_attr($style['font_color']) . '" required /></td>
</tr>
<tr valign="top" class="status-style-row" data-action="' . esc_attr($style['status_action']) . '" style="' . $display_style . '">
<th scope="row">Font Size</th>
<td>
<select name="font_size[' . esc_attr($style['status_action']) . ']" required>';
foreach ($font_sizes as $size) {
echo '<option value="' . esc_attr($size . 'px') . '" ' . selected($style['font_size'], $size . 'px', false) . '>' . esc_html($size . 'px') . '</option>';
}
echo '</select></td>
</tr>
<tr valign="top" class="status-style-row" data-action="' . esc_attr($style['status_action']) . '" style="' . $display_style . '">
<th scope="row">Font Family</th>
<td>
<select name="font_family[' . esc_attr($style['status_action']) . ']" class="font-family-dropdown" required size="5">';
foreach ($font_families as $font_value => $font_label) {
$selected = selected(str_replace('"', '', $style['font_family']), $font_value, false);
echo '<option value="' . esc_attr($font_value) . '"' . $selected . '>' . esc_html($font_label) . '</option>';
}
echo '</select>
</td>
</tr>
<tr valign="top" class="status-style-row" data-action="' . esc_attr($style['status_action']) . '" style="' . $display_style . '">
<th scope="row">Font Weight</th>
<td>
<select name="font_weight[' . esc_attr($style['status_action']) . ']" required>
<option value="normal"' . selected($style['font_weight'], 'normal', false) . '>Normal</option>
<option value="bold"' . selected($style['font_weight'], 'bold', false) . '>Bold</option>
</select>
</td>
</tr>';
}
echo '</table>
<input type="submit" name="save_status_style" value="Save Status Style" class="button button-primary" />
</form>';
echo '</div>';
echo '</div>'; // Close div for flex display
// Add separator line
echo '<hr style="border: 3px solid #000; margin: 20px 0;">';
// Notice Options
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['save_notice'])) {
$type = sanitize_text_field($_POST['notice_type']);
$notice = wp_kses_post($_POST['notice']);
$existing_notice = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$wpdb->prefix}sige_activity_notices WHERE type = %s", $type));
if ($existing_notice) {
$wpdb->update(
"{$wpdb->prefix}sige_activity_notices",
['notice' => $notice],
['id' => $existing_notice]
);
} else {
$wpdb->insert(
"{$wpdb->prefix}sige_activity_notices",
['type' => $type, 'notice' => $notice]
);
}
echo '<div class="notice notice-success"><p>Notice saved successfully.</p></div>';
}
$types = ['Main Event', 'Presentation', 'Short-course', 'Lecture', 'Workshop', 'Others'];
echo '<h3>Register Activity Notices</h3>';
echo '<form method="post" style="width: fit-content; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); background: #f9f9f9; border: 1px solid #ccc; padding: 20px; border-radius: 8px;">
<style>
.sige-notices-form th,
.sige-notices-form td {
padding: 10px 5px;
vertical-align: top;
}
.sige-notices-form th {
text-align: left;
padding-right: 10px;
}
.sige-notices-form td {
width: 100%;
}
.sige-notices-form textarea {
width: 100%;
box-sizing: border-box;
}
</style>
<table class="form-table sige-notices-form" style="width: 100%;">
<tr valign="top">
<th scope="row">Type</th>
<td>
<select name="notice_type" id="notice_type" required>';
foreach ($types as $type_name) {
echo '<option value="' . $type_name . '">' . $type_name . '</option>';
}
echo '</select>
</td>
</tr>
<tr valign="top">
<th scope="row">Notice</th>
<td>';
wp_editor('', 'notice', array(
'textarea_name' => 'notice',
'textarea_rows' => 10,
'wpautop' => true,
'media_buttons' => true,
'teeny' => false,
'tinymce' => true,
'quicktags' => true,
'editor_class' => 'wp-editor-area'
));
echo '</td>
</tr>
</table>
<input type="submit" name="save_notice" value="Update Notice" class="button button-primary" />
</form>';
$notices = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}sige_activity_notices");
if ($notices) {
echo '<h3>Existing Notices</h3>';
echo '<table id="notices-table" class="display" style="width: 100%;">
<thead>
<tr>
<th style="width: 100px;">Type</th>
<th>Notice</th>
</tr>
</thead>
<tbody>';
foreach ($notices as $notice) {
echo "<tr>
<td>{$notice->type}</td>
<td style='text-align: justify;'>{$notice->notice}</td>
</tr>";
}
echo '</tbody></table>';
}
echo '<script>
jQuery(document).ready(function($) {
$("#notices-table").DataTable();
$("#button_action").on("change", function() {
const selectedAction = $(this).val();
$(".button-style-row, .button-label-input").each(function() {
const action = $(this).data("action");
if (action === selectedAction) {
$(this).show();
} else {
$(this).hide();
}
});
}).trigger("change");
$("#status_action").on("change", function() {
const selectedAction = $(this).val();
$(".status-style-row, .status-label-input").each(function() {
const action = $(this).data("action");
if (action === selectedAction) {
$(this).show();
} else {
$(this).hide();
}
});
}).trigger("change");
$("#activity_type").on("change", function() {
const selectedType = $(this).val();
$(".activity-type-options").each(function() {
const activityType = $(this).data("activity-type");
if (activityType === selectedType) {
$(this).show();
} else {
$(this).hide();
}
});
}).trigger("change");
$("#notice_type").on("change", function() {
const selectedType = $(this).val();
$.ajax({
url: ajaxurl,
type: "POST",
data: {
action: "get_notice",
type: selectedType
},
success: function(response) {
if (response.success) {
tinymce.get("notice").setContent(response.data.notice);
} else {
tinymce.get("notice").setContent("");
$("#notice").attr("placeholder", "Empty field");
}
}
});
}).trigger("change");
});
</script>';
echo '</div>';
}
add_action('wp_ajax_get_notice', 'get_notice');
add_action('wp_ajax_nopriv_get_notice', 'get_notice');
function get_notice()
{
global $wpdb;
$type = sanitize_text_field($_POST['type']);
$notice = $wpdb->get_var($wpdb->prepare("SELECT notice FROM {$wpdb->prefix}sige_activity_notices WHERE type = %s", $type));
if ($notice !== null) {
wp_send_json_success(['notice' => wp_kses_post($notice)]);
} else {
wp_send_json_error(['notice' => '']);
}
}
function displayMiscellaneous()
{
global $wpdb;
echo '<div class="wrap"><h2>Miscellaneous</h2>';
// Fetch all distinct meta keys from wp_usermeta
$meta_keys = $wpdb->get_col("SELECT DISTINCT meta_key FROM {$wpdb->prefix}usermeta");
// Fetch the saved meta keys and their statuses
$saved_meta_keys = $wpdb->get_results("SELECT meta_key, status FROM {$wpdb->prefix}sige_meta_keys", OBJECT_K);
// Remove saved meta keys from the list of all meta keys
$meta_keys = array_diff($meta_keys, array_keys($saved_meta_keys));
// Handle form submission for saving meta keys
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['save_meta_keys'])) {
$selected_meta_key = sanitize_text_field($_POST['meta_key']);
$meta_key_status = isset($_POST['meta_key_status']) ? 1 : 0;
// Save or update the selected meta key status
$existing_entry = $wpdb->get_var($wpdb->prepare("
SELECT COUNT(*) FROM {$wpdb->prefix}sige_meta_keys
WHERE meta_key = %s
", $selected_meta_key));
if ($existing_entry) {
$wpdb->update(
"{$wpdb->prefix}sige_meta_keys",
['status' => $meta_key_status],
['meta_key' => $selected_meta_key]
);
} else {
$wpdb->insert(
"{$wpdb->prefix}sige_meta_keys",
['meta_key' => $selected_meta_key, 'status' => $meta_key_status]
);
}
echo '<div class="notice notice-success"><p>Meta Key status saved successfully.</p></div>';
echo '<script>
setTimeout(function() {
window.location.reload();
}, 2000);
</script>';
}
// Handle delete request
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['delete_meta_key'])) {
$meta_key_to_delete = sanitize_text_field($_POST['meta_key_to_delete']);
$wpdb->delete(
"{$wpdb->prefix}sige_meta_keys",
['meta_key' => $meta_key_to_delete]
);
echo '<div class="notice notice-success"><p>Meta Key deleted successfully.</p></div>';
echo '<script>
setTimeout(function() {
window.location.reload();
}, 2000);
</script>';
}
echo '<h3>Meta Key Options</h3>';
echo '<form method="post" style="width: fit-content;">
<style>
.meta-key-form th,
.meta-key-form td {
padding: 10px 5px;
vertical-align: top;
}
.meta-key-form th {
text-align: left;
padding-right: 10px;
}
.meta-key-form td {
width: 100%;
}
.meta-key-form select,
.meta-key-form input[type="checkbox"] {
margin-bottom: 20px;
}
</style>
<table class="form-table meta-key-form" style="width: 100%;">
<tr valign="top">
<th scope="row">Meta Key</th>
<td>
<select name="meta_key" required>';
foreach ($meta_keys as $meta_key) {
echo '<option value="' . esc_attr($meta_key) . '">' . esc_html($meta_key) . '</option>';
}
echo ' </select>
</td>
</tr>
<tr valign="top">
<th scope="row">Status</th>
<td>
<label>
<input type="checkbox" name="meta_key_status" value="1">
Enable
</label>
</td>
</tr>
</table>
<input type="submit" name="save_meta_keys" value="Save Meta Key Status" class="button button-primary" />
</form>';
// Display the saved meta keys in a table
if (!empty($saved_meta_keys)) {
echo '<h3>Saved Meta Keys</h3>';
echo '<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>Meta Key</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>';
foreach ($saved_meta_keys as $meta_key => $data) {
echo '<tr>
<td>' . esc_html($meta_key) . '</td>
<td>' . ($data->status ? 'Enabled' : 'Disabled') . '</td>
<td>
<form method="post" style="display:inline;">
<input type="hidden" name="meta_key_to_delete" value="' . esc_attr($meta_key) . '" />
<input type="submit" name="delete_meta_key" value="Delete" class="button button-secondary" onclick="return confirm(\'Are you sure you want to delete this meta key?\');" />
</form>
</td>
</tr>';
}
echo '</tbody></table>';
}
echo '<script>
document.addEventListener("DOMContentLoaded", function() {
const metaKeySelect = document.querySelector("select[name=\'meta_key\']");
const metaKeyCheckbox = document.querySelector("input[name=\'meta_key_status\']");
metaKeySelect.addEventListener("change", function() {
const selectedMetaKey = metaKeySelect.value;
const savedMetaKeys = ' . json_encode($saved_meta_keys) . ';
if (savedMetaKeys[selectedMetaKey] && savedMetaKeys[selectedMetaKey].status) {
metaKeyCheckbox.checked = true;
} else {
metaKeyCheckbox.checked = false;
}
});
// Trigger change event on page load to set the initial checkbox state
metaKeySelect.dispatchEvent(new Event("change"));
});
</script>';
// Separator line
echo '<hr style="border: 3px solid #000;">';
// New box for confidentiality and sharing information
echo '<div style="box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); background: #f9f9f9; border: 1px solid #ccc; border-radius: 8px; padding: 20px;">';
echo '<h3>Confidentiality and Sharing Information</h3>';
// Fetch information types from the new table
$information_types = $wpdb->get_col("SELECT information_type FROM {$wpdb->prefix}sige_confidentiality_message");
echo '<form method="post" id="information_form">';
echo '<label for="information_type">Type:</label>';
echo '<select id="information_type" name="information_type">';
foreach ($information_types as $type) {
echo '<option value="' . esc_attr($type) . '">' . esc_html($type) . '</option>';
}
echo '</select>';
echo '<br><br>';
// Initialize wp_editor with empty content
wp_editor('', 'message', [
'textarea_name' => 'message',
'textarea_rows' => 10,
'editor_class' => 'wp-editor-area',
'media_buttons' => false,
'tinymce' => true,
'quicktags' => true,
]);
echo '<br><br>';
echo '<input type="button" id="update_message" value="Update" class="button button-primary" />';
echo '</form>';
echo '</div>';
// Fetch and display the message for the selected information type
echo '<script>
document.addEventListener("DOMContentLoaded", function() {
const informationTypeSelect = document.getElementById("information_type");
const messageEditor = tinyMCE.get("message") || document.getElementById("message");
const updateButton = document.getElementById("update_message");
function loadMessage() {
const selectedType = informationTypeSelect.value;
fetch("' . admin_url('admin-ajax.php') . '?action=get_message&information_type=" + selectedType)
.then(response => response.json())
.then(data => {
if (messageEditor) {
if (tinyMCE.get("message")) {
tinyMCE.get("message").setContent(data.message || "");
} else {
messageEditor.value = data.message || "";
}
}
});
}
informationTypeSelect.addEventListener("change", loadMessage);
loadMessage();
updateButton.addEventListener("click", function() {
const selectedType = informationTypeSelect.value;
const messageContent = tinyMCE.get("message") ? tinyMCE.get("message").getContent() : document.getElementById("message").value;
fetch("' . admin_url('admin-ajax.php') . '?action=update_message", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: "information_type=" + encodeURIComponent(selectedType) + "&message=" + encodeURIComponent(messageContent),
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert("Message updated successfully.");
} else {
alert("Failed to update the message.");
}
});
});
});
</script>';
echo '</div>';
}
// AJAX handler for fetching the message
function get_message()
{
global $wpdb;
$information_type = sanitize_text_field($_GET['information_type']);
$message = $wpdb->get_var($wpdb->prepare("
SELECT message FROM {$wpdb->prefix}sige_confidentiality_message
WHERE information_type = %s
", $information_type));
wp_send_json(['message' => $message]);
}
add_action('wp_ajax_get_message', 'get_message');
// AJAX handler for updating the message
function update_message()
{
global $wpdb;
$information_type = sanitize_text_field($_POST['information_type']);
$message = wp_kses_post($_POST['message']); // Use wp_kses_post to allow safe HTML
$updated = $wpdb->update(
"{$wpdb->prefix}sige_confidentiality_message",
['message' => $message],
['information_type' => $information_type]
);
if ($updated !== false) {
wp_send_json(['success' => true]);
} else {
wp_send_json(['success' => false]);
}
}
add_action('wp_ajax_update_message', 'update_message');
// Update settingsSubmenuPage function to include emailSettingsSubmenuPage
function settingsSubmenuPage()
{
$tab = isset($_GET['tab']) ? $_GET['tab'] : 'main_options';
echo '<div class="wrap">
<h2>Settings</h2>
<h2 class="nav-tab-wrapper">
<a href="?page=settings-submenu&tab=main_options" class="nav-tab ' . ($tab == 'main_options' ? 'nav-tab-active' : '') . '">Main Options</a>
<a href="?page=settings-submenu&tab=dashboard_options" class="nav-tab ' . ($tab == 'dashboard_options' ? 'nav-tab-active' : '') . '">Dashboard Options</a>
<a href="?page=settings-submenu&tab=activity_options" class="nav-tab ' . ($tab == 'activity_options' ? 'nav-tab-active' : '') . '">Activity Options</a>
<a href="?page=settings-submenu&tab=enrollment_options" class="nav-tab ' . ($tab == 'enrollment_options' ? 'nav-tab-active' : '') . '">Enrollment Options</a>
<a href="?page=settings-submenu&tab=email_options" class="nav-tab ' . ($tab == 'email_options' ? 'nav-tab-active' : '') . '">Email Options</a>
<a href="?page=settings-submenu&tab=miscellaneous" class="nav-tab ' . ($tab == 'miscellaneous' ? 'nav-tab-active' : '') . '">Miscellaneous</a>
</h2>';
if ($tab == 'main_options') {
displayMainOptions();
} elseif ($tab == 'dashboard_options') {
displayDashboardOptions();
} elseif ($tab == 'activity_options') {
displayActivityOptions();
} elseif ($tab == 'enrollment_options') {
displayEnrollmentOptions();
} elseif ($tab == 'email_options') {
emailSettingsSubmenuPage();
} elseif ($tab == 'miscellaneous') {
displayMiscellaneous();
}
echo '</div>';
}
// Handle GSD export
function gsd_export_data()
{
if (isset($_GET['gsd_export']) && $_GET['gsd_export'] == '1') {
global $wpdb;
$current_year = date('Y'); // Get the current year dynamically
$activity_type = 'Main Event';
// Fetch user meta keys selected by the user
$current_user = wp_get_current_user();
$selected_meta_keys = get_user_meta($current_user->ID, 'selected_additional_features_frontend', true);
// Prepare the select and join clauses for the meta fields
$meta_selects = '';
$meta_joins = '';
if (!empty($selected_meta_keys)) {
foreach ($selected_meta_keys as $meta_key) {
$meta_selects .= ", um_$meta_key.meta_value as $meta_key";
$meta_joins .= " LEFT JOIN {$wpdb->prefix}usermeta um_$meta_key ON um_$meta_key.user_id = u.ID AND um_$meta_key.meta_key = '$meta_key'";
}
}
// Fetch user IDs, emails, and selected meta data from sige_enrollments table for activity_id representing Main Event
$query = $wpdb->prepare("
SELECT DISTINCT u.ID, u.user_email $meta_selects
FROM {$wpdb->prefix}sige_enrollments e
JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
$meta_joins
WHERE a.type = %s AND YEAR(a.start_date) = %d AND e.status NOT IN ('Not Approved', 'Enrollment Canceled by User') AND a.modality IN ('In-person', 'Hybrid')
", $activity_type, $current_year);
$results = $wpdb->get_results($query);
if (!empty($results)) {
// Get current date and time
$current_datetime = date('Ymd_His');
$filename = "gsd_enrollments_{$current_datetime}.csv";
header('Content-Type: text/csv');
header("Content-Disposition: attachment; filename=\"$filename\"");
$output = fopen('php://output', 'w');
// Header row
$header = ['User Email'];
if (!empty($selected_meta_keys)) {
foreach ($selected_meta_keys as $meta_key) {
$header[] = ucfirst(str_replace('_', ' ', $meta_key));
}
}
fputcsv($output, $header, ';'); // Header row
// Data rows
foreach ($results as $row) {
$data = [$row->user_email];
if (!empty($selected_meta_keys)) {
foreach ($selected_meta_keys as $meta_key) {
$data[] = $row->$meta_key;
}
}
fputcsv($output, $data, ';'); // Data rows
}
fclose($output);
exit;
} else {
wp_die('No data found for GSD export.');
}
}
}
add_action('init', 'gsd_export_data');
function attendanceControlNotOnlineSubmenuPage()
{
global $wpdb;
$filtered_user_id = isset($_POST['filtered_user_id']) ? sanitize_text_field($_POST['filtered_user_id']) : '';
$qrScannerUsedInput = isset($_POST['qr_scanner_used']) ? sanitize_text_field($_POST['qr_scanner_used']) : '';
// Handle form submission to update attendance
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['update_attendance'])) {
//error_log('Form submitted with update_attendance');
$enrollment_id = isset($_POST['enrollment_id']) ? intval($_POST['enrollment_id']) : 0;
//error_log('enrollment_id: ' . $enrollment_id);
$attended = isset($_POST['attended']) ? sanitize_text_field($_POST['attended']) : '';
//error_log('attended: ' . $attended);
$user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
//error_log('user_id: ' . $user_id);
if ($enrollment_id && $attended) {
//error_log('Valid enrollment_id and attended values');
// Fetch the activity_id from the sige_enrollments table
$activity_id = $wpdb->get_var($wpdb->prepare("SELECT activity_id FROM {$wpdb->prefix}sige_enrollments WHERE id = %d", $enrollment_id));
//error_log('activity_id: ' . $activity_id);
$existing_record = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$wpdb->prefix}sige_enrollment_attendance_control WHERE enrollment_id = %d", $enrollment_id));
//error_log('existing_record: ' . $existing_record);
if ($existing_record) {
//error_log('Updating existing record');
$wpdb->update(
"{$wpdb->prefix}sige_enrollment_attendance_control",
['attended' => $attended],
['id' => $existing_record]
);
} else {
//error_log('Inserting new record');
$wpdb->insert(
"{$wpdb->prefix}sige_enrollment_attendance_control",
[
'enrollment_id' => $enrollment_id,
'attended' => $attended
]
);
}
if ($activity_id !== null) {
//error_log('Sending email notification');
send_email_notification($user_id, $attended, $activity_id);
} else {
//error_log('Activity ID not found for enrollment ID ' . $enrollment_id);
}
} else {
//error_log('Invalid enrollment_id or attended value');
}
}
// Handle QR code verification (Hybrid / In-person)
$qr_error_message = '';
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $qrScannerUsedInput === 'true') {
$hashed_user_id = isset($_POST['filtered_user_id']) ? trim(sanitize_text_field($_POST['filtered_user_id'])) : '';
if ($hashed_user_id !== '') {
$filtered_user_id = verifyUserBasedOnQRCode($hashed_user_id, $qr_error_message);
if ($filtered_user_id === false && $qr_error_message === '') {
$qr_error_message = 'QR Code não corresponde a nenhum usuário.';
}
} else {
$qr_error_message = 'QR Code vazio ou inválido.';
}
}
// Fetch enrollments with status "Approved"
$query = "
SELECT e.id as enrollment_id, e.activity_id, a.name as activity_name, e.user_id, u.user_email, um.meta_value as user_full_name, e.enrollment_date, e.status, ac.attended
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'full_name'
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.status IN ('Approved', 'Not Requested', 'Waiting List')
AND a.modality IN ('Hybrid', 'In-person')
";
if ($filtered_user_id) {
$query .= $wpdb->prepare(" AND e.user_id = %d", $filtered_user_id);
}
$enrollments = $wpdb->get_results($query);
echo '<div class="wrap"><h2>Attendance Control - Hybrid or In-person</h2>';
if (!empty($qr_error_message)) {
echo '<div class="notice notice-error" style="padding:8px; margin:10px 0; border-left:4px solid #dc3232;"><strong>QR Code:</strong> ' . esc_html($qr_error_message) . '</div>';
}
// QR Code Scanner container
echo '<div id="qr-reader" style="width:300px;"></div>
<button id="start-qr-reader" class="button button-secondary">Start QR Scanner</button>';
// Filter form
echo '<form method="post" action="" style="margin-top: 20px; margin-bottom: 20px;">
<input type="hidden" name="qr_scanner_used" id="qr_scanner_used" value="' . esc_attr($qrScannerUsedInput) . '" />
<input type="text" name="filtered_user_id" id="filtered_user_id" placeholder="Enter User ID" value="' . esc_attr($filtered_user_id) . '" />
<input type="submit" value="Filter" class="button button-secondary" />
</form>';
echo '<button id="export-csv" class="button button-secondary" style="margin-bottom: 20px;">Export to CSV</button>';
echo '<table id="attendance-table" class="display wp-list-table widefat fixed striped">
<thead>
<tr>
<th>Activity Name</th>
<th>User ID</th>
<th>User Full Name</th>
<th>Email</th>
<th>Enrollment Date</th>
<th>Status</th>
<th>Attended</th>
<th>Action</th>
</tr>
</thead>
<tbody>';
if ($enrollments) {
foreach ($enrollments as $enrollment) {
echo '<tr>
<td>' . esc_html($enrollment->activity_name) . '</td>
<td>' . esc_html($enrollment->user_id) . '</td>
<td>' . esc_html($enrollment->user_full_name) . '</td>
<td>' . esc_html($enrollment->user_email) . '</td>
<td>' . esc_html($enrollment->enrollment_date) . '</td>
<td>' . esc_html($enrollment->status) . '</td>
<td>' . esc_html($enrollment->attended) . '</td>
<td>
<form method="post" action="">
<input type="hidden" name="enrollment_id" value="' . esc_attr($enrollment->enrollment_id) . '" />
<input type="hidden" name="user_id" value="' . esc_attr($enrollment->user_id) . '" />
<select name="attended">
<option value="yes"' . selected($enrollment->attended, 'yes', false) . '>Yes</option>
<option value="no"' . selected($enrollment->attended, 'no', false) . '>No</option>
</select>
<input type="submit" name="update_attendance" value="Update" class="button button-primary" />
</form>
</td>
</tr>';
}
} else {
echo '<tr><td colspan="8">No approved enrollments found.</td></tr>';
}
echo '</tbody></table></div>';
// Add custom JavaScript directly within the PHP file
echo '<script>
document.addEventListener("DOMContentLoaded", function() {
function initializeQrCodeScanner() {
if (typeof Html5Qrcode !== "undefined") {
const qrReader = new Html5Qrcode("qr-reader");
const startQrReaderBtn = document.getElementById("start-qr-reader");
const userIdInput = document.getElementById("filtered_user_id");
const qrScannerUsedInput = document.getElementById("qr_scanner_used");
// Elemento de feedback rápido
let feedbackEl = document.getElementById("qr-feedback-msg");
if (!feedbackEl) {
feedbackEl = document.createElement("div");
feedbackEl.id = "qr-feedback-msg";
feedbackEl.style.marginTop = "10px";
feedbackEl.style.fontWeight = "bold";
document.getElementById("qr-reader").insertAdjacentElement("afterend", feedbackEl);
}
startQrReaderBtn.addEventListener("click", function() {
if (startQrReaderBtn.textContent === "Stop QR Scanner") {
qrReader.stop();
startQrReaderBtn.textContent = "Start QR Scanner";
} else {
qrReader.start(
{ facingMode: "environment" },
{
fps: 10,
qrbox: 250
},
qrCodeMessage => {
userIdInput.value = qrCodeMessage.trim();
qrScannerUsedInput.value = "true";
feedbackEl.textContent = "QR lido. Processando...";
feedbackEl.style.color = "#2271b1";
qrReader.stop();
startQrReaderBtn.textContent = "Start QR Scanner";
// Evita submit múltiplo
setTimeout(() => { document.querySelector("form").submit(); }, 100);
},
errorMessage => {
console.warn(`QR Code scanning error: ${errorMessage}`);
})
.then(() => {
startQrReaderBtn.textContent = "Stop QR Scanner";
})
.catch(err => {
console.error(`Unable to start QR Code scanning: ${err}`);
});
}
});
} else {
console.error("Html5Qrcode library is not loaded properly.");
}
}
function exportTableToCSV(filename) {
const csv = [];
const rows = document.querySelectorAll("#attendance-table tr");
for (const row of rows) {
const cols = row.querySelectorAll("td, th");
const rowData = [];
for (let i = 0; i < cols.length - 1; i++) { // Exclude the last column (Action)
rowData.push(cols[i].innerText);
}
csv.push(rowData.join(";"));
}
// Download CSV
const csvFile = new Blob([csv.join("\n")], { type: "text/csv" });
const downloadLink = document.createElement("a");
downloadLink.download = filename;
downloadLink.href = window.URL.createObjectURL(csvFile);
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
document.getElementById("export-csv").addEventListener("click", function() {
const now = new Date();
const formattedDate = `${("0" + now.getDate()).slice(-2)}_${("0" + (now.getMonth() + 1)).slice(-2)}_${now.getFullYear()}_${("0" + now.getHours()).slice(-2)}_${("0" + now.getMinutes()).slice(-2)}_${("0" + now.getSeconds()).slice(-2)}`;
exportTableToCSV(`attendance_${formattedDate}.csv`);
});
// Initialize DataTables
jQuery("#attendance-table").DataTable({
"paging": true,
"searching": true,
"info": true,
"autoWidth": false, // Disable auto width for columns
"scrollX": true, // Enable horizontal scrolling
"order": [[0, "asc"]], // Order the first column in ascending order
"lengthMenu": [[10, 25, 50, 100, 200, 500, -1], [10, 25, 50, 100, 200, 500, "All"]], // Custom entries per page
"pageLength": 10, // Set the default page length to 10
"language": {
"lengthMenu": "Show _MENU_ entries",
"info": "Showing _START_ to _END_ of _TOTAL_ entries",
"infoFiltered": "(filtered from _MAX_ total entries)",
"paginate": {
"previous": "Previous",
"next": "Next"
}
}
});
initializeQrCodeScanner();
});
</script>';
}
function attendanceControlOnlineSubmenuPage()
{
global $wpdb;
$filtered_user_id = isset($_POST['filtered_user_id']) ? sanitize_text_field($_POST['filtered_user_id']) : '';
$qrScannerUsedInput = isset($_POST['qr_scanner_used']) ? sanitize_text_field($_POST['qr_scanner_used']) : '';
// Handle form submission to update attendance
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['update_attendance'])) {
//error_log('Form submitted with update_attendance');
$enrollment_id = isset($_POST['enrollment_id']) ? intval($_POST['enrollment_id']) : 0;
//error_log('enrollment_id: ' . $enrollment_id);
$attended = isset($_POST['attended']) ? sanitize_text_field($_POST['attended']) : '';
//error_log('attended: ' . $attended);
$user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
//error_log('user_id: ' . $user_id);
if ($enrollment_id && $attended) {
//error_log('Valid enrollment_id and attended values');
// Fetch the activity_id from the sige_enrollments table
$activity_id = $wpdb->get_var($wpdb->prepare("SELECT activity_id FROM {$wpdb->prefix}sige_enrollments WHERE id = %d", $enrollment_id));
//error_log('activity_id: ' . $activity_id);
$existing_record = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$wpdb->prefix}sige_enrollment_online_attendance_control WHERE enrollment_id = %d", $enrollment_id));
//error_log('existing_record: ' . $existing_record);
if ($existing_record) {
//error_log('Updating existing record');
$wpdb->update(
"{$wpdb->prefix}sige_enrollment_online_attendance_control",
['attended' => $attended],
['id' => $existing_record]
);
} else {
//error_log('Inserting new record');
$wpdb->insert(
"{$wpdb->prefix}sige_enrollment_online_attendance_control",
[
'enrollment_id' => $enrollment_id,
'attended' => $attended
]
);
}
if ($activity_id !== null) {
//error_log('Sending email notification');
send_email_notification($user_id, $attended, $activity_id);
} else {
//error_log('Activity ID not found for enrollment ID ' . $enrollment_id);
}
} else {
//error_log('Invalid enrollment_id or attended value');
}
}
// Handle QR code verification (Online)
$qr_error_message = '';
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $qrScannerUsedInput === 'true') {
$hashed_user_id = isset($_POST['filtered_user_id']) ? trim(sanitize_text_field($_POST['filtered_user_id'])) : '';
if ($hashed_user_id !== '') {
$filtered_user_id = verifyUserBasedOnQRCode($hashed_user_id, $qr_error_message);
if ($filtered_user_id === false && $qr_error_message === '') {
$qr_error_message = 'QR Code não corresponde a nenhum usuário.';
}
} else {
$qr_error_message = 'QR Code vazio ou inválido.';
}
}
// Fetch enrollments with status "Approved"
$query = "
SELECT e.id as enrollment_id, e.activity_id, a.name as activity_name, e.user_id, u.user_email, um.meta_value as user_full_name, e.enrollment_date, e.status, ac.attended
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'full_name'
LEFT JOIN {$wpdb->prefix}sige_enrollment_online_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.status IN ('Approved', 'Not Requested', 'Waiting List')
AND a.modality IN ('Online')
";
if ($filtered_user_id) {
$query .= $wpdb->prepare(" AND e.user_id = %d", $filtered_user_id);
}
$enrollments = $wpdb->get_results($query);
echo '<div class="wrap"><h2>Attendance Control - Online</h2>';
if (!empty($qr_error_message)) {
echo '<div class="notice notice-error" style="padding:8px; margin:10px 0; border-left:4px solid #dc3232;"><strong>QR Code:</strong> ' . esc_html($qr_error_message) . '</div>';
}
// QR Code Scanner container
echo '<div id="qr-reader" style="width:300px;"></div>
<button id="start-qr-reader" class="button button-secondary">Start QR Scanner</button>';
// Filter form
echo '<form method="post" action="" style="margin-top: 20px; margin-bottom: 20px;">
<input type="hidden" name="qr_scanner_used" id="qr_scanner_used" value="' . esc_attr($qrScannerUsedInput) . '" />
<input type="text" name="filtered_user_id" id="filtered_user_id" placeholder="Enter User ID" value="' . esc_attr($filtered_user_id) . '" />
<input type="submit" value="Filter" class="button button-secondary" />
</form>';
echo '<button id="export-csv" class="button button-secondary" style="margin-bottom: 20px;">Export to CSV</button>';
echo '<table id="attendance-table" class="display wp-list-table widefat fixed striped">
<thead>
<tr>
<th>Activity Name</th>
<th>User ID</th>
<th>User Full Name</th>
<th>Email</th>
<th>Enrollment Date</th>
<th>Status</th>
<th>Attended</th>
<th>Action</th>
</tr>
</thead>
<tbody>';
if ($enrollments) {
foreach ($enrollments as $enrollment) {
echo '<tr>
<td>' . esc_html($enrollment->activity_name) . '</td>
<td>' . esc_html($enrollment->user_id) . '</td>
<td>' . esc_html($enrollment->user_full_name) . '</td>
<td>' . esc_html($enrollment->user_email) . '</td>
<td>' . esc_html($enrollment->enrollment_date) . '</td>
<td>' . esc_html($enrollment->status) . '</td>
<td>' . esc_html($enrollment->attended) . '</td>
<td>
<form method="post" action="">
<input type="hidden" name="enrollment_id" value="' . esc_attr($enrollment->enrollment_id) . '" />
<input type="hidden" name="user_id" value="' . esc_attr($enrollment->user_id) . '" />
<select name="attended">
<option value="yes"' . selected($enrollment->attended, 'yes', false) . '>Yes</option>
<option value="no"' . selected($enrollment->attended, 'no', false) . '>No</option>
</select>
<input type="submit" name="update_attendance" value="Update" class="button button-primary" />
</form>
</td>
</tr>';
}
} else {
echo '<tr><td colspan="8">No approved enrollments found.</td></tr>';
}
echo '</tbody></table></div>';
// Add custom JavaScript directly within the PHP file
echo '<script>
document.addEventListener("DOMContentLoaded", function() {
function initializeQrCodeScanner() {
if (typeof Html5Qrcode !== "undefined") {
const qrReader = new Html5Qrcode("qr-reader");
const startQrReaderBtn = document.getElementById("start-qr-reader");
const userIdInput = document.getElementById("filtered_user_id");
const qrScannerUsedInput = document.getElementById("qr_scanner_used");
startQrReaderBtn.addEventListener("click", function() {
if (startQrReaderBtn.textContent === "Stop QR Scanner") {
qrReader.stop();
startQrReaderBtn.textContent = "Start QR Scanner";
} else {
qrReader.start(
{ facingMode: "environment" },
{
fps: 10,
qrbox: 250
},
qrCodeMessage => {
userIdInput.value = qrCodeMessage;
qrScannerUsedInput.value = "true";
qrReader.stop();
startQrReaderBtn.textContent = "Start QR Scanner";
// Submit the form automatically after setting the hashed user ID
document.querySelector("form").submit();
},
errorMessage => {
console.warn(`QR Code scanning error: ${errorMessage}`);
})
.then(() => {
startQrReaderBtn.textContent = "Stop QR Scanner";
})
.catch(err => {
console.error(`Unable to start QR Code scanning: ${err}`);
});
}
});
} else {
console.error("Html5Qrcode library is not loaded properly.");
}
}
function exportTableToCSV(filename) {
const csv = [];
const rows = document.querySelectorAll("#attendance-table tr");
for (const row of rows) {
const cols = row.querySelectorAll("td, th");
const rowData = [];
for (let i = 0; i < cols.length - 1; i++) { // Exclude the last column (Action)
rowData.push(cols[i].innerText);
}
csv.push(rowData.join(";"));
}
// Download CSV
const csvFile = new Blob([csv.join("\n")], { type: "text/csv" });
const downloadLink = document.createElement("a");
downloadLink.download = filename;
downloadLink.href = window.URL.createObjectURL(csvFile);
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
document.getElementById("export-csv").addEventListener("click", function() {
const now = new Date();
const formattedDate = `${("0" + now.getDate()).slice(-2)}_${("0" + (now.getMonth() + 1)).slice(-2)}_${now.getFullYear()}_${("0" + now.getHours()).slice(-2)}_${("0" + now.getMinutes()).slice(-2)}_${("0" + now.getSeconds()).slice(-2)}`;
exportTableToCSV(`attendance_${formattedDate}.csv`);
});
// Initialize DataTables
jQuery("#attendance-table").DataTable({
"paging": true,
"searching": true,
"info": true,
"autoWidth": false, // Disable auto width for columns
"scrollX": true, // Enable horizontal scrolling
"order": [[0, "asc"]], // Order the first column in ascending order
"lengthMenu": [[10, 25, 50, 100, 200, 500, -1], [10, 25, 50, 100, 200, 500, "All"]], // Custom entries per page
"pageLength": 10, // Set the default page length to 10
"language": {
"lengthMenu": "Show _MENU_ entries",
"info": "Showing _START_ to _END_ of _TOTAL_ entries",
"infoFiltered": "(filtered from _MAX_ total entries)",
"paginate": {
"previous": "Previous",
"next": "Next"
}
}
});
initializeQrCodeScanner();
});
</script>';
}
function userbadgeQRCode()
{
// Disable cache for all users
nocache_headers();
// Append nocache query parameter to bust cache
if (!isset($_GET['nocache'])) {
// Append a unique timestamp-based parameter to the URL
$permalink = get_permalink();
if (!$permalink) {
$permalink = home_url();
}
$new_url = add_query_arg('nocache', time(), $permalink);
wp_redirect($new_url);
exit;
exit();
}
// Check if the user is logged in
if (!is_user_logged_in()) {
$login_url = wp_login_url(get_permalink()); // Redirect to the current page after login
echo '
<div style="
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #808080; /* Gray background */
color: #fff; /* White text color */
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
z-index: 1000;
text-align: center;
border-radius: 10px;
">
<p>You must be logged in to view the available activities.</p>
<a href="' . esc_url($login_url) . '" style="color: #fff; text-decoration: underline;">Click here to log in</a>
</div>';
return;
}
// Prevent back/forward navigation cache
echo '<script>
if (performance.navigation.type === performance.navigation.TYPE_BACK_FORWARD) {
window.location.reload(true); // Force reload on back/forward navigation
}
</script>';
// Check if the user is an administrator
//if (!current_user_can('administrator')) {
// error_log('User is not an administrator.');
// return '
// <div style="
// position: fixed;
// top: 50%;
// left: 50%;
// transform: translate(-50%, -50%);
// background-color: #FF6347; /* Tomato background */
// color: #fff; /* White text color */
// padding: 20px;
// box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
// z-index: 1000;
// text-align: center;
// border-radius: 10px;
// ">
// <p>This page is currently under maintenance. Please check back later.</p>
// </div>';
//}
global $wpdb;
$current_user_id = get_current_user_id();
// Check if the last_time_update meta is greater than 27/08/2024
$last_time_update = get_user_meta($current_user_id, 'last_time_update', true);
$cutoff_date = strtotime('2024-09-04');
// Parse the last update time to a timestamp
$last_update_timestamp = strtotime(str_replace('/', '-', $last_time_update));
// Log the parsed timestamp and other relevant data
//error_log('Last time update (original format): ' . var_export($last_time_update, true));
//error_log('Last time update (parsed timestamp): ' . ($last_update_timestamp ? $last_update_timestamp : 'NULL or invalid date'));
//error_log('Cutoff date (timestamp): ' . $cutoff_date);
//error_log('Cutoff date (formatted): ' . date('Y-m-d H:i:s', $cutoff_date));
if (!$last_time_update || $last_update_timestamp <= $cutoff_date) {
echo '<div style="display: flex; justify-content: center; align-items: center; height: 100vh;">
<div style="box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); background: #f9f9f9; border: 1px solid #ccc; padding: 20px; border-radius: 8px; text-align: center;">
<p>We need to verify and update your profile information.</p>
</div>
</div>';
echo '<script>
setTimeout(function() {
window.location.href = "https://www.sige.ita.br/?ff_landing=3";
}, 5000);
</script>';
return '';
}
//error_log('Current user ID: ' . $current_user_id);
// Fetch full name from usermeta
$full_name = get_user_meta($current_user_id, 'full_name', true);
//error_log('Full name: ' . $full_name);
// Secret phrase
$secret_phrase = 'KrWy5Zc5q3gqSxPTzrw36fYrnafsRt57si6pRUpeHJNGkvQcGj';
//error_log('Secret phrase: ' . $secret_phrase);
// Generate MD5 hash of the user ID
$hashed_user_id = md5($secret_phrase . $current_user_id);
//error_log('Hashed user ID: ' . $hashed_user_id);
// Generate QR Code with the hashed user ID
ob_start();
QRcode::png($hashed_user_id, null, QR_ECLEVEL_L, 10);
$imageString = ob_get_contents();
ob_end_clean();
$qrCodeDataUri = 'data:image/png;base64,' . base64_encode($imageString);
//error_log('QR Code data URI generated.');
$current_year = (int) date('Y');
$current_year = date('Y');
//error_log('Current year: ' . $current_year);
$activities = $wpdb->get_results($wpdb->prepare("
SELECT a.*, p.place, s.full_name as speaker, e.name as event_name, e.id as event_id
FROM {$wpdb->prefix}sige_activities a
LEFT JOIN {$wpdb->prefix}sige_place p ON a.place_id = p.id
LEFT JOIN {$wpdb->prefix}sige_speakers s ON a.speaker_id = s.id
LEFT JOIN {$wpdb->prefix}sige_event_names e ON a.event_name_id = e.id
LEFT JOIN {$wpdb->prefix}sige_enrollments e2 ON e2.activity_id = a.id
WHERE (a.status = 'Open' OR a.status = 'Closed')
AND YEAR(a.start_date) = %d
AND a.attendance_control = 'yes'
AND e2.status NOT IN ('Not Requested', '')
AND e2.status IS NOT NULL
GROUP BY a.id
", $current_year));
if ($activities === null) {
//error_log('Error fetching activities: ' . $wpdb->last_error);
} elseif (empty($activities)) {
//error_log('No activities found.');
} else {
//error_log('Activities fetched successfully. Number of activities: ' . count($activities));
foreach ($activities as $activity) {
//error_log('Activity: ' . print_r($activity, true));
}
}
// Organize activities by event name
$events = [];
foreach ($activities as $activity) {
$enrollment_status_action = $wpdb->get_var($wpdb->prepare("
SELECT status FROM {$wpdb->prefix}sige_enrollments
WHERE activity_id = %d AND user_id = %d
", $activity->id, $current_user_id));
// Skip the activity if the enrollment status is 'Not Requested'
if (!$enrollment_status_action || $enrollment_status_action == 'Not Requested') {
continue; // Skip this iteration and move to the next one
}
//error_log('Activity ID: ' . $activity->id . ', Enrollment Status: ' . $enrollment_status_action);
$events[$activity->event_name][] = [
'activity_name' => $activity->name,
'modality' => $activity->modality,
'status' => $enrollment_status_action
];
}
// Output the HTML
ob_start();
?>
<div id="badgeContent" style="text-align: center;">
<div
style="position: relative; margin: 0 auto; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); background-color: #fff; max-width: 800px;">
<img src="<?php echo plugin_dir_url(__FILE__) . 'image/ita.png'; ?>" alt="ITA Logo" class="ita-logo"
style="position: absolute; top: 10px; left: 10px; width: 85px; height: auto;">
<img src="<?php echo plugin_dir_url(__FILE__) . 'image/gladioalado.png'; ?>" alt="Gladio Alado Logo"
class="gladio-logo" style="position: absolute; top: 10px; right: 10px; width: 120px; height: auto;">
<h3 style="padding-top: 100px; font-family: 'Times New Roman', Times, serif;">XXVII SYMPOSIUM ON OPERATIONAL
APPLICATIONS IN DEFENSE AREAS</h3>
<img id="qrCodeImage" src="<?php echo $qrCodeDataUri; ?>" alt="QR Code">
<h3>Activities for <?php echo $current_year; ?></h3>
<h4 style="color: crimson; font-weight: bold">Enrollment status on <?php echo date('d-m-Y \a\t H:i:s'); ?></h4>
<?php if (!empty($events)) { ?>
<?php foreach ($events as $event_name => $activities) { ?>
<div
style="margin-bottom: 20px; padding: 15px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); background-color: #f9f9f9;">
<h4><strong><?php echo esc_html($event_name); ?></strong></h4>
<ul style="list-style-type: none; padding: 0;">
<?php foreach ($activities as $activity) { ?>
<li style="padding: 10px; text-align: left;">
<strong>Activity:</strong> <?php echo esc_html($activity['activity_name']); ?><br>
<strong>Modality:</strong> <?php echo esc_html($activity['modality']); ?><br>
<strong>Status:</strong> <?php echo esc_html($activity['status']); ?>
</li>
<?php } ?>
</ul>
</div>
<?php } ?>
<?php } else { ?>
<p>No activities available for this year.</p>
<?php } ?>
<p align="justify">Dear <strong><?php echo esc_html($full_name); ?></strong>,</p>
<p align="justify">SIGE is an open event promoted by the Aeronautics Institute of Technology with the aim of
creating an environment for the exchange of experiences between the academic, industrial and operational
sectors of the Armed Forces, on issues of teaching, research, and development in Defense areas.</p>
<p align="justify">The organizing team is made up of masters and doctoral students from the Graduate Program in
Operational Applications (PPGAO) at ITA.</p>
<p align="justify">Please note that the badge only shows your registrations for in-person and hybrid activities.
To track your registrations for online activities, visit www.sige.ita.br/inscricoes/</p>
<p style="margin-top: 20px;">Contact the event Organizing Committee for questions via email at sige@ita.br</p>
</div>
<button id="downloadPDF" class="button button-primary" style="margin-top: 20px;">Download PDF</button>
</div>
<script>
document.getElementById('downloadPDF').addEventListener('click', function() {
var xhr = new XMLHttpRequest();
xhr.open('POST', '<?php echo admin_url('admin-ajax.php'); ?>', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.responseType = 'blob';
xhr.onload = function() {
if (xhr.status === 200) {
var blob = new Blob([xhr.response], {
type: 'application/pdf'
});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'User_Badge_<?php echo $current_user_id; ?>.pdf';
link.click();
//error_log('PDF generated and downloaded.');
} else {
console.error('Error generating PDF:', xhr.statusText);
//error_log('Error generating PDF: ' . xhr.statusText);
}
};
xhr.onerror = function() {
console.error('Error generating PDF:', xhr.statusText);
//error_log('Error generating PDF: ' . xhr.statusText);
};
xhr.send('action=generate_userbadge_pdf');
});
</script>
<?php
return ob_get_clean();
}
add_shortcode('userbadge_qr_code', 'userbadgeQRCode');
// Handle the AJAX request to generate the PDF
add_action('wp_ajax_generate_userbadge_pdf', 'generate_userbadge_pdf');
add_action('wp_ajax_nopriv_generate_userbadge_pdf', 'generate_userbadge_pdf');
function generate_userbadge_pdf()
{
if (!is_user_logged_in()) {
return '
<div style="
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #808080; /* Gray background */
color: #fff; /* White text color */
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
z-index: 1000;
text-align: center;
border-radius: 10px;
">
<p>You must be logged in to perform this action.</p>
</div>';
}
global $wpdb;
$current_user_id = get_current_user_id();
// Fetch full name from usermeta
$full_name = get_user_meta($current_user_id, 'full_name', true);
// Secret phrase
$secret_phrase = 'KrWy5Zc5q3gqSxPTzrw36fYrnafsRt57si6pRUpeHJNGkvQcGj';
// Generate MD5 hash of the user ID
$hashed_user_id = md5($secret_phrase . $current_user_id);
// Generate QR Code with the hashed user ID
ob_start();
QRcode::png($hashed_user_id, null, QR_ECLEVEL_L, 10);
$imageString = ob_get_contents();
ob_end_clean();
$imgdata = base64_decode(str_replace('data:image/png;base64,', '', base64_encode($imageString)));
// Get activities for the current year
$current_year = date('Y');
//error_log('Current year: ' . $current_year);
$activities = $wpdb->get_results($wpdb->prepare("
SELECT a.*, p.place, s.full_name as speaker, e.name as event_name, e.id as event_id
FROM {$wpdb->prefix}sige_activities a
LEFT JOIN {$wpdb->prefix}sige_place p ON a.place_id = p.id
LEFT JOIN {$wpdb->prefix}sige_speakers s ON a.speaker_id = s.id
LEFT JOIN {$wpdb->prefix}sige_event_names e ON a.event_name_id = e.id
LEFT JOIN {$wpdb->prefix}sige_enrollments e2 ON e2.activity_id = a.id
WHERE (a.status = 'Open' OR a.status = 'Closed')
AND YEAR(a.start_date) = %d
AND a.attendance_control = 'yes'
AND e2.status NOT IN ('Not Requested', '')
AND e2.status IS NOT NULL
GROUP BY a.id
", $current_year));
if ($activities === null) {
//error_log('Error fetching activities: ' . $wpdb->last_error);
} elseif (empty($activities)) {
//error_log('No activities found.');
} else {
//error_log('Activities fetched successfully. Number of activities: ' . count($activities));
foreach ($activities as $activity) {
//error_log('Activity: ' . print_r($activity, true));
}
}
// Organize activities by event name
$events = [];
foreach ($activities as $activity) {
$enrollment_status_action = $wpdb->get_var($wpdb->prepare("
SELECT status FROM {$wpdb->prefix}sige_enrollments
WHERE activity_id = %d AND user_id = %d
", $activity->id, $current_user_id));
// Skip the activity if the enrollment status is 'Not Requested'
if (!$enrollment_status_action || $enrollment_status_action == 'Not Requested') {
continue; // Skip this iteration and move to the next one
}
//error_log('Activity ID: ' . $activity->id . ', Enrollment Status: ' . $enrollment_status_action);
$events[$activity->event_name][] = [
'activity_name' => $activity->name,
'modality' => $activity->modality,
'status' => $enrollment_status_action
];
}
// Create a new PDF document
$pdf = new TCPDF();
$pdf->AddPage();
// Add custom styling
$css = '
<style>
.badge-box {
position: relative;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
background-color: #fff;
max-width: 800px;
text-align: center;
}
.event-box {
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
background-color: #f9f9f9;
border: 1px solid #ddd; /* Add border for the event box */
}
.event-box ul {
list-style-type: none;
padding: 0;
margin: 0;
}
.event-box ul li {
border: none; /* Remove borders between list items */
margin-bottom: 20.5em; /* Add some margin to space out each list item */
}
img.ita-logo {
width: 100px;
height: auto;
}
img.gladio-logo {
width: 120px;
height: auto;
}
</style>';
// Add logos (adjusted Y coordinate by 10 pixels)
$pdf->Image(plugin_dir_path(__FILE__) . 'image/ita.png', 15, 15, 27.5); // Adjusted Y coordinate to 20
$pdf->Image(plugin_dir_path(__FILE__) . 'image/gladioalado.png', 145, 15, 40); // Adjusted Y coordinate to 20
// Add QR code image
$pdf->Image('@' . $imgdata, 55, 55, 100, 100, 'PNG'); // Adjusted 100px down
// Add text
$pdf->SetXY(15, 55); // Adjusted 100px down
$pdf->writeHTMLCell(0, 0, '', '', '<h3 style="font-family: Times New Roman, Times, serif;">XXVII SYMPOSIUM ON OPERATIONAL APPLICATIONS IN DEFENSE AREAS</h3>', 0, 1, 0, true, 'C', true);
//$pdf->SetXY(15, 65); // Adjusted 100px down
// Prepare the HTML content
$html_content = '<div class="badge-box">';
$html_content .= '<p align="justify" style="margin-top: 10px;">Dear <strong>' . esc_html($full_name) . '</strong>,</p>';
$html_content .= '<h3>Activities for ' . $current_year . '</h3>';
$html_content .= '<p style="color: crimson; font-weight: bold; margin-top: 10px;">Enrollment status on : ' . date('d-m-Y - H:i:s') . '</p>';
if (!empty($events)) {
foreach ($events as $event_name => $activities) {
$html_content .= '<div class="event-box"><h4><strong>' . esc_html($event_name) . '</strong></h4><ul>';
foreach ($activities as $activity) {
$html_content .= '<li>'
. '<strong>Activity:</strong> ' . esc_html($activity['activity_name']) . '<br>'
. '<strong>Modality:</strong> ' . esc_html($activity['modality']) . '<br>'
. '<strong>Status:</strong> ' . esc_html($activity['status'])
. '</li>';
$html_content .= '<li style="list-style-type: none;"></li>';
}
$html_content .= '</ul></div><p>&nbsp;</p>'; // Add <p> to separate content
}
} else {
$html_content .= '<p>No activities available for this year.</p>';
}
$html_content .= '<p style="margin-top: 20px;">Contact the event Organizing Committee for questions via email at sige@ita.br</p>';
$html_content .= '</div>';
// Add HTML content
$pdf->SetXY(15, 140); // Adjusted 100px down
$pdf->writeHTMLCell(0, 0, '', '', $css . $html_content, 0, 1, 0, true, '', true);
// Output PDF
$pdf->Output('user_badge.pdf', 'D');
wp_die();
}
function verifyUserBasedOnQRCode($hashed_user_id, &$error_message = '')
{
// Validação básica do formato do hash MD5
if (!preg_match('/^[a-f0-9]{32}$/i', $hashed_user_id)) {
$error_message = 'Formato de hash inválido.';
return false;
}
$secret_phrase = 'KrWy5Zc5q3gqSxPTzrw36fYrnafsRt57si6pRUpeHJNGkvQcGj';
// Tenta obter mapa em cache (transient de curta duração)
$cache_key = 'sige_qr_hash_user_map';
$hash_map = get_transient($cache_key);
if ($hash_map === false || !is_array($hash_map)) {
$hash_map = [];
// Usa apenas IDs para economizar memória
$user_ids = get_users(['fields' => 'ids']);
foreach ($user_ids as $uid) {
$hash_map[md5($secret_phrase . $uid)] = $uid;
}
// Cache por 10 minutos
set_transient($cache_key, $hash_map, 10 * MINUTE_IN_SECONDS);
}
if (isset($hash_map[$hashed_user_id])) {
return (int)$hash_map[$hashed_user_id];
}
// Fallback adicional (caso algum usuário novo não esteja em cache ainda)
// Evita reconstruir tudo de novo: checa último user_id criado
$maybe_new_user_id = username_exists($hashed_user_id); // provavel falso, apenas placeholder
// (Mantido para possível extensão futura)
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[verifyUserBasedOnQRCode] Hash não encontrado: ' . $hashed_user_id);
}
return false;
}
function format_full_name($full_name)
{
// Convert the full name to uppercase using multibyte function
$full_name = mb_strtoupper($full_name, 'UTF-8');
// Prepositions to keep intact
$prepositions = ['DE', 'DA', 'DO', 'DAS', 'DOS', 'E'];
// Check if the total length of the name is less than or equal to 25
if (strlen($full_name) <= 15) {
return $full_name;
}
// Process name if length exceeds 15 characters
$name_parts = explode(' ', $full_name); // Split name by spaces
$formatted_name = '';
$char_count = 0;
// Build the formatted name up to the last full name part under 15 characters
foreach ($name_parts as $index => $part) {
// Always include prepositions and conjunctions as full words
if (in_array($part, $prepositions)) {
$formatted_name .= $part . ' ';
$char_count += strlen($part) + 1;
} elseif ($char_count + strlen($part) <= 15) {
// Add full parts of the name if still within limit
$formatted_name .= $part . ' ';
$char_count += strlen($part) + 1;
} else {
break; // Stop if adding the next part would exceed 15 characters
}
}
// For the remaining parts, abbreviate them by using initials
for ($i = $index; $i < count($name_parts); $i++) {
if (!in_array($name_parts[$i], $prepositions)) {
$formatted_name .= $name_parts[$i][0] . '.';
$char_count += 2; // 1 for the initial and 1 for the period
}
}
// Ensure the final name is trimmed of any extra spaces and return it
return trim($formatted_name);
}
function generate_attendance_pdf()
{
if (isset($_POST['download_pdf']) && $_POST['download_pdf'] == 1) {
if (!is_user_logged_in()) {
wp_send_json_error(array('message' => 'You must be logged in to create and download the PDF of name Labels.'));
return;
}
global $wpdb;
$current_user_id = get_current_user_id();
// Capture form inputs
$TopCorrection = floatval($_POST['TopCorrection']);
$LeftCorrection = floatval($_POST['LeftCorrection']);
$TopMargin = floatval($_POST['TopMargin']);
$LabelHeight = floatval($_POST['LabelHeight']);
$LeftMargin = floatval($_POST['LeftMargin']);
$LabelWidth = floatval($_POST['LabelWidth']);
$status = sanitize_text_field($_POST['attendance_status']);
$start_datetime = sanitize_text_field($_POST['start_datetime']);
$end_datetime = sanitize_text_field($_POST['end_datetime']);
$sort_order = sanitize_text_field($_POST['sort_order']); // Get sorting order (Asc/Desc)
// Update user metadata
update_user_meta($current_user_id, 'TopCorrection', $TopCorrection);
update_user_meta($current_user_id, 'LeftCorrection', $LeftCorrection);
update_user_meta($current_user_id, 'TopMargin', $TopMargin);
update_user_meta($current_user_id, 'LabelHeight', $LabelHeight);
update_user_meta($current_user_id, 'LeftMargin', $LeftMargin);
update_user_meta($current_user_id, 'LabelWidth', $LabelWidth);
update_user_meta($current_user_id, 'attendance_status', $status);
update_user_meta($current_user_id, 'start_datetime', $start_datetime);
update_user_meta($current_user_id, 'end_datetime', $end_datetime);
update_user_meta($current_user_id, 'sort_order', $sort_order); // Save sorting order
// Fetch users based on the selected status, date range, and sorting order, filtering by activity type and modality
$users = $wpdb->get_results($wpdb->prepare("
SELECT DISTINCT u.ID, u.user_email
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
WHERE e.status = %s
AND e.enrollment_date BETWEEN %s AND %s
AND a.type = 'Main Event'
AND a.modality IN ('In-person', 'Hybrid')
", $status, $start_datetime, $end_datetime));
// Sort users by formatted full name
usort($users, function ($a, $b) use ($sort_order) {
// Initialize the Collator for the current locale (e.g., "en_US" or "pt_BR")
$collator = new Collator('pt_BR'); // Adjust locale if necessary
$name_a = format_full_name(get_user_meta($a->ID, 'full_name', true) ?: $a->user_email);
$name_b = format_full_name(get_user_meta($b->ID, 'full_name', true) ?: $b->user_email);
// Log the names and sort order for debugging
error_log("Comparing: $name_a and $name_b (Sort order: $sort_order)");
if ($sort_order == 'Asc') {
return $collator->compare($name_a, $name_b);
} else {
return $collator->compare($name_b, $name_a);
}
});
// Create a new PDF document
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, 'LETTER', true, 'UTF-8', false);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->AddPage();
// If no users are found, add a message to the PDF with status, start date, and end date
if (empty($users)) {
$message = 'No users found for status: ' . $status . "\n" .
'Start Date and Time: ' . $start_datetime . "\n" .
'End Date and Time: ' . $end_datetime;
// Display the message on the PDF
$pdf->SetXY(15, 50);
$pdf->SetFont('Helvetica', '', 14);
$pdf->MultiCell(0, 10, $message, 0, 'C');
} else {
// Define positions for the labels dynamically with corrections
$label_positions = [];
for ($row = 0; $row < 10; $row++) {
$top_value = $TopMargin + ($row * $LabelHeight) + $TopCorrection;
$left_1 = $LeftMargin + $LeftCorrection;
$left_2 = $left_1 + $LabelWidth;
$left_3 = $left_2 + $LabelWidth;
$label_positions[] = ['top' => $top_value, 'left' => $left_1]; // Column 1
$label_positions[] = ['top' => $top_value, 'left' => $left_2]; // Column 2
$label_positions[] = ['top' => $top_value, 'left' => $left_3]; // Column 3
}
$i = 0; // Counter for label positions
foreach ($users as $user) {
// Get user's full name from metadata or fallback to email
$full_name = get_user_meta($user->ID, 'full_name', true);
if (!$full_name) {
$full_name = $user->user_email; // Fallback to email if no full_name is available
} else {
// Format the full_name using the support function
$full_name = format_full_name($full_name);
}
// Add full name to the current label position
if (isset($label_positions[$i])) {
$position = $label_positions[$i];
$pdf->SetXY($position['left'], $position['top']);
$pdf->Cell(60, 10, $full_name, 0, 1, 'L');
}
$i++;
// Add new page after filling positions on one page
if ($i % count($label_positions) == 0) {
$pdf->AddPage();
$i = 0;
}
}
}
// Generate file name with date, time, and status
$date_time = date('Y-m-d_H-i-s');
$file_name = "attendance_{$status}_{$date_time}.pdf"; // This uses the selected status in the file name
// Output PDF as a downloadable file
$pdf->Output($file_name, 'I');
wp_die();
} else {
// Log if the download PDF button was not pressed
error_log('Download PDF button not pressed.');
}
}
add_action('wp_ajax_generate_attendance_pdf', 'generate_attendance_pdf');
add_action('wp_ajax_nopriv_generate_attendance_pdf', 'generate_attendance_pdf'); // If you want to allow non-logged-in users as well
function generate_pdf_shortcode()
{
if (!is_user_logged_in()) {
return '<div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #e0e0e0; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); z-index: 999; text-align: center;">
<p>You must be logged in to handle the label edition.</p>
</div>';
}
// Get the current user ID
$current_user_id = get_current_user_id();
// Retrieve user metadata or set default values, handle 0 values correctly by using explicit checks for false
$TopCorrection = get_user_meta($current_user_id, 'TopCorrection', true);
$TopCorrection = ($TopCorrection !== false && $TopCorrection !== '') ? floatval($TopCorrection) : 0;
$LeftCorrection = get_user_meta($current_user_id, 'LeftCorrection', true);
$LeftCorrection = ($LeftCorrection !== false && $LeftCorrection !== '') ? floatval($LeftCorrection) : 0;
$TopMargin = get_user_meta($current_user_id, 'TopMargin', true);
$TopMargin = ($TopMargin !== false && $TopMargin !== '') ? floatval($TopMargin) : 17;
$LabelHeight = get_user_meta($current_user_id, 'LabelHeight', true);
$LabelHeight = ($LabelHeight !== false && $LabelHeight !== '') ? floatval($LabelHeight) : 25.8;
$LeftMargin = get_user_meta($current_user_id, 'LeftMargin', true);
$LeftMargin = ($LeftMargin !== false && $LeftMargin !== '') ? floatval($LeftMargin) : 4.8;
$LabelWidth = get_user_meta($current_user_id, 'LabelWidth', true);
$LabelWidth = ($LabelWidth !== false && $LabelWidth !== '') ? floatval($LabelWidth) : 70.8;
// Define the $attendance_status variable, check if it's set in the metadata or POST
$attendance_status = get_user_meta($current_user_id, 'attendance_status', true);
if (!$attendance_status) {
$attendance_status = isset($_POST['attendance_status']) ? sanitize_text_field($_POST['attendance_status']) : 'Approved';
}
// Use current date and time if start_datetime or end_datetime is not set
$start_datetime = get_user_meta($current_user_id, 'start_datetime', true)
? get_user_meta($current_user_id, 'start_datetime', true)
: (isset($_POST['start_datetime']) && !empty($_POST['start_datetime'])
? sanitize_text_field($_POST['start_datetime'])
: current_time('Y-m-d\TH:i'));
$end_datetime = get_user_meta($current_user_id, 'end_datetime', true)
? get_user_meta($current_user_id, 'end_datetime', true)
: (isset($_POST['end_datetime']) && !empty($_POST['end_datetime'])
? sanitize_text_field($_POST['end_datetime'])
: current_time('Y-m-d\TH:i'));
// Retrieve the sort order from user metadata or use a default value
$sort_order = get_user_meta($current_user_id, 'sort_order', true);
if (!$sort_order) {
$sort_order = isset($_POST['sort_order']) ? sanitize_text_field($_POST['sort_order']) : 'Asc';
}
ob_start();
?>
<style>
/* Flex container setup */
.flex-container {
display: flex;
justify-content: space-between;
gap: 10px;
flex-wrap: wrap;
}
.flex-container>div {
flex: 1;
min-width: 280px;
margin-bottom: 20px;
}
/* Align range inputs and labels */
.range-wrapper {
display: flex;
align-items: center;
/* Aligns the label and range input vertically centered */
justify-content: space-between;
/* Ensure labels and range inputs are spread out */
width: 100%;
}
.range-wrapper label {
flex-basis: 20%;
/* Labels take up 20% of the width */
white-space: nowrap;
/* Prevent the label from wrapping */
text-align: left;
}
.range-wrapper input[type="range"] {
flex-basis: 75%;
/* Range inputs take up the remaining width */
margin-left: 10px;
padding: 5px 0;
box-sizing: border-box;
}
/* Make labels for select boxes and input fields appear above */
.form-group {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 5px;
width: 100%;
}
/* Ensure both input and select elements have the same width */
input[type="datetime-local"],
select {
width: 100%;
max-width: 100%;
padding: 8px;
font-size: 16px;
box-sizing: border-box;
}
/* Full width for Data Fetch section on smaller screens */
.data-fetch-container {
width: 100%;
max-width: 600px;
margin-bottom: 20px;
}
.flex-column-container {
display: flex;
justify-content: space-between;
gap: 20px;
}
/* Responsive behavior for smaller screens */
@media (max-width: 768px) {
.flex-container,
.flex-column-container {
flex-direction: column;
}
.flex-container>div,
.flex-column-container>div {
min-width: 100%;
}
}
/* Additional responsiveness for very small screens */
@media (max-width: 400px) {
.flex-container,
.flex-column-container {
flex-direction: column;
}
.flex-container>div,
.flex-column-container>div {
min-width: 100%;
}
}
</style>
<!-- Modal Structure -->
<div id="noEmailsModal" style="display: none; position: fixed; z-index: 9999; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4);">
<div style="background-color: white; margin: 15% auto; padding: 20px; border: 1px solid #888; width: 80%; max-width: 500px; text-align: center;">
<p id="modalText"></p>
<button id="closeModal" style="background-color: #0073aa; color: white; border: none; padding: 10px 20px; cursor: pointer;">Close</button>
</div>
</div>
<form method="post" id="pdfForm" style="text-align: center; margin-top: 20px;">
<input type="hidden" name="download_pdf" value="1">
<!-- Layout Controls Section -->
<div style="background-color: #e0f7fa; padding: 20px; border-radius: 15px; box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1); margin-bottom: 20px; display: inline-block; width: 100%; max-width: 600px;">
<h3 style="margin-bottom: 15px;">Layout Controls</h3>
<div class="flex-container">
<div>
<div class="range-wrapper">
<label for="TopMargin">Top Margin:</label>
<input type="range" min="0" max="100" step="0.1" name="TopMargin" id="TopMargin" value="<?php echo esc_attr($TopMargin); ?>" oninput="document.getElementById('TopMarginValue').innerText = this.value;">
<span id="TopMarginValue"><?php echo esc_attr($TopMargin); ?></span>
</div>
<div class="range-wrapper">
<label for="TopCorrection">Top Correction:</label>
<input type="range" min="0" max="100" step="0.1" name="TopCorrection" id="TopCorrection" value="<?php echo esc_attr($TopCorrection); ?>" oninput="document.getElementById('TopCorrectionValue').innerText = this.value;">
<span id="TopCorrectionValue"><?php echo esc_attr($TopCorrection); ?></span>
</div>
<div class="range-wrapper">
<label for="LabelWidth">Label Width:</label>
<input type="range" min="0" max="100" step="0.1" name="LabelWidth" id="LabelWidth" value="<?php echo esc_attr($LabelWidth); ?>" oninput="document.getElementById('LabelWidthValue').innerText = this.value;">
<span id="LabelWidthValue"><?php echo esc_attr($LabelWidth); ?></span>
</div>
</div>
<div>
<div class="range-wrapper">
<label for="LeftMargin">Left Margin:</label>
<input type="range" min="0" max="100" step="0.1" name="LeftMargin" id="LeftMargin" value="<?php echo esc_attr($LeftMargin); ?>" oninput="document.getElementById('LeftMarginValue').innerText = this.value;">
<span id="LeftMarginValue"><?php echo esc_attr($LeftMargin); ?></span>
</div>
<div class="range-wrapper">
<label for="LeftCorrection">Left Correction:</label>
<input type="range" min="0" max="100" step="0.1" name="LeftCorrection" id="LeftCorrection" value="<?php echo esc_attr($LeftCorrection); ?>" oninput="document.getElementById('LeftCorrectionValue').innerText = this.value;">
<span id="LeftCorrectionValue"><?php echo esc_attr($LeftCorrection); ?></span>
</div>
<div class="range-wrapper">
<label for="LabelHeight">Label Height:</label>
<input type="range" min="0" max="100" step="0.1" name="LabelHeight" id="LabelHeight" value="<?php echo esc_attr($LabelHeight); ?>" oninput="document.getElementById('LabelHeightValue').innerText = this.value;">
<span id="LabelHeightValue"><?php echo esc_attr($LabelHeight); ?></span>
</div>
</div>
</div>
</div>
<!-- Data Fetch Section -->
<div style="background-color: #e0f7fa; padding: 20px; border-radius: 15px; box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1); margin-bottom: 20px; display: inline-block; width: 100%; max-width: 600px;">
<h3 style="margin-bottom: 15px;">Data Fetch</h3>
<div class="flex-container">
<div class="form-group">
<label for="start_datetime">Start Date and Time:</label>
<input type="datetime-local" id="start_datetime" name="start_datetime" value="<?php echo esc_attr($start_datetime); ?>" required>
</div>
<div class="form-group">
<label for="end_datetime">End Date and Time:</label>
<input type="datetime-local" id="end_datetime" name="end_datetime" value="<?php echo esc_attr($end_datetime); ?>" required>
</div>
<div class="form-group">
<label for="attendance_status">Select Status:</label>
<select name="attendance_status">
<option value="Approved" <?php selected($attendance_status, 'Approved'); ?>>Approved</option>
<option value="Waiting List" <?php selected($attendance_status, 'Waiting List'); ?>>Waiting List</option>
<option value="Not Requested" <?php selected($attendance_status, 'Not Requested'); ?>>Not Requested</option>
</select>
</div>
<div class="form-group">
<label for="sort_order">Sort By Name:</label>
<select name="sort_order" id="sort_order">
<option value="Asc" <?php selected($sort_order, 'Asc'); ?>>Ascending</option>
<option value="Desc" <?php selected($sort_order, 'Desc'); ?>>Descending</option>
</select>
</div>
</div>
</div>
<!-- Button Section -->
<div style="text-align: center; margin-top: 20px;">
<!-- Download PDF Button -->
<button type="submit" class="button button-primary">Download PDF</button>
</div>
</form>
<script>
document.getElementById('pdfForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
formData.append('action', 'generate_attendance_pdf'); // Important: add the 'action' parameter for AJAX
fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
method: 'POST',
body: formData,
})
.then(response => response.blob())
.then(blob => {
const attendanceStatus = document.querySelector('select[name="attendance_status"]').value;
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
const fileName = 'attendance_' + attendanceStatus + '_' + new Date().toISOString().slice(0, 19).replace(/:/g, "-") + '.pdf';
a.download = fileName;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
})
.catch(error => console.error('Download failed:', error));
});
</script>
<?php
return ob_get_clean();
}
add_shortcode('generate_attendance_pdf', 'generate_pdf_shortcode');
function CertificateVerificationProcedure_pt()
{
global $wpdb;
// Initialize variables
$filtered_user_id = '';
$qrScannerUsedInput = isset($_POST['filtered_user_id']) ? sanitize_text_field($_POST['filtered_user_id']) : '';
$selected_year = isset($_POST['certificate_year']) ? intval($_POST['certificate_year']) : date('Y');
$show_no_certificates_modal = false;
$show_no_user_modal = false;
// Get the current year and next 5 years
$current_year = date('Y');
$years = range($current_year, $current_year + 0);
// Handle QR code verification when form is submitted
if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($qrScannerUsedInput)) {
// Apply the QR code verification to get the user ID
$filtered_user_id = verifyUserBasedOnQRCodefromCertificate($qrScannerUsedInput, $selected_year);
}
// Fetch enrollments for Hybrid and In-person activities
$hybrid_in_person_results = [];
$online_results = [];
$full_name = '';
$user_email = '';
if (!empty($filtered_user_id)) {
// Query for Hybrid and In-person attendance
$hybrid_in_person_query = "
SELECT e.activity_id, a.name as activity_name, a.type, a.modality, a.start_date, a.start_time, a.end_date, a.end_time,
um.meta_value as user_full_name, u.user_email
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'full_name'
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.user_id = %d
AND ac.attended = 'yes'
AND YEAR(a.start_date) = %d
";
$hybrid_in_person_results = $wpdb->get_results($wpdb->prepare($hybrid_in_person_query, $filtered_user_id, $selected_year));
// Query for Online attendance
$online_query = "
SELECT e.activity_id, a.name as activity_name, a.type, a.modality, a.start_date, a.start_time, a.end_date, a.end_time,
um.meta_value as user_full_name, u.user_email
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'full_name'
LEFT JOIN {$wpdb->prefix}sige_enrollment_online_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.user_id = %d
AND ac.attended = 'yes'
AND YEAR(a.start_date) = %d
";
$online_results = $wpdb->get_results($wpdb->prepare($online_query, $filtered_user_id, $selected_year));
// Get the user's full name and email for displaying
if (!empty($hybrid_in_person_results)) {
$full_name = $hybrid_in_person_results[0]->user_full_name;
$user_email = $hybrid_in_person_results[0]->user_email;
} elseif (!empty($online_results)) {
$full_name = $online_results[0]->user_full_name;
$user_email = $online_results[0]->user_email;
} else {
$full_name = $wpdb->get_var($wpdb->prepare("SELECT meta_value FROM {$wpdb->prefix}usermeta WHERE user_id = %d AND meta_key = 'full_name'", $filtered_user_id));
$user_email = $wpdb->get_var($wpdb->prepare("SELECT user_email FROM {$wpdb->prefix}users WHERE ID = %d", $filtered_user_id));
$show_no_certificates_modal = true; // Trigger the no certificates modal if no results found
}
} elseif ($_SERVER['REQUEST_METHOD'] == 'POST') {
$show_no_user_modal = true; // Trigger the no user modal if QR code doesn't match any user
}
// Output the certificate verification form
ob_start();
echo '<div class="wrap"><h2 style="text-align: center;">VERIFICAÇÃO DE VALIDADE DO CERTIFICADO</h2>';
// Add a styled container for the form elements
echo '
<div style="background-color: #e0f7fa; padding: 20px; border-radius: 10px; box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1); max-width: 600px; margin: 0 auto; text-align: center;">
<form method="post" action="" id="qrCodeForm">
<input type="text" name="filtered_user_id" id="filtered_user_id" placeholder="Enter QR Code" value="' . esc_attr($qrScannerUsedInput) . '" required style="width: 80%; padding: 10px; border-radius: 5px; margin-bottom: 10px;" />
<br>
<select name="certificate_year" id="certificate_year" style="padding: 10px; border-radius: 5px; margin-bottom: 10px; width: 80%;">
'; // Populate the dropdown with years
foreach ($years as $year) {
echo '<option value="' . $year . '" ' . selected($selected_year, $year, false) . '>' . $year . '</option>';
}
echo '
</select>
<br>
<button type="submit" class="button button-primary" style="width: 80%; padding: 10px; margin-bottom: 10px;">Verify Certificate</button>
</form>
<p style="margin: 10px 0; font-weight: bold;">OR</p> <!-- This is the OR text between the buttons -->
<button id="start-qr-reader" class="button button-secondary" style="width: 80%; padding: 10px; margin-bottom: 10px;">Start QR Scanner</button>
<div id="qr-reader" style="width:300px; margin: 10px auto;"></div>
</div>';
// Show Hybrid and In-person results first
if (!empty($hybrid_in_person_results)) {
echo '<h3 style="margin-top: 20px;">Hybrid and In-Person Attendance</h3>';
// Display full name and email
echo '<p><strong>Nome:</strong> ' . esc_html($full_name) . '</p>';
echo '<p><strong>Email:</strong> ' . esc_html($user_email) . '</p>';
foreach ($hybrid_in_person_results as $result) {
echo '<div style="margin-top: 20px; padding: 10px; background-color: #f7f7f7; border: 1px solid #ddd;">
<h4>Atividade: ' . esc_html($result->activity_name) . '</h4>
<p><strong>Tipo:</strong> ' . esc_html($result->type) . '</p>
<p><strong>Modalidade:</strong> ' . esc_html($result->modality) . '</p>
<p><strong>Data de início:</strong> ' . esc_html($result->start_date) . ' at ' . esc_html($result->start_time) . '</p>
<p><strong>Data de término:</strong> ' . esc_html($result->end_date) . ' at ' . esc_html($result->end_time) . '</p>
</div>';
}
}
// Show Online results next
if (!empty($online_results)) {
echo '<h3 style="margin-top: 20px;">Online Attendance</h3>';
// Display full name and email if not already displayed
if (empty($hybrid_in_person_results)) {
echo '<p><strong>Nome:</strong> ' . esc_html($full_name) . '</p>';
echo '<p><strong>Email:</strong> ' . esc_html($user_email) . '</p>';
}
foreach ($online_results as $result) {
echo '<div style="margin-top: 20px; padding: 10px; background-color: #f7f7f7; border: 1px solid #ddd;">
<h4>Atividade: ' . esc_html($result->activity_name) . '</h4>
<p><strong>Tipo:</strong> ' . esc_html($result->type) . '</p>
<p><strong>Modalidade:</strong> ' . esc_html($result->modality) . '</p>
<p><strong>Data de início:</strong> ' . esc_html($result->start_date) . ' at ' . esc_html($result->start_time) . '</p>
<p><strong>Data de término:</strong> ' . esc_html($result->end_date) . ' at ' . esc_html($result->end_time) . '</p>
</div>';
}
}
// Add the modals for no certificates or no user found
if ($show_no_certificates_modal) {
echo '
<style>
.modal {
display: block;
position: fixed;
z-index: 999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4); /* Transparent background */
}
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 500px;
text-align: center;
border-radius: 10px; /* Optional for rounded corners */
}
.button-secondary {
background-color: #6c757d;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.button-secondary:hover {
background-color: #5a6268;
}
</style>
<div id="noCertificatesModal" class="modal">
<div class="modal-content">
<h2>No Attendance Certificates Found</h2>
<p>Não há certificados de participação para <strong>' . esc_html($full_name) . '</strong> para o ano <strong>' . esc_html($selected_year) . '</strong>.</p>
<button class="button button-secondary close-modal" data-modal="noCertificatesModal">Close</button>
</div>
</div>';
}
if ($show_no_user_modal) {
echo '
<style>
.modal {
display: block;
position: fixed;
z-index: 999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4); /* Transparent background */
}
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 500px;
text-align: center;
border-radius: 10px; /* Optional for rounded corners */
}
.button-secondary {
background-color: #6c757d;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.button-secondary:hover {
background-color: #5a6268;
}
</style>
<div id="noUserModal" class="modal">
<div class="modal-content">
<h2>Invalid QR Code</h2>
<p>A partir do QRCode fornecido, não foi possível identificar o usuário em nosso banco de dados para o ano selecionado. Por favor, se o problema persistir, entre em contato conosco em <strong>webti.sige@ita.br</strong>.</p>
<button class="button button-secondary close-modal" data-modal="noUserModal">Close</button>
</div>
</div>';
}
// Add custom JavaScript for handling QR code scanning and modals
echo '<script>
document.addEventListener("DOMContentLoaded", function() {
function initializeQrCodeScanner() {
if (typeof Html5Qrcode !== "undefined") {
const qrReader = new Html5Qrcode("qr-reader");
const startQrReaderBtn = document.getElementById("start-qr-reader");
const userIdInput = document.getElementById("filtered_user_id");
startQrReaderBtn.addEventListener("click", function() {
if (startQrReaderBtn.textContent === "Stop QR Scanner") {
qrReader.stop();
startQrReaderBtn.textContent = "Start QR Scanner";
} else {
qrReader.start(
{ facingMode: "environment" },
{
fps: 10,
qrbox: 250
},
qrCodeMessage => {
userIdInput.value = qrCodeMessage;
qrReader.stop();
startQrReaderBtn.textContent = "Start QR Scanner";
document.getElementById("qrCodeForm").submit();
},
errorMessage => {
console.warn(`QR Code scanning error: ${errorMessage}`);
})
.then(() => {
startQrReaderBtn.textContent = "Stop QR Scanner";
})
.catch(err => {
console.error(`Unable to start QR Code scanning: ${err}`);
});
}
});
} else {
console.error("Html5Qrcode library is not loaded properly.");
}
}
function closeModal(modalId) {
document.getElementById(modalId).style.display = "none";
}
document.querySelectorAll(".close-modal").forEach(button => {
button.addEventListener("click", function() {
closeModal(this.getAttribute("data-modal"));
});
});
initializeQrCodeScanner(); // Initialize the QR code scanner when the page loads
});
</script>';
echo '</div>'; // End of wrapper div
return ob_get_clean();
}
// Register the shortcode to display the certificate verification procedure on the frontend
add_shortcode('certificate_verification_pt', 'CertificateVerificationProcedure_pt');
function CertificateVerificationProcedure_en()
{
global $wpdb;
// Initialize variables
$filtered_user_id = '';
$qrScannerUsedInput = isset($_POST['filtered_user_id']) ? sanitize_text_field($_POST['filtered_user_id']) : '';
$selected_year = isset($_POST['certificate_year']) ? intval($_POST['certificate_year']) : date('Y');
$show_no_certificates_modal = false;
$show_no_user_modal = false;
// Get the current year and next 5 years
$current_year = date('Y');
$years = range($current_year, $current_year + 0);
// Handle QR code verification when form is submitted
if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($qrScannerUsedInput)) {
// Apply the QR code verification to get the user ID
$filtered_user_id = verifyUserBasedOnQRCodefromCertificate($qrScannerUsedInput, $selected_year);
}
// Fetch enrollments for Hybrid and In-person activities
$hybrid_in_person_results = [];
$online_results = [];
$full_name = '';
$user_email = '';
if (!empty($filtered_user_id)) {
// Query for Hybrid and In-person attendance
$hybrid_in_person_query = "
SELECT e.activity_id, a.name as activity_name, a.type, a.modality, a.start_date, a.start_time, a.end_date, a.end_time,
um.meta_value as user_full_name, u.user_email
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'full_name'
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.user_id = %d
AND ac.attended = 'yes'
AND YEAR(a.start_date) = %d
";
$hybrid_in_person_results = $wpdb->get_results($wpdb->prepare($hybrid_in_person_query, $filtered_user_id, $selected_year));
// Query for Online attendance
$online_query = "
SELECT e.activity_id, a.name as activity_name, a.type, a.modality, a.start_date, a.start_time, a.end_date, a.end_time,
um.meta_value as user_full_name, u.user_email
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}users u ON e.user_id = u.ID
LEFT JOIN {$wpdb->prefix}usermeta um ON e.user_id = um.user_id AND um.meta_key = 'full_name'
LEFT JOIN {$wpdb->prefix}sige_enrollment_online_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.user_id = %d
AND ac.attended = 'yes'
AND YEAR(a.start_date) = %d
";
$online_results = $wpdb->get_results($wpdb->prepare($online_query, $filtered_user_id, $selected_year));
// Get the user's full name and email for displaying
if (!empty($hybrid_in_person_results)) {
$full_name = $hybrid_in_person_results[0]->user_full_name;
$user_email = $hybrid_in_person_results[0]->user_email;
} elseif (!empty($online_results)) {
$full_name = $online_results[0]->user_full_name;
$user_email = $online_results[0]->user_email;
} else {
$full_name = $wpdb->get_var($wpdb->prepare("SELECT meta_value FROM {$wpdb->prefix}usermeta WHERE user_id = %d AND meta_key = 'full_name'", $filtered_user_id));
$user_email = $wpdb->get_var($wpdb->prepare("SELECT user_email FROM {$wpdb->prefix}users WHERE ID = %d", $filtered_user_id));
$show_no_certificates_modal = true; // Trigger the no certificates modal if no results found
}
} elseif ($_SERVER['REQUEST_METHOD'] == 'POST') {
$show_no_user_modal = true; // Trigger the no user modal if QR code doesn't match any user
}
// Output the certificate verification form
ob_start();
echo '<div class="wrap"><h2 style="text-align: center;">CERTIFICATE VALIDITY CHECK</h2>';
// Add a styled container for the form elements
echo '
<div style="background-color: #e0f7fa; padding: 20px; border-radius: 10px; box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1); max-width: 600px; margin: 0 auto; text-align: center;">
<form method="post" action="" id="qrCodeForm">
<input type="text" name="filtered_user_id" id="filtered_user_id" placeholder="Enter QR Code" value="' . esc_attr($qrScannerUsedInput) . '" required style="width: 80%; padding: 10px; border-radius: 5px; margin-bottom: 10px;" />
<br>
<select name="certificate_year" id="certificate_year" style="padding: 10px; border-radius: 5px; margin-bottom: 10px; width: 80%;">
'; // Populate the dropdown with years
foreach ($years as $year) {
echo '<option value="' . $year . '" ' . selected($selected_year, $year, false) . '>' . $year . '</option>';
}
echo '
</select>
<br>
<button type="submit" class="button button-primary" style="width: 80%; padding: 10px; margin-bottom: 10px;">Verify Certificate</button>
</form>
<p style="margin: 10px 0; font-weight: bold;">OR</p> <!-- This is the OR text between the buttons -->
<button id="start-qr-reader" class="button button-secondary" style="width: 80%; padding: 10px; margin-bottom: 10px;">Start QR Scanner</button>
<div id="qr-reader" style="width:300px; margin: 10px auto;"></div>
</div>';
// Show Hybrid and In-person results first
if (!empty($hybrid_in_person_results)) {
echo '<h3 style="margin-top: 20px;">Hybrid and In-Person Attendance</h3>';
// Display full name and email
echo '<p><strong>Name:</strong> ' . esc_html($full_name) . '</p>';
echo '<p><strong>Email:</strong> ' . esc_html($user_email) . '</p>';
foreach ($hybrid_in_person_results as $result) {
echo '<div style="margin-top: 20px; padding: 10px; background-color: #f7f7f7; border: 1px solid #ddd;">
<h4>Activity: ' . esc_html($result->activity_name) . '</h4>
<p><strong>Type:</strong> ' . esc_html($result->type) . '</p>
<p><strong>Modality:</strong> ' . esc_html($result->modality) . '</p>
<p><strong>Start Date:</strong> ' . esc_html($result->start_date) . ' at ' . esc_html($result->start_time) . '</p>
<p><strong>End Date:</strong> ' . esc_html($result->end_date) . ' at ' . esc_html($result->end_time) . '</p>
</div>';
}
}
// Show Online results next
if (!empty($online_results)) {
echo '<h3 style="margin-top: 20px;">Online Attendance</h3>';
// Display full name and email if not already displayed
if (empty($hybrid_in_person_results)) {
echo '<p><strong>Name:</strong> ' . esc_html($full_name) . '</p>';
echo '<p><strong>Email:</strong> ' . esc_html($user_email) . '</p>';
}
foreach ($online_results as $result) {
echo '<div style="margin-top: 20px; padding: 10px; background-color: #f7f7f7; border: 1px solid #ddd;">
<h4>Activity: ' . esc_html($result->activity_name) . '</h4>
<p><strong>Type:</strong> ' . esc_html($result->type) . '</p>
<p><strong>Modality:</strong> ' . esc_html($result->modality) . '</p>
<p><strong>Start Date:</strong> ' . esc_html($result->start_date) . ' at ' . esc_html($result->start_time) . '</p>
<p><strong>End Date:</strong> ' . esc_html($result->end_date) . ' at ' . esc_html($result->end_time) . '</p>
</div>';
}
}
// Add the modals for no certificates or no user found
if ($show_no_certificates_modal) {
echo '
<style>
.modal {
display: block;
position: fixed;
z-index: 999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4); /* Transparent background */
}
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 500px;
text-align: center;
border-radius: 10px; /* Optional for rounded corners */
}
.button-secondary {
background-color: #6c757d;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.button-secondary:hover {
background-color: #5a6268;
}
</style>
<div id="noCertificatesModal" class="modal">
<div class="modal-content">
<h2>No Attendance Certificates Found</h2>
<p>There are no attendance certificates for <strong>' . esc_html($full_name) . '</strong> for the year <strong>' . esc_html($selected_year) . '</strong>.</p>
<button class="button button-secondary close-modal" data-modal="noCertificatesModal">Close</button>
</div>
</div>';
}
if ($show_no_user_modal) {
echo '
<style>
.modal {
display: block;
position: fixed;
z-index: 999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4); /* Transparent background */
}
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 500px;
text-align: center;
border-radius: 10px; /* Optional for rounded corners */
}
.button-secondary {
background-color: #6c757d;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.button-secondary:hover {
background-color: #5a6268;
}
</style>
<div id="noUserModal" class="modal">
<div class="modal-content">
<h2>Invalid QR Code</h2>
<p>From the QRCode provided, it was not possible to identify the user in our database for the year selected. Please, if the problem persists, contact us at <strong>webti.sige@ita.br</strong>.</p>
<button class="button button-secondary close-modal" data-modal="noUserModal">Close</button>
</div>
</div>';
}
// Add custom JavaScript for handling QR code scanning and modals
echo '<script>
document.addEventListener("DOMContentLoaded", function() {
function initializeQrCodeScanner() {
if (typeof Html5Qrcode !== "undefined") {
const qrReader = new Html5Qrcode("qr-reader");
const startQrReaderBtn = document.getElementById("start-qr-reader");
const userIdInput = document.getElementById("filtered_user_id");
startQrReaderBtn.addEventListener("click", function() {
if (startQrReaderBtn.textContent === "Stop QR Scanner") {
qrReader.stop();
startQrReaderBtn.textContent = "Start QR Scanner";
} else {
qrReader.start(
{ facingMode: "environment" },
{
fps: 10,
qrbox: 250
},
qrCodeMessage => {
userIdInput.value = qrCodeMessage;
qrReader.stop();
startQrReaderBtn.textContent = "Start QR Scanner";
document.getElementById("qrCodeForm").submit();
},
errorMessage => {
console.warn(`QR Code scanning error: ${errorMessage}`);
})
.then(() => {
startQrReaderBtn.textContent = "Stop QR Scanner";
})
.catch(err => {
console.error(`Unable to start QR Code scanning: ${err}`);
});
}
});
} else {
console.error("Html5Qrcode library is not loaded properly.");
}
}
function closeModal(modalId) {
document.getElementById(modalId).style.display = "none";
}
document.querySelectorAll(".close-modal").forEach(button => {
button.addEventListener("click", function() {
closeModal(this.getAttribute("data-modal"));
});
});
initializeQrCodeScanner(); // Initialize the QR code scanner when the page loads
});
</script>';
echo '</div>'; // End of wrapper div
return ob_get_clean();
}
// Register the shortcode to display the certificate verification procedure on the frontend
add_shortcode('certificate_verification_en', 'CertificateVerificationProcedure_en');
// Load the required TCPDF, FPDI, and QRCode libraries
require_once(plugin_dir_path(__FILE__) . 'libs/fpdf/fpdf.php');
require_once(plugin_dir_path(__FILE__) . 'fpdi/src/autoload.php');
require_once(plugin_dir_path(__FILE__) . 'phpqrcode/qrlib.php'); // Assuming you have PHP QR Code library
use setasign\Fpdi\TcpdfFpdi;
// Shortcode function to display the form
function display_certificate_form_pt()
{
// Only proceed if not in admin area or REST API
if (is_admin() || (defined('REST_REQUEST') && REST_REQUEST)) {
return ''; // Return empty string to prevent interference
}
// Disable cache for all users
nocache_headers();
// Append nocache query parameter to bust cache
if (!isset($_GET['nocache'])) {
// Append a unique timestamp-based parameter to the URL
$new_url = add_query_arg('nocache', time(), get_permalink());
wp_redirect($new_url);
exit();
}
// Check if the user is logged in
if (!is_user_logged_in()) {
$login_url = wp_login_url(get_permalink()); // Redirect to the current page after login
return '
<div style="
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #808080; /* Gray background */
color: #fff; /* White text color */
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
z-index: 1000;
text-align: center;
border-radius: 10px;
">
<p>Você precisa estar logado para obter seus certificados.</p>
<a href="' . esc_url($login_url) . '" style="color: #fff; text-decoration: underline;">Click here to log in</a>
</div>';
}
// Prevent back/forward navigation cache
echo '<script>
if (performance.navigation.type === performance.navigation.TYPE_BACK_FORWARD) {
window.location.reload(true); // Force reload on back/forward navigation
}
</script>';
// Prepare the output buffer
$output = '';
// Append the form HTML to the output buffer
$output .= '
<style>
.form-container {
background-color: #e0f7fa;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
padding: 20px;
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
}
.form-container select, .form-container button {
margin: 10px 0;
padding: 10px;
font-size: 16px;
border-radius: 5px;
border: 1px solid #ccc;
width: 100%;
max-width: 300px;
}
.form-container button {
background-color: #007BFF;
color: white;
border: none;
cursor: pointer;
transition: background-color 0.3s;
}
.form-container button:hover {
background-color: #0056b3;
}
</style>
<form method="get" class="form-container">
<input type="hidden" name="download_certificate" value="1">
<label for="certificate_year">Selecione o ano:</label>
<select name="certificate_year" id="certificate_year" required>
<option value="2024">2024</option>
<option value="2025">2025</option>
<!-- Add more years as needed -->
</select>
<button type="submit">Obter Certificado</button>
</form>';
return $output;
}
// Function to handle the file download
function handle_certificate_download_pt()
{
// Check if the download_certificate parameter is set
if (isset($_GET['download_certificate']) && $_GET['download_certificate'] == '1') {
// Ensure no output is sent before headers
if (ob_get_length()) {
ob_end_clean();
}
// Disable error display to prevent corrupting the file download
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(0);
// Start output buffering
ob_start();
// Check if the user is logged in
if (!is_user_logged_in()) {
wp_safe_redirect(wp_login_url(get_permalink()));
exit;
}
global $wpdb;
// Get the current user ID
$current_user_id = get_current_user_id();
// Retrieve the user's full name from metadata (or use display_name as a fallback)
$full_name = get_user_meta($current_user_id, 'full_name', true);
if (empty($full_name)) {
// If 'full_name' meta doesn't exist, fall back to display_name
$user_info = get_userdata($current_user_id);
$full_name = $user_info->display_name;
}
// Format the full name using the provided format function
if (function_exists('format_full_name_certificate')) {
$full_name = format_full_name_certificate($full_name);
} else {
// If the function doesn't exist, just use the full name as is
$full_name = $full_name;
}
// Get the selected year from the query parameter
$certificate_year = intval($_GET['certificate_year']);
// Fetch Hybrid and In-person attendance
$query_hybrid = $wpdb->prepare("
SELECT a.name as activity_name, a.start_date, a.end_date, a.start_time, a.end_time, a.type
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.user_id = %d AND ac.attended = 'yes' AND YEAR(a.start_date) = %d AND a.modality IN ('Hybrid', 'In-person') AND a.attendance_control = 'yes'
", $current_user_id, $certificate_year);
$hybrid_results = $wpdb->get_results($query_hybrid);
// Fetch Online attendance
$query_online = $wpdb->prepare("
SELECT a.name as activity_name, a.start_date, a.end_date, a.start_time, a.end_time, a.type
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}sige_enrollment_online_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.user_id = %d AND ac.attended = 'yes' AND YEAR(a.start_date) = %d AND a.modality = 'Online'
", $current_user_id, $certificate_year);
$online_results = $wpdb->get_results($query_online);
// Combine both results
$all_activities = array_merge($hybrid_results, $online_results);
$total_activities = count($all_activities);
// If no activities are found for the year, redirect back with an error message
if ($total_activities == 0) {
wp_safe_redirect(add_query_arg('no_certificates', '1', remove_query_arg(array('download_certificate', 'certificate_year'))));
exit;
}
// Secret phrase for generating a unique hash
$secret_phrase = 'CGLtShwG9qV5p3zmS3BR7G9J8iKCTe9Pd1BAyCCorBfpCCbB7F';
// Path to your PDF template
$template_path = plugin_dir_path(__FILE__) . 'templates/certificate_template_2024_pt.pdf';
// Ensure that the template file exists
if (!file_exists($template_path)) {
// Log error and redirect back with an error message
error_log('Error: Template not found at ' . $template_path);
wp_safe_redirect(add_query_arg('template_not_found', '1', remove_query_arg(array('download_certificate', 'certificate_year'))));
exit;
}
// Get the WordPress uploads directory
$upload_dir = wp_upload_dir();
$temp_dir = trailingslashit($upload_dir['basedir']) . 'certificate_temp_files/';
// Ensure the temporary directory exists
if (!file_exists($temp_dir)) {
if (!mkdir($temp_dir, 0755, true)) {
// Log error and redirect back with an error message
error_log('Error: Failed to create temporary directory at ' . $temp_dir);
wp_safe_redirect(add_query_arg('temp_dir_error', '1', remove_query_arg(array('download_certificate', 'certificate_year'))));
exit;
}
}
// Initialize variables
$certificate_number = 1;
$pdf_files = array(); // To store paths to temp PDF files
// Fixed y-position and font size
$y = 90; // Updated y-position to 90
$font_size = 20; // Font size remains 20
// Define months in Portuguese
$months = array(
'01' => 'janeiro',
'02' => 'fevereiro',
'03' => 'março',
'04' => 'abril',
'05' => 'maio',
'06' => 'junho',
'07' => 'julho',
'08' => 'agosto',
'09' => 'setembro',
'10' => 'outubro',
'11' => 'novembro',
'12' => 'dezembro',
);
// Loop over each activity to generate individual PDFs
foreach ($all_activities as $activity) {
// Generate $hashed_user_id for this certificate
$hashed_user_id = md5($secret_phrase . $current_user_id . $certificate_year . $certificate_number);
// Generate QR Code with the hashed user ID
ob_start();
QRcode::png($hashed_user_id, null, QR_ECLEVEL_L, 10); // Generates QR Code
$imageString = ob_get_contents(); // Get the QR code image as a string
ob_end_clean();
// Decode the image string into binary format for saving
$imgdata = base64_decode(str_replace('data:image/png;base64,', '', base64_encode($imageString)));
// Save the image temporarily
$temp_image_path = $temp_dir . 'temp_qrcode_' . $certificate_number . '.png';
if (file_put_contents($temp_image_path, $imgdata) === false) {
// Log error and redirect back with an error message
error_log('Error: Could not save QR code image to ' . $temp_image_path);
wp_safe_redirect(add_query_arg('qrcode_error', '1', remove_query_arg(array('download_certificate', 'certificate_year'))));
exit;
}
// Initialize TCPDF with FPDI
$pdf = new TcpdfFpdi();
// Call before the addPage() method
$pdf->SetPrintHeader(false);
$pdf->SetPrintFooter(false);
$pdf->AddPage('L'); // Set orientation to Landscape
// Import the certificate template
$pdf->setSourceFile($template_path);
$template_id = $pdf->importPage(1);
$pdf->useTemplate($template_id, 0, 0, 297, 210); // Adjust size to A4 Landscape
// Set margins
$pdf->SetMargins(15, 15, 15);
// Prepare date components
$start_date = strtotime($activity->start_date);
$end_date = strtotime($activity->end_date);
$start_day = date('d', $start_date);
$end_day = date('d', $end_date);
$month_num = date('m', $start_date); // Assuming start and end dates are in the same month
$year = date('Y', $start_date);
$month_name = $months[$month_num];
// Get the activity name
$activity_name = $activity->activity_name;
// Make the full name bold
$bold_full_name = '<b>' . $full_name . '</b>';
// Make the activity name bold
$bold_activity_name = '<b>' . $activity_name . '</b>';
// Get start_time and end_time, formatted as 'H:i'
$start_time = date('H:i', strtotime($activity->start_time));
$end_time = date('H:i', strtotime($activity->end_time));
// Calculate duration in seconds
$start_timestamp = strtotime($activity->start_date . ' ' . $activity->start_time);
$end_timestamp = strtotime($activity->end_date . ' ' . $activity->end_time);
$duration_in_seconds = $end_timestamp - $start_timestamp;
// Handle cases where end time is earlier than start time (e.g., over midnight)
if ($duration_in_seconds < 0) {
$duration_in_seconds += 24 * 3600; // Add 24 hours
}
// Calculate hours and minutes
$hours = floor($duration_in_seconds / 3600);
$minutes = floor(($duration_in_seconds % 3600) / 60);
// Format duration as 'HHhMM'
$duration_formatted = sprintf('%02dh%02d', $hours, $minutes);
// Build the activity information based on type
if ($activity->type == 'Main Event') {
$activity_info = "Certificamos que $bold_full_name participou do $bold_activity_name, realizado no Instituto Tecnológico de Aeronáutica, no período de $start_day a $end_day de $month_name de $year, em São José dos Campos - SP, Brasil.";
} elseif ($activity->type == 'Short-course') {
$activity_info = "Certificamos que $bold_full_name participou do minicurso $bold_activity_name do XXVII Simpósio de Aplicações Operacionais em Áreas de Defesa - XXVII SIGE, realizado no Instituto Tecnológico de Aeronáutica, no dia $start_day de $month_name de $year, com duração de $duration_formatted, em São José dos Campos - SP, Brasil.";
} else {
$activity_info = "Certificamos que $bold_full_name participou da atividade $bold_activity_name do XXVII Simpósio de Aplicações Operacionais em Áreas de Defesa - XXVII SIGE, realizado no Instituto Tecnológico de Aeronáutica, no dia $start_day de $month_name de $year, com duração de $duration_formatted, em São José dos Campos - SP, Brasil.";
}
// Add activity information to the PDF
$pdf->SetFont('Helvetica', '', $font_size); // Set font size
$pdf->SetXY(15, $y);
// Use writeHTMLCell to output the text with bold formatting, justified alignment, and text indent
// Wrap the activity_info in a <p> tag with text-indent CSS
$activity_info = '<p style="text-indent:20px; text-align:justify;">' . $activity_info . '</p>';
// Use writeHTMLCell to write the HTML content
$pdf->writeHTMLCell(267, 0, '', '', $activity_info, 0, 1, false, true, 'J', true);
// Calculate positions for QR code and hashed ID
$page_width = 297; // A4 Landscape width in mm
$page_height = 210; // A4 Landscape height in mm
$margin_right = 15; // Right margin
$margin_bottom = 15; // Bottom margin
$qr_size = 35; // Adjusted size
$qr_x = $page_width - $margin_right - $qr_size - 15; // Adjusted X position for QR code
$qr_y = $page_height - $margin_bottom - $qr_size - 10; // Y position for QR code, adjusted 10mm above bottom margin
// Add the QR code image to the PDF at the specified position
$pdf->Image($temp_image_path, $qr_x, $qr_y, $qr_size, $qr_size); // Adjusted position and size of the QR code
// Add the hashed user ID (MD5) just below the QR code image
$pdf->SetFont('Helvetica', '', 8); // Set font size for the hash
$hash_x = $qr_x - 15; // Adjusted X position for hashed ID
$hash_y = $qr_y + $qr_size - 6; // Y position just below QR code with adjustment
$pdf->SetXY($hash_x, $hash_y);
$pdf->Cell(0, 10, 'ID único: ' . $hashed_user_id, 0, 1, 'L'); // Insert the hashed ID
// Save the PDF to a temporary file
$pdf_temp_path = $temp_dir . 'temp_certificate_' . $certificate_number . '.pdf';
$pdf->Output($pdf_temp_path, 'F'); // Save to file
// Add the temp PDF path to the array
$pdf_files[] = $pdf_temp_path;
// Delete the temporary QR code image file
if (file_exists($temp_image_path)) {
unlink($temp_image_path); // Delete the temp image file
}
// Increment the certificate number
$certificate_number++;
}
// Create a ZIP file containing all the PDFs
$zip = new ZipArchive();
$zip_filename = $temp_dir . 'certificados_' . $certificate_year . '.zip';
if ($zip->open($zip_filename, ZipArchive::CREATE) !== TRUE) {
// Log error and redirect back with an error message
error_log('Error: Cannot create ZIP file at ' . $zip_filename);
wp_safe_redirect(add_query_arg('zip_error', '1', remove_query_arg(array('download_certificate', 'certificate_year'))));
exit;
}
// Add files to ZIP
foreach ($pdf_files as $pdf_file) {
if (file_exists($pdf_file)) {
$zip->addFile($pdf_file, basename($pdf_file));
} else {
error_log('Error: PDF file not found: ' . $pdf_file);
// Optionally handle this error
}
}
$zip->close();
// Before sending headers and outputting the ZIP file, clean the output buffer
if (ob_get_length()) {
ob_end_clean();
}
// Send headers and force ZIP download
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="certificados_' . $certificate_year . '.zip"');
header('Content-Length: ' . filesize($zip_filename));
header('Pragma: public');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
// Output the ZIP file
readfile($zip_filename);
// Delete temporary PDF files
foreach ($pdf_files as $pdf_file) {
if (file_exists($pdf_file)) {
unlink($pdf_file);
}
}
// Delete the ZIP file
if (file_exists($zip_filename)) {
unlink($zip_filename);
}
// Optionally, delete the temporary directory if it's empty
if (is_dir($temp_dir)) {
@rmdir($temp_dir);
}
// Stop further execution after sending the ZIP file
exit;
}
}
// Add action to handle the file download before the template is loaded
add_action('template_redirect', 'handle_certificate_download_pt');
// Create a shortcode to display the form
add_shortcode('download_certificate_pt', 'display_certificate_form_pt');
// Function to display error messages with modal styling
function display_certificate_errors_pt()
{
if (isset($_GET['no_certificates']) && $_GET['no_certificates'] == '1') {
echo '
<style>
.modal {
display: block;
position: fixed;
z-index: 999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4); /* Transparent background */
}
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 500px;
text-align: center;
border-radius: 10px; /* Optional for rounded corners */
}
.button-secondary {
background-color: #6c757d;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.button-secondary:hover {
background-color: #5a6268;
}
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>Certificados de Participação Não Encontrados</h2>
<p>Não há certificados de participação disponíveis para o ano selecionado.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Fechar</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
// Redirect to the same page without query parameters
window.location.href = window.location.pathname;
});
</script>';
} elseif (isset($_GET['template_not_found']) && $_GET['template_not_found'] == '1') {
echo '
<style>
/* Include your modal CSS here */
.modal {
display: block;
position: fixed;
z-index: 999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
}
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 500px;
text-align: center;
border-radius: 10px;
}
.button-secondary {
background-color: #6c757d;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.button-secondary:hover {
background-color: #5a6268;
}
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>Erro</h2>
<p>Modelo de certificado não encontrado. Por favor, entre em contato com o suporte.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Fechar</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
window.location.href = window.location.pathname;
});
</script>';
} elseif (isset($_GET['temp_dir_error']) && $_GET['temp_dir_error'] == '1') {
echo '
<style>
/* Include your modal CSS here */
.modal { /* Same as above */ }
.modal-content { /* Same as above */ }
.button-secondary { /* Same as above */ }
.button-secondary:hover { /* Same as above */ }
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>Erro</h2>
<p>Não foi possível criar o diretório temporário. Por favor, entre em contato com o suporte.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Fechar</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
window.location.href = window.location.pathname;
});
</script>';
} elseif (isset($_GET['qrcode_error']) && $_GET['qrcode_error'] == '1') {
echo '
<style>
/* Include your modal CSS here */
.modal { /* Same as above */ }
.modal-content { /* Same as above */ }
.button-secondary { /* Same as above */ }
.button-secondary:hover { /* Same as above */ }
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>Erro</h2>
<p>Não foi possível gerar o código QR. Por favor, entre em contato com o suporte.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Fechar</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
window.location.href = window.location.pathname;
});
</script>';
} elseif (isset($_GET['zip_error']) && $_GET['zip_error'] == '1') {
echo '
<style>
/* Include your modal CSS here */
.modal { /* Same as above */ }
.modal-content { /* Same as above */ }
.button-secondary { /* Same as above */ }
.button-secondary:hover { /* Same as above */ }
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>Erro</h2>
<p>Não foi possível criar o arquivo ZIP. Por favor, entre em contato com o suporte.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Fechar</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
window.location.href = window.location.pathname;
});
</script>';
}
}
add_action('wp_head', 'display_certificate_errors_pt');
// Shortcode function to display the form in English
function display_certificate_form_en()
{
// Only proceed if not in admin area or REST API
if (is_admin() || (defined('REST_REQUEST') && REST_REQUEST)) {
return ''; // Return empty string to prevent interference
}
// Disable cache for all users
nocache_headers();
// Append nocache query parameter to bust cache
if (!isset($_GET['nocache'])) {
// Append a unique timestamp-based parameter to the URL
$new_url = add_query_arg('nocache', time(), get_permalink());
wp_redirect($new_url);
exit();
}
// Check if the user is logged in
if (!is_user_logged_in()) {
$login_url = wp_login_url(get_permalink()); // Redirect to the current page after login
return '
<div style="
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #808080; /* Gray background */
color: #fff; /* White text color */
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
z-index: 1000;
text-align: center;
border-radius: 10px;
">
<p>You must be logged in to get your certificates.</p>
<a href="' . esc_url($login_url) . '" style="color: #fff; text-decoration: underline;">Click here to log in</a>
</div>';
}
// Prevent back/forward navigation cache
echo '<script>
if (performance.navigation.type === performance.navigation.TYPE_BACK_FORWARD) {
window.location.reload(true); // Force reload on back/forward navigation
}
</script>';
// Prepare the output buffer
$output = '';
// Check if the form has been submitted
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['certificate_year'])) {
$certificate_year = intval($_POST['certificate_year']);
// Build the redirect URL with the necessary GET parameters
$redirect_url = add_query_arg(array(
'download_certificate_en' => '1',
'certificate_year' => $certificate_year
), get_permalink());
// Redirect to the download URL
wp_redirect($redirect_url);
exit();
}
// Append the form HTML to the output buffer
$output .= '
<style>
.form-container {
background-color: #e0f7fa;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
padding: 20px;
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
}
.form-container select, .form-container button {
margin: 10px 0;
padding: 10px;
font-size: 16px;
border-radius: 5px;
border: 1px solid #ccc;
width: 100%;
max-width: 300px;
}
.form-container button {
background-color: #007BFF;
color: white;
border: none;
cursor: pointer;
transition: background-color 0.3s;
}
.form-container button:hover {
background-color: #0056b3;
}
</style>
<form method="post" class="form-container">
<label for="certificate_year">Select Year:</label>
<select name="certificate_year" id="certificate_year" required>
<option value="2024">2024</option>
<option value="2025">2025</option>
<!-- Add more years as needed -->
</select>
<button type="submit">Get Certificate</button>
</form>';
return $output;
}
// Function to handle the file download for English certificates
function handle_certificate_download_en()
{
// Check if the download_certificate_en parameter is set
if (isset($_GET['download_certificate_en']) && $_GET['download_certificate_en'] == '1') {
// Ensure no output is sent before headers
if (ob_get_length()) {
ob_end_clean();
}
// Disable error display to prevent corrupting the file download
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(0);
// Start output buffering
ob_start();
// Check if the user is logged in
if (!is_user_logged_in()) {
wp_safe_redirect(wp_login_url(get_permalink()));
exit;
}
global $wpdb;
// Get the current user ID
$current_user_id = get_current_user_id();
// Retrieve the user's full name from metadata (or use display_name as a fallback)
$full_name = get_user_meta($current_user_id, 'full_name', true);
if (empty($full_name)) {
// If 'full_name' meta doesn't exist, fall back to display_name
$user_info = get_userdata($current_user_id);
$full_name = $user_info->display_name;
}
// Format the full name using the provided format function
if (function_exists('format_full_name_certificate')) {
$full_name = format_full_name_certificate($full_name);
} else {
// If the function doesn't exist, just use the full name as is
$full_name = $full_name;
}
// Get the selected year from the query parameter
$certificate_year = intval($_GET['certificate_year']);
// Fetch Hybrid and In-person attendance
$query_hybrid = $wpdb->prepare("
SELECT a.name as activity_name, a.start_date, a.end_date, a.start_time, a.end_time, a.type
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}sige_enrollment_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.user_id = %d AND ac.attended = 'yes' AND YEAR(a.start_date) = %d AND a.modality IN ('Hybrid', 'In-person') AND a.attendance_control = 'yes'
", $current_user_id, $certificate_year);
$hybrid_results = $wpdb->get_results($query_hybrid);
// Fetch Online attendance
$query_online = $wpdb->prepare("
SELECT a.name as activity_name, a.start_date, a.end_date, a.start_time, a.end_time, a.type
FROM {$wpdb->prefix}sige_enrollments e
LEFT JOIN {$wpdb->prefix}sige_activities a ON e.activity_id = a.id
LEFT JOIN {$wpdb->prefix}sige_enrollment_online_attendance_control ac ON e.id = ac.enrollment_id
WHERE e.user_id = %d AND ac.attended = 'yes' AND YEAR(a.start_date) = %d AND a.modality = 'Online'
", $current_user_id, $certificate_year);
$online_results = $wpdb->get_results($query_online);
// Combine both results
$all_activities = array_merge($hybrid_results, $online_results);
$total_activities = count($all_activities);
// If no activities are found for the year, redirect back with an error message
if ($total_activities == 0) {
wp_safe_redirect(add_query_arg('no_certificates_en', '1', remove_query_arg(array('download_certificate_en', 'certificate_year'))));
exit;
}
// Secret phrase for generating a unique hash
$secret_phrase = 'CGLtShwG9qV5p3zmS3BR7G9J8iKCTe9Pd1BAyCCorBfpCCbB7F';
// Path to your PDF template
$template_path = plugin_dir_path(__FILE__) . 'templates/certificate_template_2024_en.pdf';
// Ensure that the template file exists
if (!file_exists($template_path)) {
// Log error and redirect back with an error message
error_log('Error: Template not found at ' . $template_path);
wp_safe_redirect(add_query_arg('template_not_found_en', '1', remove_query_arg(array('download_certificate_en', 'certificate_year'))));
exit;
}
// Get the WordPress uploads directory
$upload_dir = wp_upload_dir();
$temp_dir = trailingslashit($upload_dir['basedir']) . 'certificate_temp_files_en/';
// Ensure the temporary directory exists
if (!file_exists($temp_dir)) {
if (!mkdir($temp_dir, 0755, true)) {
// Log error and redirect back with an error message
error_log('Error: Failed to create temporary directory at ' . $temp_dir);
wp_safe_redirect(add_query_arg('temp_dir_error_en', '1', remove_query_arg(array('download_certificate_en', 'certificate_year'))));
exit;
}
}
// Initialize variables
$certificate_number = 1;
$pdf_files = array(); // To store paths to temp PDF files
// Fixed y-position and font size
$y = 90; // Updated y-position to 90
$font_size = 20; // Font size remains 20
// Define months in English
$months = array(
'01' => 'January',
'02' => 'February',
'03' => 'March',
'04' => 'April',
'05' => 'May',
'06' => 'June',
'07' => 'July',
'08' => 'August',
'09' => 'September',
'10' => 'October',
'11' => 'November',
'12' => 'December',
);
// Loop over each activity to generate individual PDFs
foreach ($all_activities as $activity) {
// Generate $hashed_user_id for this certificate
$hashed_user_id = md5($secret_phrase . $current_user_id . $certificate_year . $certificate_number);
// Generate QR Code with the hashed user ID
ob_start();
QRcode::png($hashed_user_id, null, QR_ECLEVEL_L, 10); // Generates QR Code
$imageString = ob_get_contents(); // Get the QR code image as a string
ob_end_clean();
// Decode the image string into binary format for saving
$imgdata = base64_decode(str_replace('data:image/png;base64,', '', base64_encode($imageString)));
// Save the image temporarily
$temp_image_path = $temp_dir . 'temp_qrcode_' . $certificate_number . '.png';
if (file_put_contents($temp_image_path, $imgdata) === false) {
// Log error and redirect back with an error message
error_log('Error: Could not save QR code image to ' . $temp_image_path);
wp_safe_redirect(add_query_arg('qrcode_error_en', '1', remove_query_arg(array('download_certificate_en', 'certificate_year'))));
exit;
}
// Initialize TCPDF with FPDI
$pdf = new TcpdfFpdi();
// Call before the addPage() method
$pdf->SetPrintHeader(false);
$pdf->SetPrintFooter(false);
$pdf->AddPage('L'); // Set orientation to Landscape
// Import the certificate template
$pdf->setSourceFile($template_path);
$template_id = $pdf->importPage(1);
$pdf->useTemplate($template_id, 0, 0, 297, 210); // Adjust size to A4 Landscape
// Set margins
$pdf->SetMargins(15, 15, 15);
// Prepare date components
$start_date = strtotime($activity->start_date);
$end_date = strtotime($activity->end_date);
$start_day = date('d', $start_date);
$end_day = date('d', $end_date);
$month_num = date('m', $start_date); // Assuming start and end dates are in the same month
$year = date('Y', $start_date);
$month_name = $months[$month_num];
// Get the activity name
$activity_name = $activity->activity_name;
// Make the full name bold
$bold_full_name = '<b>' . $full_name . '</b>';
// Make the activity name bold
$bold_activity_name = '<b>' . $activity_name . '</b>';
// Get start_time and end_time, formatted as 'H:i'
$start_time = date('H:i', strtotime($activity->start_time));
$end_time = date('H:i', strtotime($activity->end_time));
// Calculate duration in seconds
$start_timestamp = strtotime($activity->start_date . ' ' . $activity->start_time);
$end_timestamp = strtotime($activity->end_date . ' ' . $activity->end_time);
$duration_in_seconds = $end_timestamp - $start_timestamp;
// Handle cases where end time is earlier than start time (e.g., over midnight)
if ($duration_in_seconds < 0) {
$duration_in_seconds += 24 * 3600; // Add 24 hours
}
// Calculate hours and minutes
$hours = floor($duration_in_seconds / 3600);
$minutes = floor(($duration_in_seconds % 3600) / 60);
// Format duration as 'HHhMM'
$duration_formatted = sprintf('%02dh%02d', $hours, $minutes);
// Build the activity information based on type
if ($activity->type == 'Main Event') {
$activity_info = "This is to certify that $bold_full_name participated in the $bold_activity_name, held at the Aeronautics Institute of Technology, from $start_day to $end_day of $month_name, $year, in São José dos Campos - SP, Brazil.";
} elseif ($activity->type == 'Short-course') {
$activity_info = "This is to certify that $bold_full_name participated in the short-course $bold_activity_name of the XXVII Symposium of Operational Applications in Defense Areas - XXVII SIGE, held at the Aeronautics Institute of Technology, on $start_day of $month_name, $year, with a duration of $duration_formatted, in São José dos Campos - SP, Brazil.";
} else {
$activity_info = "This is to certify that $bold_full_name participated in the activity $bold_activity_name of the XXVII Symposium of Operational Applications in Defense Areas - XXVII SIGE, held at the Aeronautics Institute of Technology, on $start_day of $month_name, $year, with a duration of $duration_formatted, in São José dos Campos - SP, Brazil.";
}
// Add activity information to the PDF
$pdf->SetFont('Helvetica', '', $font_size); // Set font size
$pdf->SetXY(15, $y);
// Use writeHTMLCell to output the text with bold formatting, justified alignment, and text indent
// Wrap the activity_info in a <p> tag with text-indent CSS
$activity_info = '<p style="text-indent:20px; text-align:justify;">' . $activity_info . '</p>';
// Use writeHTMLCell to write the HTML content
$pdf->writeHTMLCell(267, 0, '', '', $activity_info, 0, 1, false, true, 'J', true);
// Calculate positions for QR code and hashed ID
$page_width = 297; // A4 Landscape width in mm
$page_height = 210; // A4 Landscape height in mm
$margin_right = 15; // Right margin
$margin_bottom = 15; // Bottom margin
$qr_size = 35; // Adjusted size
$qr_x = $page_width - $margin_right - $qr_size - 15; // Adjusted X position for QR code
$qr_y = $page_height - $margin_bottom - $qr_size - 10; // Y position for QR code, adjusted 10mm above bottom margin
// Add the QR code image to the PDF at the specified position
$pdf->Image($temp_image_path, $qr_x, $qr_y, $qr_size, $qr_size); // Adjusted position and size of the QR code
// Add the hashed user ID (MD5) just below the QR code image
$pdf->SetFont('Helvetica', '', 8); // Set font size for the hash
$hash_x = $qr_x - 15; // Adjusted X position for hashed ID
$hash_y = $qr_y + $qr_size - 6; // Y position just below QR code with adjustment
$pdf->SetXY($hash_x, $hash_y);
$pdf->Cell(0, 10, 'Unique ID: ' . $hashed_user_id, 0, 1, 'L'); // Insert the hashed ID
// Save the PDF to a temporary file
$pdf_temp_path = $temp_dir . 'temp_certificate_' . $certificate_number . '.pdf';
$pdf->Output($pdf_temp_path, 'F'); // Save to file
// Add the temp PDF path to the array
$pdf_files[] = $pdf_temp_path;
// Delete the temporary QR code image file
if (file_exists($temp_image_path)) {
unlink($temp_image_path); // Delete the temp image file
}
// Increment the certificate number
$certificate_number++;
}
// Create a ZIP file containing all the PDFs
$zip = new ZipArchive();
$zip_filename = $temp_dir . 'certificates_' . $certificate_year . '.zip';
if ($zip->open($zip_filename, ZipArchive::CREATE) !== TRUE) {
// Log error and redirect back with an error message
error_log('Error: Cannot create ZIP file at ' . $zip_filename);
wp_safe_redirect(add_query_arg('zip_error_en', '1', remove_query_arg(array('download_certificate_en', 'certificate_year'))));
exit;
}
// Add files to ZIP
foreach ($pdf_files as $pdf_file) {
if (file_exists($pdf_file)) {
$zip->addFile($pdf_file, basename($pdf_file));
} else {
error_log('Error: PDF file not found: ' . $pdf_file);
// Optionally handle this error
}
}
$zip->close();
// Before sending headers and outputting the ZIP file, clean the output buffer
if (ob_get_length()) {
ob_end_clean();
}
// Send headers and force ZIP download
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="certificates_' . $certificate_year . '.zip"');
header('Content-Length: ' . filesize($zip_filename));
header('Pragma: public');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
// Output the ZIP file
readfile($zip_filename);
// Delete temporary PDF files
foreach ($pdf_files as $pdf_file) {
if (file_exists($pdf_file)) {
unlink($pdf_file);
}
}
// Delete the ZIP file
if (file_exists($zip_filename)) {
unlink($zip_filename);
}
// Optionally, delete the temporary directory if it's empty
if (is_dir($temp_dir)) {
@rmdir($temp_dir);
}
// Stop further execution after sending the ZIP file
exit;
}
}
// Add action to handle the file download before the template is loaded
add_action('template_redirect', 'handle_certificate_download_en');
// Function to display error messages with modal styling for English version
function display_certificate_errors_en()
{
if (isset($_GET['no_certificates_en']) && $_GET['no_certificates_en'] == '1') {
echo '
<style>
.modal {
display: block;
position: fixed;
z-index: 999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4); /* Transparent background */
}
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 500px;
text-align: center;
border-radius: 10px; /* Optional for rounded corners */
}
.button-secondary {
background-color: #6c757d;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.button-secondary:hover {
background-color: #5a6268;
}
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>No Attendance Certificates Found</h2>
<p>There are no attendance certificates available for the selected year.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Close</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
// Redirect to the same page without query parameters
window.location.href = window.location.pathname;
});
</script>';
} elseif (isset($_GET['template_not_found_en']) && $_GET['template_not_found_en'] == '1') {
echo '
<style>
/* Include your modal CSS here */
.modal { /* Same as above */ }
.modal-content { /* Same as above */ }
.button-secondary { /* Same as above */ }
.button-secondary:hover { /* Same as above */ }
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>Error</h2>
<p>Certificate template not found. Please contact support.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Close</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
window.location.href = window.location.pathname;
});
</script>';
} elseif (isset($_GET['temp_dir_error_en']) && $_GET['temp_dir_error_en'] == '1') {
echo '
<style>
/* Include your modal CSS here */
.modal { /* Same as above */ }
.modal-content { /* Same as above */ }
.button-secondary { /* Same as above */ }
.button-secondary:hover { /* Same as above */ }
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>Error</h2>
<p>Failed to create temporary directory. Please contact support.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Close</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
window.location.href = window.location.pathname;
});
</script>';
} elseif (isset($_GET['qrcode_error_en']) && $_GET['qrcode_error_en'] == '1') {
echo '
<style>
/* Include your modal CSS here */
.modal { /* Same as above */ }
.modal-content { /* Same as above */ }
.button-secondary { /* Same as above */ }
.button-secondary:hover { /* Same as above */ }
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>Error</h2>
<p>Failed to generate QR code. Please contact support.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Close</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
window.location.href = window.location.pathname;
});
</script>';
} elseif (isset($_GET['zip_error_en']) && $_GET['zip_error_en'] == '1') {
echo '
<style>
/* Include your modal CSS here */
.modal { /* Same as above */ }
.modal-content { /* Same as above */ }
.button-secondary { /* Same as above */ }
.button-secondary:hover { /* Same as above */ }
</style>
<div id="errorModal" class="modal">
<div class="modal-content">
<h2>Error</h2>
<p>Failed to create ZIP file. Please contact support.</p>
<button class="button button-secondary close-modal" id="closeModalBtn">Close</button>
</div>
</div>
<script>
document.getElementById("closeModalBtn").addEventListener("click", function() {
document.getElementById("errorModal").style.display = "none";
window.location.href = window.location.pathname;
});
</script>';
}
}
add_action('wp_head', 'display_certificate_errors_en');
// Register the shortcode
add_shortcode('download_certificate_en', 'display_certificate_form_en');
function format_full_name_certificate($full_name)
{
// Convert the full name to uppercase using multibyte function
$full_name = mb_strtoupper($full_name, 'UTF-8');
// Prepositions to keep intact
$prepositions = ['DE', 'DA', 'DO', 'DAS', 'DOS', 'E'];
// Check if the total length of the name is less than or equal to 35
if (strlen($full_name) <= 35) {
return $full_name;
}
// Process name if length exceeds 35 characters
$name_parts = explode(' ', $full_name); // Split name by spaces
$formatted_name = '';
$char_count = 0;
// Build the formatted name up to the last full name part under 35 characters
foreach ($name_parts as $index => $part) {
// Always include prepositions and conjunctions as full words
if (in_array($part, $prepositions)) {
$formatted_name .= $part . ' ';
$char_count += strlen($part) + 1;
} elseif ($char_count + strlen($part) <= 35) {
// Add full parts of the name if still within limit
$formatted_name .= $part . ' ';
$char_count += strlen($part) + 1;
} else {
break; // Stop if adding the next part would exceed 35 characters
}
}
// For the remaining parts, abbreviate them by using initials
for ($i = $index; $i < count($name_parts); $i++) {
if (!in_array($name_parts[$i], $prepositions)) {
$formatted_name .= $name_parts[$i][0] . '.';
$char_count += 2; // 1 for the initial and 1 for the period
}
}
// Ensure the final name is trimmed of any extra spaces and return it
return trim($formatted_name);
}
function verifyUserBasedOnQRCodefromCertificate($hashed_user_id, $certificate_year)
{
global $wpdb;
// Define the secret phrase used for hashing
$secret_phrase = 'CGLtShwG9qV5p3zmS3BR7G9J8iKCTe9Pd1BAyCCorBfpCCbB7F';
// Loop through users to find the matching hash
$users = get_users();
foreach ($users as $user) {
for ($certificate_number = 1; $certificate_number <= 10; $certificate_number++) {
$computed_hash = md5($secret_phrase . $user->ID . $certificate_year . $certificate_number);
if ($computed_hash === $hashed_user_id) {
return $user->ID;
}
}
}
// Return false if no match found
return false;
}
function sige_enqueue_export_csv_script($unique_id = '')
{
if (!is_admin() && !empty($unique_id)) {
wp_enqueue_script(
'sige-export-csv',
plugin_dir_url(__FILE__) . 'js/sige-export-csv.js',
array('jquery'),
null,
true
);
wp_localize_script('sige-export-csv', 'SIGEExportVars', array(
'unique_id' => $unique_id
));
}
}
add_action('wp_enqueue_scripts', 'sige_enqueue_export_csv_script');
// Secure AJAX handler for saving confidentiality response
add_action('wp_ajax_save_confidentiality_response', function () {
// Only allow logged-in users
if (!is_user_logged_in()) {
wp_send_json_error(['message' => 'Unauthorized'], 403);
exit;
}
$current_user_id = get_current_user_id();
// Validate and sanitize input
$user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
$year = isset($_POST['year']) ? intval($_POST['year']) : 0;
$response = isset($_POST['response']) ? sanitize_text_field($_POST['response']) : '';
// Only allow the current user to update their own record
if ($user_id !== $current_user_id || $year < 2000 || $year > (int)date('Y') + 1) {
wp_send_json_error(['message' => 'Invalid request'], 400);
exit;
}
global $wpdb;
$table = $wpdb->prefix . 'sige_confidentiality_user_option';
// Insert or update the user's response
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM $table WHERE user_id = %d AND year = %d",
$current_user_id,
$year
));
if ($existing) {
$wpdb->update(
$table,
['response' => $response],
['user_id' => $current_user_id, 'year' => $year]
);
} else {
$wpdb->insert(
$table,
['user_id' => $current_user_id, 'year' => $year, 'response' => $response]
);
}
wp_send_json_success(['message' => 'Response saved']);
exit;
});
function attendance_control($attributes)
{
nocache_headers();
if (!isset($_GET['nocache'])) {
$new_url = add_query_arg('nocache', time(), get_permalink());
wp_redirect($new_url);
exit();
}
// Prevent back/forward navigation cache
$output = '<script>
if (performance.navigation.type === performance.navigation.TYPE_BACK_FORWARD) {
window.location.reload();
}
</script>';
if (!is_user_logged_in()) {
$login_url = wp_login_url(get_permalink());
return '
<div style="
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #808080; /* Gray background */
color: #fff; /* White text color */
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
z-index: 1000;
text-align: center;
border-radius: 10px;
">
<p>Você precisa estar logado para acessar esta página.</p>
<a href="' . esc_url($login_url) . '" style="color: #fff; text-decoration: underline;">Clique aqui para efeutar o login</a>
</div>';
}
$user = wp_get_current_user();
$user_id = $user->ID;
$args = shortcode_atts(array('activity_id' => 'none'), $attributes);
$activity_id = intval($args['activity_id']);
global $wpdb;
$result = $wpdb->get_row($wpdb->prepare("
SELECT id
FROM {$wpdb->prefix}sige_enrollments
WHERE user_id = '%d'
AND activity_id = '%d'
", $user_id, $activity_id));
if ($result) {
$enrollment_id = $result->id;
$already_confirmed = $wpdb->get_row($wpdb->prepare("
SELECT id
FROM {$wpdb->prefix}sige_enrollment_attendance_control
WHERE enrollment_id = '%d'
", $enrollment_id));
if (!$already_confirmed) {
$results = $wpdb->insert("{$wpdb->prefix}sige_enrollment_attendance_control", ['enrollment_id' => $enrollment_id, 'attended' => 'yes']);
if (!$results) {
return '<div style="
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fbff00d3; /* Green background */
color: #000000ff; /* Black text color */
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
z-index: 1000;
text-align: center;
border-radius: 10px;
">
<p>Sua presença não pode ser confirmada no momento, por favor tente novamente.</p>
</div>';
}
}
return '<div style="
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #04681dd3; /* Green background */
color: #000000ff; /* Black text color */
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
z-index: 1000;
text-align: center;
border-radius: 10px;
">
<p>Presença confirmada.</p>
</div>';
} else {
return '<div style="
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fbff00d3; /* Yellow background */
color: #000000ff; /* Black text color */
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
z-index: 1000;
text-align: center;
border-radius: 10px;
">
<p>Você não está inscrito neste evento.</p>
</div>';
}
}
add_shortcode('attendanceControl', 'attendance_control');
/**
* Shortcode handler for QR code POST access.
* Usage: [qr_post_access]
* Only allows access if POST request with correct token.
*/
function qr_post_access_handler()
{
// Only allow POST requests
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return '<div style="text-align:center;padding:40px;"><strong>Access denied. Please scan the QR code and submit the form to access this page.</strong></div>';
}
// Validate QR token (replace 'EXPECTED_TOKEN' with your actual token)
if (!isset($_POST['qr_token']) || $_POST['qr_token'] !== 'EXPECTED_TOKEN') {
return '<div style="text-align:center;padding:40px;"><strong>Invalid QR code data.</strong></div>';
}
// Authorized content
return '<div style="text-align:center;padding:40px;"><strong>Welcome! You accessed this page via POST after scanning the QR code.</strong></div>';
}
add_shortcode('qr_post_access', 'qr_post_access_handler');
function handle_feedback_submission()
{
ob_start();
if (isset($_POST['submit_feedback_form'])) {
// Verify nonce
if (
!isset($_POST['feedback_form_nonce']) ||
!wp_verify_nonce($_POST['feedback_form_nonce'], 'feedback_form_action')
) {
wp_die('Security check failed');
}
// Sanitize form data
$feedback_data = array(
'global_score' => sanitize_text_field($_POST['global_score'] ?? ''),
'schedule' => sanitize_text_field($_POST['schedule'] ?? ''),
'technical_sessions' => sanitize_text_field($_POST['technical_sessions']),
'lectures' => sanitize_textarea_field($_POST['lectures'] ?? ''),
'coffee_break' => sanitize_textarea_field($_POST['coffee_break'] ?? ''),
'opening' => sanitize_textarea_field($_POST['opening'] ?? ''),
'short_courses' => sanitize_textarea_field($_POST['short_courses'] ?? ''),
'suggestions' => sanitize_textarea_field($_POST['suggestions'] ?? ''),
'date' => date('Y-m-d')
);
// Insert into database
global $wpdb;
$table_name = $wpdb->prefix . 'sige_feedback';
$result = $wpdb->insert(
$table_name,
$feedback_data,
array('%s', '%s', '%s', '%s', '%s', '%s', '%s')
);
if ($result === false) {
// Log error and display message
error_log('Failed to save feedback: ' . $wpdb->last_error);
wp_die('Error saving feedback');
}
// Show success message
add_action('admin_notices', function () {
echo '<div class="notice notice-success is-dismissible">
<p>Feedback submitted successfully!</p>
</div>';
});
// Redirect to prevent form resubmission
wp_redirect(add_query_arg('feedback', 'success', wp_get_referer()));
exit;
}
// Display the feedback form template
include_once plugin_dir_path(__FILE__) . 'templates/feedback-form.php';
}
add_shortcode('feedback_form', 'handle_feedback_submission');
function display_feedback_statistics()
{
global $wpdb;
ob_start();
echo '<style>
.feedback-statistics {
max-width: 800px;
margin: 20px auto;
padding: 20px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.feedback-statistics h3 {
color: #444;
margin: 20px 0 10px;
padding-bottom: 10px;
border-bottom: 2px solid #0073aa;
}
.feedback-statistics table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
background-color: #fff;
}
.feedback-statistics th {
background-color: #f8f8f8;
padding: 15px 10px;
text-align: left;
border: 1px solid #ddd;
}
.feedback-statistics td {
padding: 15px 10px;
border: 1px solid #ddd;
}
.feedback-statistics tr:nth-child(even) {
background-color: #f9f9f9;
}
.feedback-statistics tr:hover {
background-color: #f5f5f5;
}
/* Make tables responsive */
@media screen and (max-width: 768px) {
.feedback-statistics table {
display: block;
overflow-x: auto;
white-space: nowrap;
}
}
</style>';
$global_stats = $wpdb->get_results(
"
SELECT
COUNT(CASE WHEN global_score IS NOT NULL THEN 1 END) as total_responses,
COUNT(CASE WHEN global_score = 'Muito Bom' THEN 1 END) as vgood,
COUNT(CASE WHEN global_score = 'Bom' THEN 1 END) as good,
COUNT(CASE WHEN global_score = 'Neutro' THEN 1 END) as regular,
COUNT(CASE WHEN global_score = 'Ruim' THEN 1 END) as poor,
COUNT(CASE WHEN global_score = 'Muito Ruim' THEN 1 END) as vpoor
FROM {$wpdb->prefix}sige_feedback",
ARRAY_A
);
$schedule_stats = $wpdb->get_results(
"
SELECT
COUNT(CASE WHEN schedule IS NOT NULL THEN 1 END) as total_responses,
COUNT(CASE WHEN schedule = 'Muito Bom' THEN 1 END) as vgood,
COUNT(CASE WHEN schedule = 'Bom' THEN 1 END) as good,
COUNT(CASE WHEN schedule = 'Neutro' THEN 1 END) as regular,
COUNT(CASE WHEN schedule = 'Ruim' THEN 1 END) as poor,
COUNT(CASE WHEN schedule = 'Ruim' THEN 1 END) as vpoor
FROM {$wpdb->prefix}sige_feedback",
ARRAY_A
);
$technical_stats = $wpdb->get_results(
"
SELECT
COUNT(CASE WHEN technical_sessions IS NOT NULL THEN 1 END) as total_responses,
COUNT(CASE WHEN technical_sessions = 'Muito Bom' THEN 1 END) as vgood,
COUNT(CASE WHEN technical_sessions = 'Bom' THEN 1 END) as good,
COUNT(CASE WHEN technical_sessions = 'Regular' THEN 1 END) as regular,
COUNT(CASE WHEN technical_sessions = 'Ruim' THEN 1 END) as poor,
COUNT(CASE WHEN technical_sessions = 'Muito Ruim' THEN 1 END) as vpoor
FROM {$wpdb->prefix}sige_feedback",
ARRAY_A
);
$lecture_stats = $wpdb->get_results(
"
SELECT
COUNT(CASE WHEN lectures IS NOT NULL THEN 1 END) as total_responses,
COUNT(CASE WHEN lectures = 'Muito Bom' THEN 1 END) as vgood,
COUNT(CASE WHEN lectures = 'Bom' THEN 1 END) as good,
COUNT(CASE WHEN lectures = 'Regular' THEN 1 END) as regular,
COUNT(CASE WHEN lectures = 'Ruim' THEN 1 END) as poor,
COUNT(CASE WHEN lectures = 'Muito Ruim' THEN 1 END) as vpoor
FROM {$wpdb->prefix}sige_feedback",
ARRAY_A
);
$coffee_stats = $wpdb->get_results(
"
SELECT
COUNT(CASE WHEN coffee_break IS NOT NULL THEN 1 END) as total_responses,
COUNT(CASE WHEN coffee_break = 'Muito Bom' THEN 1 END) as vgood,
COUNT(CASE WHEN coffee_break = 'Bom' THEN 1 END) as good,
COUNT(CASE WHEN coffee_break = 'Regular' THEN 1 END) as regular,
COUNT(CASE WHEN coffee_break = 'Ruim' THEN 1 END) as poor,
COUNT(CASE WHEN coffee_break = 'Muito Ruim' THEN 1 END) as vpoor
FROM {$wpdb->prefix}sige_feedback",
ARRAY_A
);
$opening_stats = $wpdb->get_results(
"
SELECT
COUNT(CASE WHEN opening IS NOT NULL THEN 1 END) as total_responses,
COUNT(CASE WHEN opening = 'Muito Bom' THEN 1 END) as vgood,
COUNT(CASE WHEN opening = 'Bom' THEN 1 END) as good,
COUNT(CASE WHEN opening = 'Regular' THEN 1 END) as regular,
COUNT(CASE WHEN opening = 'Ruim' THEN 1 END) as poor,
COUNT(CASE WHEN opening = 'Muito Ruim' THEN 1 END) as vpoor
FROM {$wpdb->prefix}sige_feedback",
ARRAY_A
);
$shortc_stats = $wpdb->get_results(
"
SELECT
COUNT(CASE WHEN short_courses IS NOT NULL THEN 1 END) as total_responses,
COUNT(CASE WHEN short_courses = 'Muito Bom' THEN 1 END) as vgood,
COUNT(CASE WHEN short_courses = 'Bom' THEN 1 END) as good,
COUNT(CASE WHEN short_courses = 'Regular' THEN 1 END) as regular,
COUNT(CASE WHEN short_courses = 'Ruim' THEN 1 END) as poor,
COUNT(CASE WHEN short_courses = 'Muito Ruim' THEN 1 END) as vpoor
FROM {$wpdb->prefix}sige_feedback",
ARRAY_A
);
// Display results in HTML format
echo '<div class="feedback-statistics">';
// Global Score Section
echo '<h3>Avaliação Geral do SIGE</h3>';
echo '<table class="wp-list-table widefat fixed striped">
<tr>
<th>Total de Respostas</th>
<th>Muito Bom</th>
<th>Bom</th>
<th>Neutro</th>
<th>Ruim</th>
<th>Muito Ruim</th>
</tr>
<tr>
<td>' . $global_stats[0]['total_responses'] . '</td>
<td>' . $global_stats[0]['vgood'] . '</td>
<td>' . $global_stats[0]['good'] . '</td>
<td>' . $global_stats[0]['regular'] . '</td>
<td>' . $global_stats[0]['poor'] . '</td>
<td>' . $global_stats[0]['vpoor'] . '</td>
</tr>
</table>';
// Schedule Section
echo '<h3>Avaliação da agenda do evento</h3>';
echo '<table class="wp-list-table widefat fixed striped">
<tr>
<th>Total de Respostas</th>
<th>Muito Bom</th>
<th>Bom</th>
<th>Neutro</th>
<th>Ruim</th>
<th>Muito Ruim</th>
</tr>
<tr>
<td>' . $schedule_stats[0]['total_responses'] . '</td>
<td>' . $schedule_stats[0]['vgood'] . '</td>
<td>' . $schedule_stats[0]['good'] . '</td>
<td>' . $schedule_stats[0]['regular'] . '</td>
<td>' . $schedule_stats[0]['poor'] . '</td>
<td>' . $schedule_stats[0]['vpoor'] . '</td>
</tr>
</table>';
// Technical Sessions Section
echo '<h3>Avaliação da duração das seções técnicas</h3>';
echo '<table class="wp-list-table widefat fixed striped">
<tr>
<th>Total de Respostas</th>
<th>Muito Bom</th>
<th>Bom</th>
<th>Neutro</th>
<th>Ruim</th>
<th>Muito Ruim</th>
</tr>
<tr>
<td>' . $technical_stats[0]['total_responses'] . '</td>
<td>' . $technical_stats[0]['vgood'] . '</td>
<td>' . $technical_stats[0]['good'] . '</td>
<td>' . $technical_stats[0]['regular'] . '</td>
<td>' . $technical_stats[0]['poor'] . '</td>
<td>' . $technical_stats[0]['vpoor'] . '</td>
</tr>
</table>';
echo '<h3>Avaliação dos temas das palestras</h3>';
echo '<table class="wp-list-table widefat fixed striped">
<tr>
<th>Total de Respostas</th>
<th>Muito Bom</th>
<th>Bom</th>
<th>Neutro</th>
<th>Ruim</th>
<th>Muito Ruim</th>
</tr>
<tr>
<td>' . $lecture_stats[0]['total_responses'] . '</td>
<td>' . $lecture_stats[0]['vgood'] . '</td>
<td>' . $lecture_stats[0]['good'] . '</td>
<td>' . $lecture_stats[0]['regular'] . '</td>
<td>' . $lecture_stats[0]['poor'] . '</td>
<td>' . $lecture_stats[0]['vpoor'] . '</td>
</tr>
</table>';
echo '<h3>Avaliação dos coffee breaks</h3>';
echo '<table class="wp-list-table widefat fixed striped">
<tr>
<th>Total de Respostas</th>
<th>Muito Bom</th>
<th>Bom</th>
<th>Neutro</th>
<th>Ruim</th>
<th>Muito Ruim</th>
</tr>
<tr>
<td>' . $coffee_stats[0]['total_responses'] . '</td>
<td>' . $coffee_stats[0]['vgood'] . '</td>
<td>' . $coffee_stats[0]['good'] . '</td>
<td>' . $coffee_stats[0]['regular'] . '</td>
<td>' . $coffee_stats[0]['poor'] . '</td>
<td>' . $coffee_stats[0]['vpoor'] . '</td>
</tr>
</table>';
echo '<h3>Avaliação da abertura do evento</h3>';
echo '<table class="wp-list-table widefat fixed striped">
<tr>
<th>Total de Respostas</th>
<th>Muito Bom</th>
<th>Bom</th>
<th>Neutro</th>
<th>Ruim</th>
<th>Muito Ruim</th>
</tr>
<tr>
<td>' . $opening_stats[0]['total_responses'] . '</td>
<td>' . $opening_stats[0]['vgood'] . '</td>
<td>' . $opening_stats[0]['good'] . '</td>
<td>' . $opening_stats[0]['regular'] . '</td>
<td>' . $opening_stats[0]['poor'] . '</td>
<td>' . $opening_stats[0]['vpoor'] . '</td>
</tr>
</table>';
echo '<h3>Avaliação dos minicursos</h3>';
echo '<table class="wp-list-table widefat fixed striped">
<tr>
<th>Total de Respostas</th>
<th>Muito Bom</th>
<th>Bom</th>
<th>Neutro</th>
<th>Ruim</th>
<th>Muito Ruim</th>
</tr>
<tr>
<td>' . $shortc_stats[0]['total_responses'] . '</td>
<td>' . $shortc_stats[0]['vgood'] . '</td>
<td>' . $shortc_stats[0]['good'] . '</td>
<td>' . $shortc_stats[0]['regular'] . '</td>
<td>' . $shortc_stats[0]['poor'] . '</td>
<td>' . $shortc_stats[0]['vpoor'] . '</td>
</tr>
</table>';
echo '<h3>Avaliações escritas dos participantes</h3>';
echo '<table class="wp-list-table widefat fixed striped">
<tr>
<td>' . $shortc_stats[0]['total_responses'] . '</td>
<td>' . $shortc_stats[0]['vgood'] . '</td>
<td>' . $shortc_stats[0]['good'] . '</td>
<td>' . $shortc_stats[0]['regular'] . '</td>
<td>' . $shortc_stats[0]['poor'] . '</td>
<td>' . $shortc_stats[0]['vpoor'] . '</td>
</tr>
</table>';
$suggestions = $wpdb->get_results(
"SELECT suggestions, date
FROM {$wpdb->prefix}sige_feedback
WHERE suggestions IS NOT NULL
AND suggestions != ''
ORDER BY date DESC",
ARRAY_A
);
// Display suggestions section
echo '<h3>Sugestões dos Participantes</h3>';
if (!empty($suggestions)) {
echo '<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>Data</th>
<th>Sugestão</th>
</tr>
</thead>
<tbody>';
foreach ($suggestions as $suggestion) {
$formatted_date = date('d/m/Y', strtotime($suggestion['date']));
echo '<tr>
<td width="100">' . esc_html($formatted_date) . '</td>
<td>' . nl2br(esc_html($suggestion['suggestions'])) . '</td>
</tr>';
}
echo '</tbody></table>';
} else {
echo '<p>Nenhuma sugestão registrada até o momento.</p>';
}
echo '</div>';
return ob_get_clean();
}
add_shortcode('feedback_statistics', 'display_feedback_statistics');