9060 lines
409 KiB
Plaintext
9060 lines
409 KiB
Plaintext
<?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 master’s 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> </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');
|