update courses

This commit is contained in:
Flatlogic Bot 2026-04-06 17:25:15 +00:00
parent cbd1870a55
commit a7d7445387
9 changed files with 623 additions and 11 deletions

View File

@ -16,6 +16,22 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
exit;
}
if ($post_action === 'close_all_registration') {
db()->query("UPDATE courses SET registration_open = 0");
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
}
if ($post_action === 'open_all_registration') {
db()->query("UPDATE courses SET registration_open = 1");
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
}
if ($post_action === 'reset_all_students') {
db()->query("TRUNCATE TABLE course_students");
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
}
if ($post_action === 'edit' || $post_action === 'add') {
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
@ -23,6 +39,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$desc_ar = $_POST['description_ar'] ?? '';
$status = $_POST['status'] ?? 'active';
$price = (float)($_POST['price'] ?? 0);
$max_students = (isset($_POST['max_students']) && $_POST['max_students'] !== '') ? (int)$_POST['max_students'] : null;
$registration_open = isset($_POST['registration_open']) ? 1 : 0;
$picture = null;
if ($post_action === 'edit' && $post_id > 0) {
@ -44,11 +62,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($post_action === 'edit' && $post_id > 0) {
$stmt = db()->prepare("UPDATE courses SET name_en=?, name_ar=?, description_en=?, description_ar=?, status=?, price=?, picture=? WHERE id=?");
$stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture, $post_id]);
$stmt = db()->prepare("UPDATE courses SET name_en=?, name_ar=?, description_en=?, description_ar=?, status=?, price=?, picture=?, max_students=?, registration_open=? WHERE id=?");
$stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture, $max_students, $registration_open, $post_id]);
} else {
$stmt = db()->prepare("INSERT INTO courses (name_en, name_ar, description_en, description_ar, status, price, picture) VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture]);
$stmt = db()->prepare("INSERT INTO courses (name_en, name_ar, description_en, description_ar, status, price, picture, max_students, registration_open) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture, $max_students, $registration_open]);
}
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
@ -105,7 +123,21 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
<div>
<h1 class="section-title mb-2"><?= h(t('Courses', 'الدورات')) ?></h1>
</div>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addCourseModal" style="background-color: var(--accent); border-color: var(--accent);">+ <?= h(t('Add Course', 'إضافة دورة')) ?></button>
<div class="d-flex flex-wrap gap-2 justify-content-end">
<form method="post" action="<?= h(app_url('admin.php', ['page'=>'courses'])) ?>" class="m-0" onsubmit="return confirm('<?= h(t('Close registration for all courses?', 'هل أنت متأكد من إغلاق التسجيل لجميع الدورات؟')) ?>');">
<input type="hidden" name="action" value="close_all_registration">
<button type="submit" class="btn btn-outline-warning btn-sm"><?= h(t('Close All', 'إغلاق الكل')) ?></button>
</form>
<form method="post" action="<?= h(app_url('admin.php', ['page'=>'courses'])) ?>" class="m-0" onsubmit="return confirm('<?= h(t('Open registration for all courses?', 'هل أنت متأكد من فتح التسجيل لجميع الدورات؟')) ?>');">
<input type="hidden" name="action" value="open_all_registration">
<button type="submit" class="btn btn-outline-success btn-sm"><?= h(t('Open All', 'فتح الكل')) ?></button>
</form>
<form method="post" action="<?= h(app_url('admin.php', ['page'=>'courses'])) ?>" class="m-0" onsubmit="return confirm('<?= h(t('Are you absolutely sure you want to remove ALL students from ALL courses to start a new batch?', 'هل أنت متأكد تماماً أنك تريد إزالة جميع الطلاب من جميع الدورات لبدء دفعة جديدة؟')) ?>');">
<input type="hidden" name="action" value="reset_all_students">
<button type="submit" class="btn btn-outline-danger btn-sm"><?= h(t('Reset Batch', 'إعادة ضبط الدفعة')) ?></button>
</form>
<button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#addCourseModal" style="background-color: var(--accent); border-color: var(--accent);">+ <?= h(t('Add Course', 'إضافة دورة')) ?></button>
</div>
</div>
<div class="panel-card mb-4">
@ -128,9 +160,10 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
<th><?= h(t('Name', 'الاسم')) ?></th>
<th><?= h(t('Price', 'السعر')) ?></th>
<th><?= h(t('Status', 'الحالة')) ?></th>
<th><?= h(t('Students', 'الطلاب')) ?></th>
<th><?= h(t('Assigned', 'مخصص')) ?></th>
<th><?= h(t('Reg.', 'التسجيل')) ?></th>
<th><?= h(t('Description', 'الوصف')) ?></th>
<th><?= h(t('Actions', 'إجراءات')) ?></th>
<th class="text-end"><?= h(t('Actions', 'إجراءات')) ?></th>
</tr>
</thead>
<tbody>
@ -163,11 +196,21 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
</td>
<td>
<span class="badge bg-info text-dark"><?= $assigned_count ?></span>
<?php if ($row['max_students']): ?>
<span class="badge bg-secondary">/ <?= h($row['max_students']) ?></span>
<?php endif; ?>
</td>
<td>
<?php if ($row['registration_open']): ?>
<span class="badge bg-success"><?= h(t('Open', 'مفتوح')) ?></span>
<?php else: ?>
<span class="badge bg-danger"><?= h(t('Closed', 'مغلق')) ?></span>
<?php endif; ?>
</td>
<td class="text-truncate" style="max-width: 200px;">
<?= h(current_lang() === 'ar' ? $row['description_ar'] : $row['description_en']) ?>
</td>
<td>
<td class="text-end">
<button type="button" class="btn btn-sm btn-outline-info" data-bs-toggle="modal" data-bs-target="#manageStudentsModal<?= $row['id'] ?>" title="<?= h(t('Manage Students', 'إدارة الطلاب')) ?>">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-people" viewBox="0 0 16 16">
<path d="M15 14s1 0 1-1-1-4-5-4-5 3-5 4 1 1 1 1zm-7.978-1L7 12.996c.001-.264.167-1.03.76-1.72C8.312 10.629 9.282 10 11 10c1.717 0 2.687.63 3.24 1.276.593.69.758 1.457.76 1.72l-.008.002-.014.002zM11 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4m3-2a3 3 0 1 1-6 0 3 3 0 0 1 6 0M6.936 9.28a6 6 0 0 0-1.23-.247A7 7 0 0 0 5 9c-4 0-5 3-5 4q0 1 1 1h4.216A2.24 2.24 0 0 1 5 13c0-1.01.377-2.042 1.09-2.904.243-.294.526-.569.846-.816M4.92 10A5.5 5.5 0 0 0 4 13H1c0-.26.164-1.03.76-1.724.545-.636 1.492-1.256 3.16-1.275ZM1.5 5.5a3 3 0 1 1 6 0 3 3 0 0 1-6 0m3-2a2 2 0 1 0 0 4 2 2 0 0 0 0-4"/>
@ -263,6 +306,10 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
<input type="number" step="0.01" name="price" class="form-control" value="<?= h($row['price'] ?? 0) ?>">
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Max Students', 'الحد الأقصى للطلاب')) ?></label>
<input type="number" name="max_students" class="form-control" placeholder="<?= h(t('Empty = unlimited', 'فارغ = غير محدود')) ?>" value="<?= h($row['max_students']) ?>">
</div>
<div class="col-md-12 mb-3">
<label class="form-label"><?= h(t('Picture', 'صورة')) ?></label>
<input type="file" name="picture" class="form-control" accept="image/*">
<?php if(!empty($row['picture'])): ?>
@ -276,6 +323,12 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
<option value="inactive" <?= ($row['status'] ?? 'active') === 'inactive' ? 'selected' : '' ?>><?= h(t('Inactive', 'غير نشط')) ?></option>
</select>
</div>
<div class="col-12 mb-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="registration_open" id="regSwitch<?= $row['id'] ?>" value="1" <?= $row['registration_open'] ? 'checked' : '' ?>/>
<label class="form-check-label" for="regSwitch<?= $row['id'] ?>"><?= h(t('Registration Open', 'التسجيل مفتوح')) ?></label>
</div>
</div>
</div>
<div class="d-flex justify-content-end gap-2 mt-4">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal"><?= h(t('Cancel', 'إلغاء')) ?></button>
@ -290,7 +343,7 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
<?php endforeach; ?>
<?php if(!$items): ?>
<tr><td colspan="6" class="text-center text-secondary py-3"><?= h(t('No courses found.', 'لا توجد دورات.')) ?></td></tr>
<tr><td colspan="8" class="text-center text-secondary py-3"><?= h(t('No courses found.', 'لا توجد دورات.')) ?></td></tr>
<?php endif; ?>
</tbody>
</table>
@ -342,6 +395,10 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
<input type="number" step="0.01" name="price" class="form-control" value="0.00">
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Max Students', 'الحد الأقصى للطلاب')) ?></label>
<input type="number" name="max_students" class="form-control" placeholder="<?= h(t('Empty = unlimited', 'فارغ = غير محدود')) ?>">
</div>
<div class="col-md-12 mb-3">
<label class="form-label"><?= h(t('Picture', 'صورة')) ?></label>
<input type="file" name="picture" class="form-control" accept="image/*">
</div>
@ -352,6 +409,12 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
<option value="inactive"><?= h(t('Inactive', 'غير نشط')) ?></option>
</select>
</div>
<div class="col-12 mb-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="registration_open" id="regSwitchAdd" value="1" checked>
<label class="form-check-label" for="regSwitchAdd"><?= h(t('Registration Open', 'التسجيل مفتوح')) ?></label>
</div>
</div>
</div>
<div class="d-flex justify-content-end gap-2 mt-4">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal"><?= h(t('Cancel', 'إلغاء')) ?></button>
@ -362,4 +425,4 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
</div>
</div>
</div>
<!-- End Add Modal -->
<!-- End Add Modal -->

View File

@ -9,6 +9,21 @@ $courseIdForView = (int) ($_GET['course_id'] ?? $_POST['course_id'] ?? 0);
$course = null;
if ($courseIdForView > 0) {
$course = db()->query("SELECT * FROM courses WHERE id = $courseIdForView")->fetch();
if ($course) {
if (!$course['registration_open']) {
$msg = current_lang() === 'ar' ? 'التسجيل في هذه الدورة/الدفعة مغلق حالياً.' : 'Registration for this course/batch is currently closed.';
die("<div style='padding:2rem;text-align:center;font-family:sans-serif'><h1>" . $msg . "</h1><a href='index.php'>" . (current_lang() === 'ar' ? 'العودة' : 'Back') . "</a></div>");
}
if ($course['max_students'] > 0) {
$enrolled = db()->query("SELECT COUNT(*) FROM course_students WHERE course_id = $courseIdForView")->fetchColumn();
if ($enrolled >= $course['max_students']) {
$msg = current_lang() === 'ar' ? 'لقد وصلت هذه الدورة إلى الحد الأقصى لعدد الطلاب.' : 'This course has reached its maximum capacity.';
die("<div style='padding:2rem;text-align:center;font-family:sans-serif'><h1>" . $msg . "</h1><a href='index.php'>" . (current_lang() === 'ar' ? 'العودة' : 'Back') . "</a></div>");
}
}
} else {
die('Course not found');
}
}
$errors = [];
$form = [

View File

@ -96,7 +96,21 @@ $metrics = ['subjects' => count($subjects), 'teachers' => db()->query("SELECT CO
</div>
<p class="text-secondary mb-4 flex-grow-1"><?= h(current_lang() === 'ar' ? $course['description_ar'] : $course['description_en']) ?></p>
<div class="d-grid mt-auto">
<a class="btn btn-dark" href="<?= h(app_url('checkout.php', ['course_id' => $course['id']])) ?>"><?= h(t('Enroll Now', 'سجل الآن')) ?></a>
<?php
$isFull = false;
$isClosed = !$course['registration_open'];
if ($course['max_students'] > 0) {
$enrolled = db()->query("SELECT COUNT(*) FROM course_students WHERE course_id = " . $course['id'])->fetchColumn();
if ($enrolled >= $course['max_students']) {
$isFull = true;
}
}
if ($isClosed || $isFull):
?>
<button class="btn btn-secondary" disabled><?= h($isClosed ? t('Registration Closed', 'التسجيل مغلق') : t('Class Full', 'مكتمل العدد')) ?></button>
<?php else: ?>
<a class="btn btn-dark" href="<?= h(app_url('checkout.php', ['course_id' => $course['id']])) ?>"><?= h(t('Enroll Now', 'سجل الآن')) ?></a>
<?php endif; ?>
</div>
</div>
</article>

237
patch_admin.php Normal file
View File

@ -0,0 +1,237 @@
<?php
$content = file_get_contents('admin_courses.php');
// 1. Add post actions
$post_actions_orig = " if (\$post_action === 'edit' || \$post_action === 'add') {";
$post_actions_new = <<<PHP
if (\$post_action === 'close_all_registration') {
db()->query("UPDATE courses SET registration_open = 0");
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
}
if (\$post_action === 'open_all_registration') {
db()->query("UPDATE courses SET registration_open = 1");
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
}
if (\$post_action === 'reset_all_students') {
db()->query("TRUNCATE TABLE course_students");
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
}
if (\$post_action === 'edit' || \$post_action === 'add') {
PHP;
$content = str_replace($post_actions_orig, $post_actions_new, $content);
// 2. Add max_students and registration_open to post
$vars_orig = <<<PHP
$status = $_POST['status'] ?? 'active';
$price = (float)($_POST['price'] ?? 0);
PHP;
$vars_new = <<<PHP
$status = $_POST['status'] ?? 'active';
$price = (float)($_POST['price'] ?? 0);
$max_students = (isset($_POST['max_students']) && $_POST['max_students'] !== '') ? (int)$_POST['max_students'] : null;
$registration_open = isset($_POST['registration_open']) ? 1 : 0;
PHP;
$content = str_replace($vars_orig, $vars_new, $content);
// 3. Update query edit
$edit_orig = '$stmt = db()->prepare("UPDATE courses SET name_en=?, name_ar=?, description_en=?, description_ar=?, status=?, price=?, picture=? WHERE id=?");' . "\n" .
' $stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture, $post_id]);';
$edit_new = '$stmt = db()->prepare("UPDATE courses SET name_en=?, name_ar=?, description_en=?, description_ar=?, status=?, price=?, picture=?, max_students=?, registration_open=? WHERE id=?");' . "\n" .
' $stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture, $max_students, $registration_open, $post_id]);';
$content = str_replace($edit_orig, $edit_new, $content);
// 4. Update query add
$add_orig = '$stmt = db()->prepare("INSERT INTO courses (name_en, name_ar, description_en, description_ar, status, price, picture) VALUES (?, ?, ?, ?, ?, ?, ?)");' . "\n" .
' $stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture]);';
$add_new = '$stmt = db()->prepare("INSERT INTO courses (name_en, name_ar, description_en, description_ar, status, price, picture, max_students, registration_open) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");' . "\n" .
' $stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture, $max_students, $registration_open]);';
$content = str_replace($add_orig, $add_new, $content);
// 5. Add bulk buttons
$buttons_orig = <<<PHP
<div>
<h1 class="section-title mb-2"><?= h(t('Courses', 'الدورات')) ?></h1>
</div>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addCourseModal" style="background-color: var(--accent); border-color: var(--accent);">+ <?= h(t('Add Course', 'إضافة دورة')) ?></button>
</div>
<div class="panel-card mb-4">
PHP;
$buttons_new = <<<PHP
<div>
<h1 class="section-title mb-2"><?= h(t('Courses', 'الدورات')) ?></h1>
</div>
<div class="d-flex flex-wrap gap-2 justify-content-end">
<form method="post" action="<?= h(app_url('admin.php', ['page'=>'courses'])) ?>" class="m-0" onsubmit="return confirm('<?= h(t('Close registration for all courses?', 'هل أنت متأكد من إغلاق التسجيل لجميع الدورات؟')) ?>');">
<input type="hidden" name="action" value="close_all_registration">
<button type="submit" class="btn btn-outline-warning btn-sm"><?= h(t('Close All', 'إغلاق الكل')) ?></button>
</form>
<form method="post" action="<?= h(app_url('admin.php', ['page'=>'courses'])) ?>" class="m-0" onsubmit="return confirm('<?= h(t('Open registration for all courses?', 'هل أنت متأكد من فتح التسجيل لجميع الدورات؟')) ?>');">
<input type="hidden" name="action" value="open_all_registration">
<button type="submit" class="btn btn-outline-success btn-sm"><?= h(t('Open All', 'فتح الكل')) ?></button>
</form>
<form method="post" action="<?= h(app_url('admin.php', ['page'=>'courses'])) ?>" class="m-0" onsubmit="return confirm('<?= h(t('Are you absolutely sure you want to remove ALL students from ALL courses to start a new batch?', 'هل أنت متأكد تماماً أنك تريد إزالة جميع الطلاب من جميع الدورات لبدء دفعة جديدة؟')) ?>');">
<input type="hidden" name="action" value="reset_all_students">
<button type="submit" class="btn btn-outline-danger btn-sm"><?= h(t('Reset Batch', 'إعادة ضبط الدفعة')) ?></button>
</form>
<button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#addCourseModal" style="background-color: var(--accent); border-color: var(--accent);">+ <?= h(t('Add Course', 'إضافة دورة')) ?></button>
</div>
</div>
<div class="panel-card mb-4">
PHP;
$content = str_replace($buttons_orig, $buttons_new, $content);
// 6. List view columns
$th_orig = <<<PHP
<th><?= h(t('Assigned', 'مخصص')) ?></th>
<th class="text-end"><?= h(t('Actions', 'إجراءات')) ?></th>
PHP;
$th_new = <<<PHP
<th><?= h(t('Assigned', 'مخصص')) ?></th>
<th><?= h(t('Reg.', 'التسجيل')) ?></th>
<th class="text-end"><?= h(t('Actions', 'إجراءات')) ?></th>
PHP;
$content = str_replace($th_orig, $th_new, $content);
$td_orig = <<<PHP
<td>
<span class="badge bg-info text-dark"><?= $assigned_count ?></span>
</td>
<td class="text-truncate" style="max-width: 200px;">
<?= h(current_lang() === 'ar' ? $row['description_ar'] : $row['description_en']) ?>
</td>
<td>
<button type="button" class="btn btn-sm btn-outline-info" data-bs-toggle="modal" data-bs-target="#manageStudentsModal<?= $row['id'] ?>" title="<?= h(t('Manage Students', 'إدارة الطلاب')) ?>">
PHP;
$td_new = <<<PHP
<td>
<span class="badge bg-info text-dark"><?= $assigned_count ?></span>
<?php if ($row['max_students']): ?>
<span class="badge bg-secondary">/ <?= h($row['max_students']) ?></span>
<?php endif; ?>
</td>
<td class="text-truncate" style="max-width: 200px;">
<?= h(current_lang() === 'ar' ? $row['description_ar'] : $row['description_en']) ?>
</td>
<td>
<?php if ($row['registration_open']): ?>
<span class="badge bg-success"><?= h(t('Open', 'مفتوح')) ?></span>
<?php else: ?>
<span class="badge bg-danger"><?= h(t('Closed', 'مغلق')) ?></span>
<?php endif; ?>
</td>
<td>
<button type="button" class="btn btn-sm btn-outline-info" data-bs-toggle="modal" data-bs-target="#manageStudentsModal<?= $row['id'] ?>" title="<?= h(t('Manage Students', 'إدارة الطلاب')) ?>">
PHP;
$content = str_replace($td_orig, $td_new, $content);
// 7. Modals
$edit_modal_orig = <<<PHP
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Price', 'السعر')) ?></label>
<input type="number" step="0.01" name="price" class="form-control" value="<?= h($row['price'] ?? 0) ?>">
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Picture', 'صورة')) ?></label>
<input type="file" name="picture" class="form-control" accept="image/*">
PHP;
$edit_modal_new = <<<PHP
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Price', 'السعر')) ?></label>
<input type="number" step="0.01" name="price" class="form-control" value="<?= h($row['price'] ?? 0) ?>">
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Max Students', 'الحد الأقصى للطلاب')) ?></label>
<input type="number" name="max_students" class="form-control" placeholder="<?= h(t('Empty = unlimited', 'فارغ = غير محدود')) ?>" value="<?= h($row['max_students']) ?>">
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Picture', 'صورة')) ?></label>
<input type="file" name="picture" class="form-control" accept="image/*">
PHP;
$content = str_replace($edit_modal_orig, $edit_modal_new, $content);
$edit_modal_orig2 = <<<PHP
<div class="col-12 mb-3">
<label class="form-label"><?= h(t('Status', 'الحالة')) ?></label>
<select name="status" class="form-select">
<option value="active" <?= ($row['status'] ?? 'active') === 'active' ? 'selected' : '' ?>><?= h(t('Active', 'نشط')) ?></option>
<option value="inactive" <?= ($row['status'] ?? 'active') === 'inactive' ? 'selected' : '' ?>><?= h(t('Inactive', 'غير نشط')) ?></option>
</select>
</div>
PHP;
$edit_modal_new2 = <<<PHP
<div class="col-12 mb-3">
<label class="form-label"><?= h(t('Status', 'الحالة')) ?></label>
<select name="status" class="form-select">
<option value="active" <?= ($row['status'] ?? 'active') === 'active' ? 'selected' : '' ?>><?= h(t('Active', 'نشط')) ?></option>
<option value="inactive" <?= ($row['status'] ?? 'active') === 'inactive' ? 'selected' : '' ?>><?= h(t('Inactive', 'غير نشط')) ?></option>
</select>
</div>
<div class="col-12 mb-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="registration_open" id="regSwitch<?= $row['id'] ?>" value="1" <?= $row['registration_open'] ? 'checked' : '' ?>/>
<label class="form-check-label" for="regSwitch<?= $row['id'] ?>"><?= h(t('Registration Open', 'التسجيل مفتوح')) ?></label>
</div>
</div>
PHP;
$content = str_replace($edit_modal_orig2, $edit_modal_new2, $content);
$add_modal_orig = <<<PHP
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Price', 'السعر')) ?></label>
<input type="number" step="0.01" name="price" class="form-control" value="0.00">
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Picture', 'صورة')) ?></label>
<input type="file" name="picture" class="form-control" accept="image/*">
PHP;
$add_modal_new = <<<PHP
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Price', 'السعر')) ?></label>
<input type="number" step="0.01" name="price" class="form-control" value="0.00">
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Max Students', 'الحد الأقصى للطلاب')) ?></label>
<input type="number" name="max_students" class="form-control" placeholder="<?= h(t('Empty = unlimited', 'فارغ = غير محدود')) ?>">
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?= h(t('Picture', 'صورة')) ?></label>
<input type="file" name="picture" class="form-control" accept="image/*">
PHP;
$content = str_replace($add_modal_orig, $add_modal_new, $content);
$add_modal_orig2 = <<<PHP
<div class="col-12 mb-3">
<label class="form-label"><?= h(t('Status', 'الحالة')) ?></label>
<select name="status" class="form-select">
<option value="active"><?= h(t('Active', 'نشط')) ?></option>
<option value="inactive"><?= h(t('Inactive', 'غير نشط')) ?></option>
</select>
</div>
PHP;
$add_modal_new2 = <<<PHP
<div class="col-12 mb-3">
<label class="form-label"><?= h(t('Status', 'الحالة')) ?></label>
<select name="status" class="form-select">
<option value="active"><?= h(t('Active', 'نشط')) ?></option>
<option value="inactive"><?= h(t('Inactive', 'غير نشط')) ?></option>
</select>
</div>
<div class="col-12 mb-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="registration_open" id="regSwitchAdd" value="1" checked>
<label class="form-check-label" for="regSwitchAdd"><?= h(t('Registration Open', 'التسجيل مفتوح')) ?></label>
</div>
</div>
PHP;
$content = str_replace($add_modal_orig2, $add_modal_new2, $content);
file_put_contents('admin_courses.php', $content);
echo "Done";
?>

160
patch_admin.py Normal file
View File

@ -0,0 +1,160 @@
import sys
import re
with open('admin_courses.php', 'r') as f:
content = f.read()
# 1. Add post actions
content = content.replace(
" if ($post_action === 'edit' || $post_action === 'add') {",
""" if ($post_action === 'close_all_registration') {
db()->query(\"UPDATE courses SET registration_open = 0\");
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
}
if ($post_action === 'open_all_registration') {
db()->query(\"UPDATE courses SET registration_open = 1\");
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
}
if ($post_action === 'reset_all_students') {
db()->query(\"TRUNCATE TABLE course_students\");
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
exit;
}
if ($post_action === 'edit' || $post_action === 'add') {"""
)
# 2. Add max_students and registration_open to post
content = content.replace(
""" $status = $_POST['status'] ?? 'active';
$price = (float)($_POST['price'] ?? 0);""",
""" $status = $_POST['status'] ?? 'active';
$price = (float)($_POST['price'] ?? 0);
$max_students = (isset($_POST['max_students']) && $_POST['max_students'] !== '') ? (int)$_POST['max_students'] : null;
$registration_open = isset($_POST['registration_open']) ? 1 : 0;"""
)
# 3. Update query edit
content = content.replace(
'$stmt = db()->prepare("UPDATE courses SET name_en=?, name_ar=?, description_en=?, description_ar=?, status=?, price=?, picture=? WHERE id=?");\n $stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture, $post_id]);',
'$stmt = db()->prepare("UPDATE courses SET name_en=?, name_ar=?, description_en=?, description_ar=?, status=?, price=?, picture=?, max_students=?, registration_open=? WHERE id=?");\n $stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture, $max_students, $registration_open, $post_id]);'
)
# 4. Update query add
content = content.replace(
'$stmt = db()->prepare("INSERT INTO courses (name_en, name_ar, description_en, description_ar, status, price, picture) VALUES (?, ?, ?, ?, ?, ?, ?)");\n $stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture]);',
'$stmt = db()->prepare("INSERT INTO courses (name_en, name_ar, description_en, description_ar, status, price, picture, max_students, registration_open) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");\n $stmt->execute([$name_en, $name_ar, $desc_en, $desc_ar, $status, $price, $picture, $max_students, $registration_open]);'
)
# 5. Add bulk buttons
content = content.replace(
""" <div>
<h1 class=\"section-title mb-2\">?= h(t('Courses', 'الدورات')) ?></h1>
</div>
<button type=\"button\" class=\"btn btn-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#addCourseModal\" style=\"background-color: var(--accent); border-color: var(--accent);\">+ ?= h(t('Add Course', 'إضافة دورة')) ?></button>
</div>
<div class=\"panel-card mb-4\">
",
""" <div>
<h1 class=\"section-title mb-2\">?= h(t('Courses', 'الدورات')) ?></h1>
</div>
<div class=\"d-flex gap-2\">
<form method=\"post\" action=\"<?= h(app_url('admin.php', ['page'=>'courses'])) \" class=\"m-0\" onsubmit=\"return confirm('<?= h(t('Close registration for all courses?', 'هل أنت متأكد من إغلاق التسجيل لجميع الدورات؟')) ?>');\">
<input type=\"hidden\" name=\"action\" value=\"close_all_registration">
<button type=\"submit\" class=\"btn btn-outline-danger\">?= h(t('Close Registration (All)', 'إغلاق التسجيل للكل')) ?></button>
</form>
<form method=\"post\" action=\"<?= h(app_url('admin.php', ['page'=>'courses'])) \" class=\"m-0\" onsubmit=\"return confirm('<?= h(t('Open registration for all courses?', 'هل أنت متأكد من فتح التسجيل لجميع الدورات؟')) ?>');\">
<input type=\"hidden\" name=\"action\" value=\"open_all_registration">
<button type=\"submit\" class=\"btn btn-outline-success\">?= h(t('Open Registration (All)', 'فتح التسجيل للكل')) ?></button>
</form>
<button type=\"button\" class=\"btn btn-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#addCourseModal\" style=\"background-color: var(--accent); border-color: var(--accent);\">+ ?= h(t('Add Course', 'إضافة دورة')) ?></button>
</div>
</div>
<div class=\"panel-card mb-4\">
"""
)
# 6. Modal edit
content = content.replace(
""" <div class=\"col-md-6 mb-3\">
<label class=\"form-label\">?= h(t('Price', 'السعر')) ?></label>
<input type=\"number\" step=\"0.01\" name=\"price\" class=\"form-control\" value=\"<?= h($row['price']) ?>\">
</div>""",
""" <div class=\"col-md-6 mb-3\">
<label class=\"form-label\">?= h(t('Price', 'السعر')) ?></label>
<input type=\"number\" step=\"0.01\" name=\"price\" class=\"form-control\" value=\"<?= h($row['price']) ?>\">
</div>
<div class=\"col-md-6 mb-3\">
<label class=\"form-label\">?= h(t('Max Students', 'الحد الأقصى للطلاب')) ?></label>
<input type=\"number\" name=\"max_students\" class=\"form-control\" placeholder=\"<?= h(t('Empty = unlimited', 'فارغ = غير محدود')) ?>\" value=\"<?= h($row['max_students']) ?>\">
</div>
<div class=\"col-md-12 mb-3\">
<div class=\"form-check form-switch\">
<input class=\"form-check-input\" type=\"checkbox\" name=\"registration_open\" id=\"regSwitch<?= $row['id'] ?>\" value=\"1\" <?= $row['registration_open'] ? 'checked' : '' ?>/>
<label class=\"form-check-label\" for=\"regSwitch<?= $row['id'] ?>\">?= h(t('Registration Open', 'التسجيل مفتوح')) ?></label>
</div>
</div>"""
)
# 7. Modal add
content = content.replace(
""" <div class=\"col-md-6 mb-3\">
<label class=\"form-label\">?= h(t('Price', 'السعر')) ?></label>
<input type=\"number\" step=\"0.01\" name=\"price\" class=\"form-control\" value=\"0.00\">
</div>""",
""" <div class=\"col-md-6 mb-3\">
<label class=\"form-label\">?= h(t('Price', 'السعر')) ?></label>
<input type=\"number\" step=\"0.01\" name=\"price\" class=\"form-control\" value=\"0.00\">
</div>
<div class=\"col-md-6 mb-3\">
<label class=\"form-label\">?= h(t('Max Students', 'الحد الأقصى للطلاب')) ?></label>
<input type=\"number\" name=\"max_students\" class=\"form-control\" placeholder=\"<?= h(t('Empty = unlimited', 'فارغ = غير محدود')) ?>\">
</div>
<div class=\"col-md-12 mb-3\">
<div class=\"form-check form-switch\">
<input class=\"form-check-input\" type=\"checkbox\" name=\"registration_open\" id=\"regSwitchAdd\" value=\"1\" checked>
<label class=\"form-check-label\" for=\"regSwitchAdd\">?= h(t('Registration Open', 'التسجيل مفتوح')) ?></label>
</div>
</div>"""
)
# 8. update list to show registration status
content = content.replace(
""" <th>?= h(t('Assigned', 'مخصص')) ?></th>
<th class=\"text-end\">?= h(t('Actions', 'الإجراءات')) ?></th>""",
""" <th>?= h(t('Assigned', 'مخصص')) ?></th>
<th>?= h(t('Reg Status', 'حالة التسجيل')) ?></th>
<th class=\"text-end\">?= h(t('Actions', 'الإجراءات')) ?></th>"""
)
content = content.replace(
""" <td>
<span class=\"badge bg-secondary\">?= h($assigned_count) ?> <?= h(t('Students', 'طلاب')) ?></span>
</td>
<td class=\"text-end\">
""",
""" <td>
<span class=\"badge bg-secondary\">?= h($assigned_count) ?> <?= h(t('Students', 'طلاب')) ?></span>
<?php if ($row['max_students']): ?>
<span class=\"badge bg-info\">/ <?= h($row['max_students']) ?></span>
<?php endif; ?>
</td>
<td>
<?php if ($row['registration_open']): ?>
<span class=\"badge bg-success\">?= h(t('Open', 'مفتوح')) ?></span>
<?php else: ?>
<span class=\"badge bg-danger\">?= h(t('Closed', 'مغلق')) ?></span>
<?php endif; ?>
</td>
<td class=\"text-end\">
"""
)
with open('admin_courses.php', 'w') as f:
f.write(content)
print("Done")

31
patch_admin_courses.php Normal file

File diff suppressed because one or more lines are too long

29
patch_checkout.php Normal file
View File

@ -0,0 +1,29 @@
<?php
$file = 'checkout.php';
$content = file_get_contents($file);
// check course limits
$limit_check = <<<PHP
if ($courseIdForView > 0) {
$course = db()->query("SELECT * FROM courses WHERE id = $courseIdForView")->fetch();
if ($course) {
if (! $course['registration_open']) {
die(t('Registration for this course is currently closed.', 'التسجيل في هذه الدورة مغلق حالياً.'));
}
if ($course['max_students'] > 0) {
$enrolled = db()->query("SELECT COUNT(*) FROM course_students WHERE course_id = $courseIdForView")->fetchColumn();
if ($enrolled >= $course['max_students']) {
die(t('This course has reached its maximum number of students.', 'لقد وصلت هذه الدورة إلى الحد الأقصى لعدد الطلاب.'));
}
}
} else {
die('Course not found');
}
}
PHP;
$content = preg_replace("/if \(\\$courseIdForView > 0\) \{\\s*\\\$course = db\(\)->query\(\"SELECT \* FROM courses WHERE id = \\\$courseIdForView\"\)->fetch\(\);\\s*\}", $limit_check, $content);
file_put_contents($file, $content);
echo "Done\n";

34
patch_checkout.py Normal file
View File

@ -0,0 +1,34 @@
import sys
with open('checkout.php', 'r') as f:
content = f.read()
old_code = """if ($courseIdForView > 0) {
$course = db()->query("SELECT * FROM courses WHERE id = $courseIdForView")->fetch();
}"""
new_code = """if ($courseIdForView > 0) {
$course = db()->query("SELECT * FROM courses WHERE id = $courseIdForView")->fetch();
if ($course) {
if (!$course['registration_open']) {
$msg = current_lang() === 'ar' ? 'التسجيل في هذه الدورة/الدفعة مغلق حالياً.' : 'Registration for this course/batch is currently closed.';
die("<div style='padding:2rem;text-align:center;font-family:sans-serif'><h1>" . $msg . "</h1><a href='index.php'>" . (current_lang() === 'ar' ? 'العودة' : 'Back') . "</a></div>");
}
if ($course['max_students'] > 0) {
$enrolled = db()->query("SELECT COUNT(*) FROM course_students WHERE course_id = $courseIdForView")->fetchColumn();
if ($enrolled >= $course['max_students']) {
$msg = current_lang() === 'ar' ? 'لقد وصلت هذه الدورة إلى الحد الأقصى لعدد الطلاب.' : 'This course has reached its maximum capacity.';
die("<div style='padding:2rem;text-align:center;font-family:sans-serif'><h1>" . $msg . "</h1><a href='index.php'>" . (current_lang() === 'ar' ? 'العودة' : 'Back') . "</a></div>");
}
}
} else {
die('Course not found');
}
}"""
content = content.replace(old_code, new_code)
with open('checkout.php', 'w') as f:
f.write(content)
print("Done")

29
patch_index.py Normal file
View File

@ -0,0 +1,29 @@
import sys
with open('index.php', 'r') as f:
content = f.read()
old_button = """<a class="btn btn-dark" href="<?= h(app_url('checkout.php', ['course_id' => $course['id']])) ?>"><?= h(t('Enroll Now', 'سجل الآن')) ?></a>"""
new_button = """<?php
$isFull = false;
$isClosed = !$course['registration_open'];
if ($course['max_students'] > 0) {
$enrolled = db()->query("SELECT COUNT(*) FROM course_students WHERE course_id = " . $course['id'])->fetchColumn();
if ($enrolled >= $course['max_students']) {
$isFull = true;
}
}
if ($isClosed || $isFull):
?>
<button class="btn btn-secondary" disabled><?= h($isClosed ? t('Registration Closed', 'التسجيل مغلق') : t('Class Full', 'مكتمل العدد')) ?></button>
<?php else: ?>
<a class="btn btn-dark" href="<?= h(app_url('checkout.php', ['course_id' => $course['id']])) ?>"><?= h(t('Enroll Now', 'سجل الآن')) ?></a>
<?php endif; ?>"""
content = content.replace(old_button, new_button)
with open('index.php', 'w') as f:
f.write(content)
print("Done")