<?php
// Start session
session_start();
// Include database configuration
require_once '../config/database.php';
// Check if user is logged in and has admin role
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'admin') {
header('Location: login.php');
exit;
}
// Check table existence
$tables_status = [];
// Check exam_schedules table
$check_exam_schedules = $conn->query("SHOW TABLES LIKE 'exam_schedules'");
$tables_status['exam_schedules'] = $check_exam_schedules->num_rows > 0;
// Check question_banks table
$check_question_banks = $conn->query("SHOW TABLES LIKE 'question_banks'");
$tables_status['question_banks'] = $check_question_banks->num_rows > 0;
// Check questions table
$check_questions = $conn->query("SHOW TABLES LIKE 'questions'");
$tables_status['questions'] = $check_questions->num_rows > 0;
// Check exam_question_maps table
$check_exam_question_maps = $conn->query("SHOW TABLES LIKE 'exam_question_maps'");
$tables_status['exam_question_maps'] = $check_exam_question_maps->num_rows > 0;
// Check if question_bank_id field exists in questions table
$question_bank_field_exists = false;
if ($tables_status['questions']) {
$check_field = $conn->query("SHOW COLUMNS FROM questions LIKE 'question_bank_id'");
$question_bank_field_exists = $check_field->num_rows > 0;
}
// Get statistics
$statistics = [];
if ($tables_status['exam_schedules']) {
$result = $conn->query("SELECT COUNT(*) AS count FROM exam_schedules");
$statistics['exams'] = $result->fetch_assoc()['count'];
}
if ($tables_status['question_banks']) {
$result = $conn->query("SELECT COUNT(*) AS count FROM question_banks");
$statistics['question_banks'] = $result->fetch_assoc()['count'];
// Get count of banks by course
$result = $conn->query("SELECT course_id, COUNT(*) AS count FROM question_banks GROUP BY course_id");
$statistics['banks_by_course'] = [];
while ($row = $result->fetch_assoc()) {
$course_id = $row['course_id'] ?: 'General';
$statistics['banks_by_course'][$course_id] = $row['count'];
}
}
if ($tables_status['questions']) {
$result = $conn->query("SELECT COUNT(*) AS count FROM questions");
$statistics['questions'] = $result->fetch_assoc()['count'];
if ($question_bank_field_exists) {
// Get count of questions by bank
$result = $conn->query("SELECT question_bank_id, COUNT(*) AS count FROM questions WHERE question_bank_id IS NOT NULL GROUP BY question_bank_id");
$statistics['questions_by_bank'] = [];
while ($row = $result->fetch_assoc()) {
$statistics['questions_by_bank'][$row['question_bank_id']] = $row['count'];
}
// Check for questions without bank
$result = $conn->query("SELECT COUNT(*) AS count FROM questions WHERE question_bank_id IS NULL");
$statistics['questions_without_bank'] = $result->fetch_assoc()['count'];
}
}
if ($tables_status['exam_question_maps']) {
$result = $conn->query("SELECT COUNT(*) AS count FROM exam_question_maps");
$statistics['mapped_questions'] = $result->fetch_assoc()['count'];
// Get count of mappings by exam
$result = $conn->query("SELECT exam_id, COUNT(*) AS count FROM exam_question_maps GROUP BY exam_id");
$statistics['mappings_by_exam'] = [];
while ($row = $result->fetch_assoc()) {
$statistics['mappings_by_exam'][$row['exam_id']] = $row['count'];
}
}
// Get courses
$courses = [];
$course_query = $conn->query("SELECT id, title FROM courses ORDER BY title");
if ($course_query) {
while ($row = $course_query->fetch_assoc()) {
$courses[$row['id']] = $row['title'];
}
}
// Handle diagnostic actions
$message = '';
if (isset($_POST['action'])) {
if ($_POST['action'] === 'create_exam_question_maps') {
$create_query = "CREATE TABLE IF NOT EXISTS exam_question_maps (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
exam_id INT(11) NOT NULL,
question_id INT(11) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (exam_id) REFERENCES exam_schedules(id) ON DELETE CASCADE,
FOREIGN KEY (question_id) REFERENCES questions(id) ON DELETE CASCADE,
UNIQUE KEY unique_exam_question (exam_id, question_id)
)";
if ($conn->query($create_query)) {
$message = '<div class="alert alert-success">The exam_question_maps table was created successfully.</div>';
$tables_status['exam_question_maps'] = true;
} else {
$message = '<div class="alert alert-danger">Failed to create the exam_question_maps table: ' . $conn->error . '</div>';
}
} elseif ($_POST['action'] === 'add_question_bank_field') {
$alter_query = "ALTER TABLE questions ADD COLUMN question_bank_id INT(11) NULL,
ADD CONSTRAINT fk_question_bank FOREIGN KEY (question_bank_id) REFERENCES question_banks(id) ON DELETE SET NULL";
if ($conn->query($alter_query)) {
$message = '<div class="alert alert-success">The question_bank_id field was added to the questions table successfully.</div>';
$question_bank_field_exists = true;
} else {
$message = '<div class="alert alert-danger">Failed to add the question_bank_id field: ' . $conn->error . '</div>';
}
} elseif ($_POST['action'] === 'fix_orphaned_question_mappings') {
// Find and remove mappings with non-existent questions or exams
$delete_query = "DELETE eqm FROM exam_question_maps eqm
LEFT JOIN questions q ON eqm.question_id = q.id
LEFT JOIN exam_schedules es ON eqm.exam_id = es.id
WHERE q.id IS NULL OR es.id IS NULL";
if ($conn->query($delete_query)) {
$rows_affected = $conn->affected_rows;
$message = '<div class="alert alert-success">Fixed orphaned mappings: ' . $rows_affected . ' orphaned records removed.</div>';
} else {
$message = '<div class="alert alert-danger">Failed to fix orphaned mappings: ' . $conn->error . '</div>';
}
}
}
// Include header
include_once 'includes/header.php';
?>
<div class="container-fluid">
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Exam System Diagnostics</h1>
<div>
<a href="database/setup_exam_tables.php" class="btn btn-primary btn-sm shadow-sm me-2">
<i class="fas fa-database fa-sm text-white-50"></i> Setup Tables
</a>
<a href="exam_schedules.php" class="btn btn-secondary btn-sm shadow-sm">
<i class="fas fa-arrow-left fa-sm text-white-50"></i> Back to Exams
</a>
</div>
</div>
<?php echo $message; ?>
<div class="row">
<!-- System Status -->
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">System Status</h6>
<span class="badge bg-primary"><?php echo (array_sum($tables_status) == count($tables_status) && $question_bank_field_exists) ? 'Healthy' : 'Issues Detected'; ?></span>
</div>
<div class="card-body">
<table class="table table-bordered">
<thead>
<tr>
<th>Component</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>exam_schedules Table</td>
<td>
<?php if ($tables_status['exam_schedules']): ?>
<span class="badge bg-success">Exists</span>
<?php else: ?>
<span class="badge bg-danger">Missing</span>
<?php endif; ?>
</td>
<td>
<?php if (!$tables_status['exam_schedules']): ?>
<a href="database/setup_exam_tables.php" class="btn btn-primary btn-sm">Create</a>
<?php else: ?>
<span class="text-muted">No action needed</span>
<?php endif; ?>
</td>
</tr>
<tr>
<td>question_banks Table</td>
<td>
<?php if ($tables_status['question_banks']): ?>
<span class="badge bg-success">Exists</span>
<?php else: ?>
<span class="badge bg-danger">Missing</span>
<?php endif; ?>
</td>
<td>
<?php if (!$tables_status['question_banks']): ?>
<a href="database/setup_exam_tables.php" class="btn btn-primary btn-sm">Create</a>
<?php else: ?>
<span class="text-muted">No action needed</span>
<?php endif; ?>
</td>
</tr>
<tr>
<td>questions Table</td>
<td>
<?php if ($tables_status['questions']): ?>
<span class="badge bg-success">Exists</span>
<?php else: ?>
<span class="badge bg-danger">Missing</span>
<?php endif; ?>
</td>
<td>
<?php if (!$tables_status['questions']): ?>
<a href="database/setup_exam_tables.php" class="btn btn-primary btn-sm">Create</a>
<?php else: ?>
<span class="text-muted">No action needed</span>
<?php endif; ?>
</td>
</tr>
<tr>
<td>exam_question_maps Table</td>
<td>
<?php if ($tables_status['exam_question_maps']): ?>
<span class="badge bg-success">Exists</span>
<?php else: ?>
<span class="badge bg-danger">Missing</span>
<?php endif; ?>
</td>
<td>
<?php if (!$tables_status['exam_question_maps']): ?>
<form method="post" action="" class="d-inline">
<input type="hidden" name="action" value="create_exam_question_maps">
<button type="submit" class="btn btn-primary btn-sm">Create</button>
</form>
<?php else: ?>
<span class="text-muted">No action needed</span>
<?php endif; ?>
</td>
</tr>
<tr>
<td>question_bank_id Field in questions</td>
<td>
<?php if ($question_bank_field_exists): ?>
<span class="badge bg-success">Exists</span>
<?php else: ?>
<span class="badge bg-danger">Missing</span>
<?php endif; ?>
</td>
<td>
<?php if (!$question_bank_field_exists && $tables_status['questions'] && $tables_status['question_banks']): ?>
<form method="post" action="" class="d-inline">
<input type="hidden" name="action" value="add_question_bank_field">
<button type="submit" class="btn btn-primary btn-sm">Add Field</button>
</form>
<?php else: ?>
<span class="text-muted">No action needed</span>
<?php endif; ?>
</td>
</tr>
<tr>
<td>Orphaned Question Mappings</td>
<td>
<?php
$orphaned_count = 0;
if ($tables_status['exam_question_maps']) {
$orphaned_query = "SELECT COUNT(*) AS count
FROM exam_question_maps eqm
LEFT JOIN questions q ON eqm.question_id = q.id
LEFT JOIN exam_schedules es ON eqm.exam_id = es.id
WHERE q.id IS NULL OR es.id IS NULL";
$result = $conn->query($orphaned_query);
if ($result) {
$orphaned_count = $result->fetch_assoc()['count'];
}
}
?>
<?php if ($orphaned_count > 0): ?>
<span class="badge bg-warning"><?php echo $orphaned_count; ?> Orphaned</span>
<?php else: ?>
<span class="badge bg-success">None</span>
<?php endif; ?>
</td>
<td>
<?php if ($orphaned_count > 0): ?>
<form method="post" action="" class="d-inline">
<input type="hidden" name="action" value="fix_orphaned_question_mappings">
<button type="submit" class="btn btn-warning btn-sm">Fix</button>
</form>
<?php else: ?>
<span class="text-muted">No action needed</span>
<?php endif; ?>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Statistics -->
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">System Statistics</h6>
</div>
<div class="card-body">
<div class="row">
<!-- Exams Count -->
<div class="col-md-6 mb-4">
<div class="card border-left-primary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
Total Exams</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<?php echo isset($statistics['exams']) ? $statistics['exams'] : 'N/A'; ?>
</div>
</div>
<div class="col-auto">
<i class="fas fa-calendar fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Question Banks Count -->
<div class="col-md-6 mb-4">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
Question Banks</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<?php echo isset($statistics['question_banks']) ? $statistics['question_banks'] : 'N/A'; ?>
</div>
</div>
<div class="col-auto">
<i class="fas fa-folder fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Questions Count -->
<div class="col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
Total Questions</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<?php echo isset($statistics['questions']) ? $statistics['questions'] : 'N/A'; ?>
</div>
</div>
<div class="col-auto">
<i class="fas fa-question-circle fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Mapped Questions Count -->
<div class="col-md-6 mb-4">
<div class="card border-left-warning shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
Mapped Questions</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<?php echo isset($statistics['mapped_questions']) ? $statistics['mapped_questions'] : 'N/A'; ?>
</div>
</div>
<div class="col-auto">
<i class="fas fa-link fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<?php if (isset($statistics['questions_without_bank']) && $statistics['questions_without_bank'] > 0): ?>
<div class="alert alert-warning mt-3">
<i class="fas fa-exclamation-triangle"></i> There are <?php echo $statistics['questions_without_bank']; ?> questions not assigned to any question bank.
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Exams with Zero Questions -->
<?php if ($tables_status['exam_schedules'] && $tables_status['exam_question_maps']): ?>
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-warning">Exams with No Questions</h6>
</div>
<div class="card-body">
<?php
$empty_exams_query = "SELECT es.id, es.title, c.title as course_title
FROM exam_schedules es
JOIN courses c ON es.course_id = c.id
LEFT JOIN exam_question_maps eqm ON es.id = eqm.exam_id
WHERE eqm.id IS NULL
ORDER BY es.exam_date DESC";
$empty_exams_result = $conn->query($empty_exams_query);
?>
<?php if ($empty_exams_result && $empty_exams_result->num_rows > 0): ?>
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Exam Title</th>
<th>Course</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php while ($exam = $empty_exams_result->fetch_assoc()): ?>
<tr>
<td><?php echo htmlspecialchars($exam['title']); ?></td>
<td><?php echo htmlspecialchars($exam['course_title']); ?></td>
<td>
<a href="map_questions.php?exam_id=<?php echo $exam['id']; ?>" class="btn btn-primary btn-sm">
<i class="fas fa-link"></i> Map Questions
</a>
</td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
</div>
<?php else: ?>
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> All exams have at least one question mapped.
</div>
<?php endif; ?>
</div>
</div>
</div>
<?php endif; ?>
<!-- Question Banks by Course -->
<?php if (isset($statistics['banks_by_course']) && !empty($statistics['banks_by_course'])): ?>
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-info">Question Banks by Course</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Course</th>
<th>Question Banks</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($statistics['banks_by_course'] as $course_id => $count): ?>
<tr>
<td>
<?php
if ($course_id === 'General') {
echo 'General (No Course)';
} else {
echo isset($courses[$course_id]) ? htmlspecialchars($courses[$course_id]) : 'Unknown Course';
}
?>
</td>
<td><?php echo $count; ?></td>
<td>
<?php if ($course_id !== 'General'): ?>
<a href="banks.php?course_id=<?php echo $course_id; ?>" class="btn btn-info btn-sm">
<i class="fas fa-folder-open"></i> View Banks
</a>
<?php else: ?>
<a href="banks.php" class="btn btn-info btn-sm">
<i class="fas fa-folder-open"></i> View Banks
</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php include_once 'includes/footer.php'; ?>