Autosave: 20260406-174830
This commit is contained in:
parent
a7d7445387
commit
6f28e66799
16
admin.php
16
admin.php
@ -148,7 +148,7 @@ render_head(
|
||||
</li>
|
||||
|
||||
<li class="nav-item w-100 mt-3 border-top pt-3">
|
||||
<a href="#settingsCollapse" data-bs-toggle="collapse" class="nav-link link-dark d-flex align-items-center justify-content-between text-secondary fw-bold px-3 py-2" aria-expanded="<?= in_array($page, ['profile', 'integrations']) ? 'true' : 'false' ?>" aria-controls="settingsCollapse" style="font-size: 0.95rem; letter-spacing: 0.5px;">
|
||||
<a href="#settingsCollapse" data-bs-toggle="collapse" class="nav-link link-dark d-flex align-items-center justify-content-between text-secondary fw-bold px-3 py-2" aria-expanded="<?= in_array($page, ['profile', 'integrations', 'landing']) ? 'true' : 'false' ?>" aria-controls="settingsCollapse" style="font-size: 0.95rem; letter-spacing: 0.5px;">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="bi bi-gear" viewBox="0 0 16 16">
|
||||
<path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492M5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0"/>
|
||||
@ -161,7 +161,7 @@ render_head(
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<div class="collapse <?= in_array($page, ['profile', 'integrations']) ? 'show' : '' ?>" id="settingsCollapse">
|
||||
<div class="collapse <?= in_array($page, ['profile', 'integrations', 'landing']) ? 'show' : '' ?>" id="settingsCollapse">
|
||||
<ul class="nav flex-column ms-3 mb-2">
|
||||
<li class="nav-item mb-1 mt-2">
|
||||
<a href="<?= h(app_url('admin.php', ['page' => 'profile'])) ?>" class="nav-link <?= $page === 'profile' ? 'active' : 'link-dark' ?> d-flex align-items-center gap-2" <?= $page === 'profile' ? 'style="background-color: var(--accent); color: white; border-radius: 6px;"' : '' ?>>
|
||||
@ -179,6 +179,16 @@ render_head(
|
||||
</svg>
|
||||
<?= h(t('Integrations', 'التكاملات')) ?>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="<?= h(app_url('admin.php', ['page' => 'landing'])) ?>" class="nav-link <?= $page === 'landing' ? 'active' : 'link-dark' ?> d-flex align-items-center gap-2" <?= $page === 'landing' ? 'style="background-color: var(--accent); color: white; border-radius: 6px;"' : '' ?> >
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-layout-text-window-reverse" viewBox="0 0 16 16">
|
||||
<path d="M13 6.5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h5a.5.5 0 0 0 .5-.5m0 3a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h5a.5.5 0 0 0 .5-.5m-.5 2.5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1 0-1z"/>
|
||||
<path d="M14 0a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zM2 1a1 1 0 0 0-1 1v1h14V2a1 1 0 0 0-1-1zM1 4v10a1 1 0 0 0 1 1h2V4zm4 0v11h9a1 1 0 0 0 1-1V4z"/>
|
||||
</svg>
|
||||
<?= h(t('Landing Page', 'الصفحة الرئيسية')) ?>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -320,6 +330,8 @@ render_head(
|
||||
<?php require_once __DIR__ . '/admin_assignments.php'; ?>
|
||||
<?php elseif ($page === 'integrations'): ?>
|
||||
<?php require_once __DIR__ . '/admin_integrations.php'; ?>
|
||||
<?php elseif ($page === 'landing'): ?>
|
||||
<?php require_once __DIR__ . '/admin_landing.php'; ?>
|
||||
<?php else: ?>
|
||||
<div class="section-header mb-4">
|
||||
<div>
|
||||
|
||||
106
admin_landing.php
Normal file
106
admin_landing.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
// admin_landing.php
|
||||
if (!isset($pdo)) {
|
||||
$pdo = db();
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'save_landing') {
|
||||
$settings = $_POST['settings'] ?? [];
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE landing_settings SET value_en = :en, value_ar = :ar WHERE setting_key = :key");
|
||||
foreach ($settings as $key => $values) {
|
||||
$stmt->execute([
|
||||
'key' => $key,
|
||||
'en' => $values['en'] ?? '',
|
||||
'ar' => $values['ar'] ?? ''
|
||||
]);
|
||||
}
|
||||
|
||||
header('Location: ' . app_url('admin.php', ['page' => 'landing', 'saved' => 1]));
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->query("SELECT setting_key, value_en, value_ar FROM landing_settings");
|
||||
$all_settings = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$settings = [];
|
||||
foreach ($all_settings as $row) {
|
||||
$settings[$row['setting_key']] = $row;
|
||||
}
|
||||
|
||||
$fields = [
|
||||
'hero_eyebrow' => ['label' => 'Hero Eyebrow / النص الصغير في البداية', 'type' => 'text'],
|
||||
'hero_title' => ['label' => 'Hero Title / العنوان الرئيسي', 'type' => 'textarea'],
|
||||
'hero_desc' => ['label' => 'Hero Description / الوصف', 'type' => 'textarea'],
|
||||
'courses_eyebrow' => ['label' => 'Courses Eyebrow / نص قسم الدورات', 'type' => 'text'],
|
||||
'courses_title' => ['label' => 'Courses Title / عنوان قسم الدورات', 'type' => 'textarea'],
|
||||
'subjects_eyebrow' => ['label' => 'Subjects Eyebrow / نص قسم المواد', 'type' => 'text'],
|
||||
'subjects_title' => ['label' => 'Subjects Title / عنوان قسم المواد', 'type' => 'textarea'],
|
||||
'flow_eyebrow' => ['label' => 'Delivery Flow Eyebrow / نص قسم مسار التسليم', 'type' => 'text'],
|
||||
'flow_title' => ['label' => 'Delivery Flow Title / عنوان قسم مسار التسليم', 'type' => 'textarea'],
|
||||
'plans_eyebrow' => ['label' => 'Plans Eyebrow / نص قسم الخطط', 'type' => 'text'],
|
||||
'plans_title' => ['label' => 'Plans Title / عنوان قسم الخطط', 'type' => 'textarea']
|
||||
];
|
||||
|
||||
?>
|
||||
|
||||
<div class="section-header mb-4">
|
||||
<div>
|
||||
<span class="eyebrow"><?= h(t('Settings', 'الإعدادات')) ?></span>
|
||||
<h1 class="section-title mb-2"><?= h(t('Landing Page Settings', 'إعدادات الصفحة الرئيسية')) ?></h1>
|
||||
<p class="text-secondary mb-0"><?= h(t('Customize the content of the landing page in English and Arabic.', 'تخصيص محتوى الصفحة الرئيسية باللغتين الإنجليزية والعربية.')) ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($_GET['saved'])): ?>
|
||||
<div class="alert alert-success"><?= h(t('Landing page settings updated successfully.', 'تم تحديث إعدادات الصفحة الرئيسية بنجاح.')) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="panel-card" style="max-width: 800px;">
|
||||
<form method="POST" action="">
|
||||
<input type="hidden" name="action" value="save_landing">
|
||||
|
||||
<ul class="nav nav-tabs mb-4" id="langTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="en-tab" data-bs-toggle="tab" data-bs-target="#en" type="button" role="tab">English</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="ar-tab" data-bs-toggle="tab" data-bs-target="#ar" type="button" role="tab">العربية</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content" id="langTabsContent">
|
||||
<!-- English Tab -->
|
||||
<div class="tab-pane fade show active" id="en" role="tabpanel">
|
||||
<?php foreach ($fields as $key => $field): ?>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold"><?= h($field['label']) ?></label>
|
||||
<?php if ($field['type'] === 'textarea'): ?>
|
||||
<textarea class="form-control" name="settings[<?= $key ?>][en]" rows="2"><?= h($settings[$key]['value_en'] ?? '') ?></textarea>
|
||||
<?php else: ?>
|
||||
<input type="text" class="form-control" name="settings[<?= $key ?>][en]" value="<?= h($settings[$key]['value_en'] ?? '') ?>">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Arabic Tab -->
|
||||
<div class="tab-pane fade" id="ar" role="tabpanel" dir="rtl">
|
||||
<?php foreach ($fields as $key => $field): ?>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold"><?= h($field['label']) ?></label>
|
||||
<?php if ($field['type'] === 'textarea'): ?>
|
||||
<textarea class="form-control" name="settings[<?= $key ?>][ar]" rows="2"><?= h($settings[$key]['value_ar'] ?? '') ?></textarea>
|
||||
<?php else: ?>
|
||||
<input type="text" class="form-control" name="settings[<?= $key ?>][ar]" value="<?= h($settings[$key]['value_ar'] ?? '') ?>">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="btn btn-dark"><?= h(t('Save Settings', 'حفظ الإعدادات')) ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -37,6 +37,33 @@ function project_description(): string
|
||||
return (string) ($_SERVER['PROJECT_DESCRIPTION'] ?? 'Modern multilingual e-learning classrooms with subscriptions, teachers, students, Google Meet live sessions, Thawani billing, and Wablas notifications.');
|
||||
}
|
||||
|
||||
|
||||
function get_landing_settings(): array {
|
||||
static $settings = null;
|
||||
if ($settings === null) {
|
||||
$settings = [];
|
||||
try {
|
||||
$stmt = db()->query("SELECT setting_key, value_en, value_ar FROM landing_settings");
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$settings[$row['setting_key']] = $row;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
return $settings;
|
||||
}
|
||||
|
||||
function landing_setting(string $key, string $default_en, string $default_ar): string {
|
||||
$settings = get_landing_settings();
|
||||
$lang = current_lang();
|
||||
if (isset($settings[$key])) {
|
||||
$val = $lang === 'ar' ? $settings[$key]['value_ar'] : $settings[$key]['value_en'];
|
||||
if (trim((string)$val) !== '') {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
return $lang === 'ar' ? $default_ar : $default_en;
|
||||
}
|
||||
function current_lang(): string
|
||||
{
|
||||
$lang = $_GET['lang'] ?? $_SESSION['lang'] ?? 'en';
|
||||
|
||||
22
index.php
22
index.php
@ -16,9 +16,9 @@ $metrics = ['subjects' => count($subjects), 'teachers' => db()->query("SELECT CO
|
||||
<div class="container py-5 py-lg-6">
|
||||
<div class="row align-items-center g-4 g-lg-5">
|
||||
<div class="col-lg-7">
|
||||
<span class="eyebrow"><?= h(t('Single platform LMS', 'منصة تعليم موحدة')) ?></span>
|
||||
<h1 class="display-title mt-3 mb-3"><?= h(t('Subscriptions, multilingual classrooms, and live Google Meet learning in one precise workspace.', 'الاشتراكات والفصول متعددة اللغات والتعلم المباشر عبر Google Meet في مساحة واحدة دقيقة.')) ?></h1>
|
||||
<p class="lead text-secondary mb-4"><?= h(t('Launch a polished e-learning experience for students, teachers, and admins with English/Arabic support, Thawani billing flows, and Wablas-ready WhatsApp notifications.', 'أطلق تجربة تعليم إلكتروني مصقولة للطلاب والمعلمين والإدارة مع دعم الإنجليزية والعربية وتدفقات دفع ثواني وإشعارات واتساب جاهزة عبر وابلاس.')) ?></p>
|
||||
<span class="eyebrow"><?= h(landing_setting('hero_eyebrow', 'Single platform LMS', 'منصة تعليم موحدة')) ?></span>
|
||||
<h1 class="display-title mt-3 mb-3"><?= h(landing_setting('hero_title', 'Subscriptions, multilingual classrooms, and live Google Meet learning in one precise workspace.', 'الاشتراكات والفصول متعددة اللغات والتعلم المباشر عبر Google Meet في مساحة واحدة دقيقة.')) ?></h1>
|
||||
<p class="lead text-secondary mb-4"><?= h(landing_setting('hero_desc', 'Launch a polished e-learning experience for students, teachers, and admins with English/Arabic support, Thawani billing flows, and Wablas-ready WhatsApp notifications.', 'أطلق تجربة تعليم إلكتروني مصقولة للطلاب والمعلمين والإدارة مع دعم الإنجليزية والعربية وتدفقات دفع ثواني وإشعارات واتساب جاهزة عبر وابلاس.')) ?></p>
|
||||
<div class="d-flex flex-wrap gap-2 mb-4">
|
||||
<a class="btn btn-dark btn-lg" href="<?= h(app_url('pricing.php')) ?>"><?= h(t('Start subscription flow', 'ابدأ مسار الاشتراك')) ?></a>
|
||||
<a class="btn btn-outline-dark btn-lg" href="<?= h(app_url('catalog.php')) ?>"><?= h(t('Browse subjects', 'تصفح المواد')) ?></a>
|
||||
@ -76,8 +76,8 @@ $metrics = ['subjects' => count($subjects), 'teachers' => db()->query("SELECT CO
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<div>
|
||||
<span class="eyebrow"><?= h(t('Featured Courses', 'الدورات المميزة')) ?></span>
|
||||
<h2 class="section-title"><?= h(t('Enroll in specialized short courses designed to accelerate your skills.', 'سجل في دورات قصيرة متخصصة لتسريع تطوير مهاراتك.')) ?></h2>
|
||||
<span class="eyebrow"><?= h(landing_setting('courses_eyebrow', 'Featured Courses', 'الدورات المميزة')) ?></span>
|
||||
<h2 class="section-title"><?= h(landing_setting('courses_title', 'Enroll in specialized short courses designed to accelerate your skills.', 'سجل في دورات قصيرة متخصصة لتسريع تطوير مهاراتك.')) ?></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-4 mt-3">
|
||||
@ -123,8 +123,8 @@ $metrics = ['subjects' => count($subjects), 'teachers' => db()->query("SELECT CO
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<div>
|
||||
<span class="eyebrow"><?= h(t('Featured subjects', 'المواد المميزة')) ?></span>
|
||||
<h2 class="section-title"><?= h(t('Separate pages for catalog, detail, checkout, and dashboards.', 'صفحات منفصلة للكتالوج والتفاصيل والدفع ولوحات التحكم.')) ?></h2>
|
||||
<span class="eyebrow"><?= h(landing_setting('subjects_eyebrow', 'Featured subjects', 'المواد المميزة')) ?></span>
|
||||
<h2 class="section-title"><?= h(landing_setting('subjects_title', 'Separate pages for catalog, detail, checkout, and dashboards.', 'صفحات منفصلة للكتالوج والتفاصيل والدفع ولوحات التحكم.')) ?></h2>
|
||||
</div>
|
||||
<a class="link-dark fw-semibold text-decoration-none" href="<?= h(app_url('catalog.php')) ?>"><?= h(t('See all subjects', 'عرض جميع المواد')) ?></a>
|
||||
</div>
|
||||
@ -153,8 +153,8 @@ $metrics = ['subjects' => count($subjects), 'teachers' => db()->query("SELECT CO
|
||||
<div class="container">
|
||||
<div class="section-header mb-4">
|
||||
<div>
|
||||
<span class="eyebrow"><?= h(t('Delivery flow', 'مسار التسليم')) ?></span>
|
||||
<h2 class="section-title"><?= h(t('One thin slice from discovery to live access.', 'شريحة رشيقة من الاكتشاف حتى الوصول المباشر.')) ?></h2>
|
||||
<span class="eyebrow"><?= h(landing_setting('flow_eyebrow', 'Delivery flow', 'مسار التسليم')) ?></span>
|
||||
<h2 class="section-title"><?= h(landing_setting('flow_title', 'One thin slice from discovery to live access.', 'شريحة رشيقة من الاكتشاف حتى الوصول المباشر.')) ?></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
@ -169,8 +169,8 @@ $metrics = ['subjects' => count($subjects), 'teachers' => db()->query("SELECT CO
|
||||
<div class="container">
|
||||
<div class="section-header mb-4">
|
||||
<div>
|
||||
<span class="eyebrow"><?= h(t('Plans', 'الخطط')) ?></span>
|
||||
<h2 class="section-title"><?= h(t('Plan-based access for a shared marketplace.', 'وصول قائم على الخطط لمنصة مشتركة.')) ?></h2>
|
||||
<span class="eyebrow"><?= h(landing_setting('plans_eyebrow', 'Plans', 'الخطط')) ?></span>
|
||||
<h2 class="section-title"><?= h(landing_setting('plans_title', 'Plan-based access for a shared marketplace.', 'وصول قائم على الخطط لمنصة مشتركة.')) ?></h2>
|
||||
</div>
|
||||
<a class="link-dark fw-semibold text-decoration-none" href="<?= h(app_url('pricing.php')) ?>"><?= h(t('Open pricing', 'افتح التسعير')) ?></a>
|
||||
</div>
|
||||
|
||||
160
patch_admin.py
160
patch_admin.py
@ -1,160 +0,0 @@
|
||||
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")
|
||||
@ -1,51 +0,0 @@
|
||||
<?php
|
||||
$content = file_get_contents('includes/app.php');
|
||||
|
||||
$helper = <<<'EOD'
|
||||
function get_platform_profile(): array {
|
||||
static $profile = null;
|
||||
if ($profile === null) {
|
||||
$stmt = db()->query("SELECT * FROM platform_profile WHERE id = 1");
|
||||
$profile = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$profile) {
|
||||
$profile = ['name' => 'LMS Platform', 'description' => '', 'logo_path' => '', 'favicon_path' => ''];
|
||||
}
|
||||
}
|
||||
return $profile;
|
||||
}
|
||||
|
||||
EOD;
|
||||
|
||||
if (strpos($content, 'function get_platform_profile()') === false) {
|
||||
$content = str_replace('function app_name(): string', $helper . 'function app_name(): string', $content);
|
||||
}
|
||||
|
||||
// Update app_name() to use profile if exists
|
||||
$app_name_new = <<<'EOD'
|
||||
function app_name(): string
|
||||
{
|
||||
$prof = get_platform_profile();
|
||||
if (!empty($prof['name'])) {
|
||||
return trim($prof['name']);
|
||||
}
|
||||
return trim((string) ($_SERVER['PROJECT_NAME'] ?? 'Aula')) ?: 'Aula';
|
||||
}
|
||||
EOD;
|
||||
|
||||
$content = preg_replace('/function app_name\(\): string\s*\{[^}]+\}/s', $app_name_new, $content);
|
||||
|
||||
// Update render_head() to add favicon support
|
||||
$render_head_old = '<title><?= h(page_title($title)) ?></title>';
|
||||
$render_head_new = <<<'EOD'
|
||||
<title><?= h(page_title($title)) ?></title>
|
||||
<?php
|
||||
$prof = get_platform_profile();
|
||||
if (!empty($prof['favicon_path'])):
|
||||
?>
|
||||
<link rel="icon" href="<?= h(asset_url($prof['favicon_path'])) ?>" />
|
||||
<?php endif; ?>
|
||||
EOD;
|
||||
$content = str_replace($render_head_old, $render_head_new, $content);
|
||||
|
||||
file_put_contents('includes/app.php', $content);
|
||||
echo "Patched includes/app.php\n";
|
||||
@ -1,29 +0,0 @@
|
||||
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")
|
||||
Loading…
x
Reference in New Issue
Block a user