Autosave: 20260307-182614

This commit is contained in:
Flatlogic Bot 2026-03-07 18:26:14 +00:00
parent 890ce0acd2
commit 9e5fb665e5
11 changed files with 692 additions and 24 deletions

256
admin_faqs.php Normal file
View File

@ -0,0 +1,256 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php';
$errors = [];
$flash = null;
$editFaqId = isset($_GET['edit_faq']) ? (int)$_GET['edit_faq'] : 0;
db()->exec("
CREATE TABLE IF NOT EXISTS faqs (
id INT AUTO_INCREMENT PRIMARY KEY,
question_en VARCHAR(255) NOT NULL,
answer_en TEXT NOT NULL,
question_ar VARCHAR(255) DEFAULT NULL,
answer_ar TEXT DEFAULT NULL,
sort_order INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
");
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['add_faq'])) {
$questionEn = trim($_POST['question_en'] ?? '');
$answerEn = trim($_POST['answer_en'] ?? '');
$questionAr = trim($_POST['question_ar'] ?? '');
$answerAr = trim($_POST['answer_ar'] ?? '');
$sortOrder = (int)($_POST['sort_order'] ?? 0);
if ($questionEn === '' || $answerEn === '') {
$errors[] = 'Question and Answer (English) are required.';
} else {
try {
$stmt = db()->prepare("INSERT INTO faqs (question_en, answer_en, question_ar, answer_ar, sort_order) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([
$questionEn,
$answerEn,
$questionAr !== '' ? $questionAr : null,
$answerAr !== '' ? $answerAr : null,
$sortOrder
]);
$flash = 'FAQ added successfully.';
} catch (Throwable $e) {
$errors[] = 'Failed to add FAQ: ' . $e->getMessage();
}
}
} elseif (isset($_POST['update_faq'])) {
$faqId = (int)($_POST['faq_id'] ?? 0);
$questionEn = trim($_POST['question_en'] ?? '');
$answerEn = trim($_POST['answer_en'] ?? '');
$questionAr = trim($_POST['question_ar'] ?? '');
$answerAr = trim($_POST['answer_ar'] ?? '');
$sortOrder = (int)($_POST['sort_order'] ?? 0);
if ($faqId <= 0 || $questionEn === '' || $answerEn === '') {
$errors[] = 'FAQ ID, Question, and Answer (English) are required.';
} else {
try {
$stmt = db()->prepare("UPDATE faqs SET question_en = ?, answer_en = ?, question_ar = ?, answer_ar = ?, sort_order = ? WHERE id = ?");
$stmt->execute([
$questionEn,
$answerEn,
$questionAr !== '' ? $questionAr : null,
$answerAr !== '' ? $answerAr : null,
$sortOrder,
$faqId
]);
$flash = 'FAQ updated successfully.';
$editFaqId = 0;
} catch (Throwable $e) {
$errors[] = 'Failed to update FAQ: ' . $e->getMessage();
}
}
} elseif (isset($_POST['delete_faq'])) {
$faqId = (int)($_POST['faq_id'] ?? 0);
if ($faqId <= 0) {
$errors[] = 'Invalid FAQ selected.';
} else {
try {
$stmt = db()->prepare("DELETE FROM faqs WHERE id = ?");
$stmt->execute([$faqId]);
$flash = 'FAQ deleted successfully.';
$editFaqId = 0;
} catch (Throwable $e) {
$errors[] = 'Failed to delete FAQ: ' . $e->getMessage();
}
}
}
}
$faqs = db()->query("SELECT * FROM faqs ORDER BY sort_order ASC, id DESC")->fetchAll();
$editingFaq = null;
if ($editFaqId > 0) {
foreach ($faqs as $faq) {
if ((int)$faq['id'] === $editFaqId) {
$editingFaq = $faq;
break;
}
}
}
render_header('Manage FAQs', 'admin');
?>
<div class="row g-4">
<div class="col-lg-3">
<?php render_admin_sidebar('faqs'); ?>
</div>
<div class="col-lg-9">
<div class="page-intro mb-4">
<h1 class="h3 mb-1">Frequently Asked Questions</h1>
<p class="text-muted mb-0">Manage the Q&A list displayed on the public FAQ page.</p>
</div>
<?php if ($flash): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?= e($flash) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($errors): ?>
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<?= e(implode(' ', $errors)) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($editingFaq): ?>
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-white border-bottom-0 pt-4 pb-0">
<h5 class="mb-0">Edit FAQ</h5>
</div>
<div class="card-body">
<form method="post" class="row g-3">
<input type="hidden" name="faq_id" value="<?= e((string)$editingFaq['id']) ?>">
<div class="col-md-6">
<label class="form-label" for="edit_question_en">Question (EN) <span class="text-danger">*</span></label>
<input id="edit_question_en" type="text" name="question_en" class="form-control" value="<?= e($editingFaq['question_en']) ?>" required>
</div>
<div class="col-md-6">
<label class="form-label" for="edit_question_ar">Question (AR)</label>
<input id="edit_question_ar" type="text" name="question_ar" class="form-control" value="<?= e((string)($editingFaq['question_ar'] ?? '')) ?>" dir="auto">
</div>
<div class="col-md-6">
<label class="form-label" for="edit_answer_en">Answer (EN) <span class="text-danger">*</span></label>
<textarea id="edit_answer_en" name="answer_en" class="form-control" rows="4" required><?= e($editingFaq['answer_en']) ?></textarea>
</div>
<div class="col-md-6">
<label class="form-label" for="edit_answer_ar">Answer (AR)</label>
<textarea id="edit_answer_ar" name="answer_ar" class="form-control" rows="4" dir="auto"><?= e((string)($editingFaq['answer_ar'] ?? '')) ?></textarea>
</div>
<div class="col-md-4">
<label class="form-label" for="edit_sort_order">Sort Order</label>
<input id="edit_sort_order" type="number" name="sort_order" class="form-control" value="<?= e((string)$editingFaq['sort_order']) ?>">
</div>
<div class="col-12 mt-4">
<button type="submit" name="update_faq" class="btn btn-primary px-4 me-2">Save Changes</button>
<a class="btn btn-outline-secondary px-4" href="<?= e(url_with_lang('admin_faqs.php')) ?>">Cancel</a>
</div>
</form>
</div>
</div>
<?php else: ?>
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-white border-bottom-0 pt-4 pb-0">
<h5 class="mb-0">Add New FAQ</h5>
</div>
<div class="card-body">
<form method="post" class="row g-3">
<div class="col-md-6">
<label class="form-label" for="question_en">Question (EN) <span class="text-danger">*</span></label>
<input id="question_en" type="text" name="question_en" class="form-control" required>
</div>
<div class="col-md-6">
<label class="form-label" for="question_ar">Question (AR)</label>
<input id="question_ar" type="text" name="question_ar" class="form-control" dir="auto">
</div>
<div class="col-md-6">
<label class="form-label" for="answer_en">Answer (EN) <span class="text-danger">*</span></label>
<textarea id="answer_en" name="answer_en" class="form-control" rows="3" required></textarea>
</div>
<div class="col-md-6">
<label class="form-label" for="answer_ar">Answer (AR)</label>
<textarea id="answer_ar" name="answer_ar" class="form-control" rows="3" dir="auto"></textarea>
</div>
<div class="col-md-4">
<label class="form-label" for="sort_order">Sort Order (Optional)</label>
<input id="sort_order" type="number" name="sort_order" class="form-control" value="0">
</div>
<div class="col-12 mt-4">
<button type="submit" name="add_faq" class="btn btn-primary px-4"><i class="bi bi-plus-circle me-2"></i>Add FAQ</button>
</div>
</form>
</div>
</div>
<?php endif; ?>
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom-0 pt-4 pb-3">
<h5 class="mb-0">Current FAQs</h5>
</div>
<div class="card-body p-0">
<?php if (!$faqs): ?>
<div class="text-center p-5 text-muted">
<i class="bi bi-question-circle display-4 mb-3 d-block text-secondary opacity-50"></i>
<p class="mb-0">No FAQs added yet.</p>
</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th class="ps-4">Sort</th>
<th>Question (EN)</th>
<th>Answer Extract</th>
<th class="text-end pe-4">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($faqs as $faq): ?>
<tr>
<td class="ps-4 text-muted"><small><?= e((string)$faq['sort_order']) ?></small></td>
<td class="fw-medium"><?= e($faq['question_en']) ?></td>
<td class="text-muted"><small><?= e(mb_strimwidth($faq['answer_en'], 0, 50, '...')) ?></small></td>
<td class="text-end pe-4">
<a class="btn btn-sm btn-light border me-1" href="<?= e(url_with_lang('admin_faqs.php', ['edit_faq' => (int)$faq['id']])) ?>" title="Edit">
<i class="bi bi-pencil"></i>
</a>
<form method="post" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this FAQ?');">
<input type="hidden" name="faq_id" value="<?= e((string)$faq['id']) ?>">
<button type="submit" name="delete_faq" class="btn btn-sm btn-light border text-danger" title="Delete">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php render_footer(); ?>

View File

@ -16,6 +16,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
'wablas_domain' => trim($_POST['wablas_domain'] ?? ''),
'wablas_api_token' => trim($_POST['wablas_api_token'] ?? ''),
'wablas_secret_key' => trim($_POST['wablas_secret_key'] ?? ''),
'smtp_host' => trim($_POST['smtp_host'] ?? ''),
'smtp_port' => trim($_POST['smtp_port'] ?? ''),
'smtp_secure' => trim($_POST['smtp_secure'] ?? ''),
'smtp_user' => trim($_POST['smtp_user'] ?? ''),
'smtp_pass' => trim($_POST['smtp_pass'] ?? ''),
'mail_from' => trim($_POST['mail_from'] ?? ''),
'mail_from_name' => trim($_POST['mail_from_name'] ?? ''),
];
if (empty($errors)) {
@ -35,6 +42,13 @@ $thawaniEnv = $settings['thawani_environment'] ?? 'test';
$wablasDomain = $settings['wablas_domain'] ?? '';
$wablasToken = $settings['wablas_api_token'] ?? '';
$wablasSecret = $settings['wablas_secret_key'] ?? '';
$smtpHost = $settings['smtp_host'] ?? '';
$smtpPort = $settings['smtp_port'] ?? '587';
$smtpSecure = $settings['smtp_secure'] ?? 'tls';
$smtpUser = $settings['smtp_user'] ?? '';
$smtpPass = $settings['smtp_pass'] ?? '';
$mailFrom = $settings['mail_from'] ?? '';
$mailFromName = $settings['mail_from_name'] ?? '';
render_header('Integrations', 'admin');
?>
@ -120,6 +134,58 @@ render_header('Integrations', 'admin');
</div>
</div>
<!-- SMTP Mail Gateway Panel -->
<div class="panel p-4 mb-4">
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-envelope me-2 text-danger" viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"/>
</svg>
SMTP Mail Settings
</h3>
<p class="text-muted small mb-4">Configure your SMTP server to send emails and system notifications.</p>
<div class="row g-4">
<div class="col-md-6">
<label class="form-label fw-bold">SMTP Host</label>
<input type="text" name="smtp_host" class="form-control" value="<?= e($smtpHost) ?>" placeholder="smtp.example.com">
</div>
<div class="col-md-3">
<label class="form-label fw-bold">SMTP Port</label>
<input type="number" name="smtp_port" class="form-control" value="<?= e($smtpPort) ?>" placeholder="587">
</div>
<div class="col-md-3">
<label class="form-label fw-bold">Security</label>
<select name="smtp_secure" class="form-select">
<option value="tls" <?= $smtpSecure === 'tls' ? 'selected' : '' ?>>TLS</option>
<option value="ssl" <?= $smtpSecure === 'ssl' ? 'selected' : '' ?>>SSL</option>
<option value="none" <?= $smtpSecure === 'none' || $smtpSecure === '' ? 'selected' : '' ?>>None</option>
</select>
</div>
<div class="col-md-6">
<label class="form-label fw-bold">SMTP Username</label>
<input type="text" name="smtp_user" class="form-control" value="<?= e($smtpUser) ?>" placeholder="user@example.com">
</div>
<div class="col-md-6">
<label class="form-label fw-bold">SMTP Password</label>
<input type="password" name="smtp_pass" class="form-control" value="<?= e($smtpPass) ?>" placeholder="••••••••">
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Mail From Address</label>
<input type="email" name="mail_from" class="form-control" value="<?= e($mailFrom) ?>" placeholder="noreply@example.com">
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Mail From Name</label>
<input type="text" name="mail_from_name" class="form-control" value="<?= e($mailFromName) ?>" placeholder="CargoLink System">
</div>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary px-5">Save Integrations</button>
</div>

View File

@ -0,0 +1,12 @@
<?php
require_once __DIR__ . '/../config.php';
try {
$pdo = db();
$pdo->exec("ALTER TABLE truck_owner_profiles ADD COLUMN bank_account VARCHAR(100) NULL AFTER plate_no;");
$pdo->exec("ALTER TABLE truck_owner_profiles ADD COLUMN bank_name VARCHAR(100) NULL AFTER bank_account;");
$pdo->exec("ALTER TABLE truck_owner_profiles ADD COLUMN bank_branch VARCHAR(100) NULL AFTER bank_name;");
echo "Columns added.\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}

64
faq.php Normal file
View File

@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php';
try {
// Check if table exists to avoid errors on first load before admin visits it
$tableExists = db()->query("SHOW TABLES LIKE 'faqs'")->rowCount() > 0;
if ($tableExists) {
$faqs = db()->query("SELECT * FROM faqs ORDER BY sort_order ASC, id DESC")->fetchAll();
} else {
$faqs = [];
}
} catch (Throwable $e) {
$faqs = [];
}
render_header('Frequently Asked Questions', 'home');
?>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-8 text-center mb-5">
<h1 class="display-5 fw-bold mb-3">Frequently Asked Questions</h1>
<p class="lead text-muted">Find answers to common questions about our platform and services.</p>
</div>
</div>
<div class="row justify-content-center">
<div class="col-lg-9">
<?php if (empty($faqs)): ?>
<div class="text-center p-5 bg-white rounded shadow-sm">
<i class="bi bi-info-circle display-4 text-muted mb-3 d-block"></i>
<p class="text-muted mb-0">No FAQs are currently available. Please check back later.</p>
</div>
<?php else: ?>
<div class="accordion accordion-flush shadow-sm bg-white rounded-3 p-3" id="faqAccordion">
<?php foreach ($faqs as $index => $faq):
$question = $lang === 'ar' && !empty($faq['question_ar']) ? $faq['question_ar'] : $faq['question_en'];
$answer = $lang === 'ar' && !empty($faq['answer_ar']) ? $faq['answer_ar'] : $faq['answer_en'];
$collapseId = 'collapse' . $faq['id'];
$headingId = 'heading' . $faq['id'];
?>
<div class="accordion-item border-0 border-bottom mb-2">
<h2 class="accordion-header" id="<?= e($headingId) ?>">
<button class="accordion-button collapsed fw-semibold fs-5 bg-transparent" type="button" data-bs-toggle="collapse" data-bs-target="#<?= e($collapseId) ?>" aria-expanded="false" aria-controls="<?= e($collapseId) ?>">
<?= e($question) ?>
</button>
</h2>
<div id="<?= e($collapseId) ?>" class="accordion-collapse collapse" aria-labelledby="<?= e($headingId) ?>" data-bs-parent="#faqAccordion">
<div class="accordion-body text-muted lh-lg">
<?= nl2br(e($answer)) ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
<?php render_footer(); ?>

View File

@ -223,6 +223,9 @@ SQL;
truck_type VARCHAR(120) NOT NULL,
load_capacity DECIMAL(10,2) NOT NULL,
plate_no VARCHAR(80) NOT NULL,
bank_account VARCHAR(100) NULL,
bank_name VARCHAR(100) NULL,
bank_branch VARCHAR(100) NULL,
id_card_path TEXT NOT NULL,
truck_pic_path VARCHAR(255) NOT NULL,
registration_path TEXT NOT NULL,

View File

@ -58,6 +58,11 @@ function render_header(string $title, string $active = ''): void
<?= e(t('nav_home')) ?>
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= $active === 'faq' ? 'active text-primary' : '' ?>" href="<?= e(url_with_lang('faq.php')) ?>">
FAQ
</a>
</li>
</ul>
<div class="d-flex align-items-center gap-3">
<div class="dropdown">
@ -151,7 +156,7 @@ function render_footer(): void
<div class="col-md-2">
<h6 class="fw-bold mb-3">Resources</h6>
<ul class="list-unstyled text-muted small">
<li class="mb-2"><a href="#" class="text-decoration-none text-muted">Help Center</a></li>
<li class="mb-2"><a href="<?= e(url_with_lang('faq.php')) ?>" class="text-decoration-none text-muted">Help Center / FAQ</a></li>
<li class="mb-2"><a href="#" class="text-decoration-none text-muted">Terms of Service</a></li>
<li class="mb-2"><a href="#" class="text-decoration-none text-muted">Privacy Policy</a></li>
</ul>
@ -184,6 +189,7 @@ function render_admin_sidebar(string $active = 'dashboard'): void
$settingsActive = in_array($active, ['company_profile', 'integrations']);
$locationsActive = in_array($active, ['countries', 'cities']);
$usersActive = in_array($active, ['shippers', 'truck_owners', 'register']);
$pagesActive = in_array($active, ['faqs']);
?>
<aside class="admin-sidebar panel p-4 shadow-sm border-0">
<h2 class="h5 fw-bold mb-4"><i class="bi bi-shield-lock me-2 text-primary"></i>Admin Panel</h2>
@ -239,6 +245,19 @@ function render_admin_sidebar(string $active = 'dashboard'): void
</a>
</div>
</div>
<a class="nav-link fw-bold text-muted text-uppercase mt-2 d-flex justify-content-between align-items-center p-2 rounded" style="cursor: pointer; font-size: 0.85rem;" data-bs-toggle="collapse" data-bs-target="#collapsePages" aria-expanded="<?= $pagesActive ? 'true' : 'false' ?>">
<span><i class="bi bi-file-earmark-text-fill me-2"></i>Pages</span>
<i class="bi bi-chevron-down small"></i>
</a>
<div class="collapse <?= $pagesActive ? 'show' : '' ?>" id="collapsePages">
<div class="nav flex-column gap-1 ms-3 border-start ps-2 border-2">
<a class="admin-nav-link <?= $active === 'faqs' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_faqs.php')) ?>">
<i class="bi bi-question-square me-2"></i>FAQs
</a>
</div>
</div>
</nav>
</aside>
<?php

View File

@ -216,6 +216,16 @@ render_header(t('app_name'), 'home');
</section>
<?php endif; ?>
<section class="mb-5 text-center">
<div class="panel p-5 border-0 shadow-sm rounded-4" style="background-color: #f8f9fa;">
<h2 class="display-6 fw-bold mb-3">Have Questions?</h2>
<p class="text-muted fs-5 mb-4 mx-auto" style="max-width: 600px;">Check out our Frequently Asked Questions to learn more about how our platform works.</p>
<a href="<?= e(url_with_lang('faq.php')) ?>" class="btn btn-primary btn-lg px-4 rounded-pill shadow-sm">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-question-circle me-2" viewBox="0 0 16 16"><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/><path d="M5.255 5.786a.237.237 0 0 0 .241.247h.825c.138 0 .248-.113.266-.25.09-.656.54-1.134 1.342-1.134.686 0 1.314.343 1.314 1.168 0 .635-.374.927-.965 1.371-.673.489-1.206 1.06-1.168 1.987l.003.217a.25.25 0 0 0 .25.246h.811a.25.25 0 0 0 .25-.25v-.105c0-.718.273-.927 1.01-1.486.609-.463 1.244-.977 1.244-2.056 0-1.511-1.276-2.241-2.673-2.241-1.267 0-2.655.59-2.75 2.286zm1.557 5.763c0 .533.425.927 1.01.927.609 0 1.028-.394 1.028-.927 0-.552-.42-.94-1.029-.94-.584 0-1.009.388-1.009.94z"/></svg>View FAQ
</a>
</div>
</section>
<div class="motivation-box mb-5">
<h3 class="display-6 fw-bold mb-3">Ready to transform your logistics?</h3>
<p class="fs-5 text-white-50 mb-4 mx-auto" style="max-width: 600px;">Join our platform today to find reliable trucks or secure the best shipments in the market.</p>

View File

@ -1,15 +1,12 @@
<?php
// Mail configuration sourced from environment variables.
// No secrets are stored here; the file just maps env -> config array for MailService.
// Mail configuration sourced from environment variables,
// falling back to database settings if configured.
function env_val(string $key, $default = null) {
$v = getenv($key);
return ($v === false || $v === null || $v === '') ? $default : $v;
}
// Fallback: if critical vars are missing from process env, try to parse executor/.env
// This helps in web/Apache contexts where .env is not exported.
// Supports simple KEY=VALUE lines; ignores quotes and comments.
function load_dotenv_if_needed(array $keys): void {
$missing = array_filter($keys, fn($k) => getenv($k) === false || getenv($k) === '');
if (empty($missing)) return;
@ -22,9 +19,7 @@ function load_dotenv_if_needed(array $keys): void {
if ($line[0] === '#' || trim($line) === '') continue;
if (!str_contains($line, '=')) continue;
[$k, $v] = array_map('trim', explode('=', $line, 2));
// Strip potential surrounding quotes
$v = trim($v, "\"' ");
// Do not override existing env
$v = trim($v, "'\" ");
if ($k !== '' && (getenv($k) === false || getenv($k) === '')) {
putenv("{$k}={$v}");
}
@ -39,15 +34,43 @@ load_dotenv_if_needed([
'DKIM_DOMAIN','DKIM_SELECTOR','DKIM_PRIVATE_KEY_PATH'
]);
$transport = env_val('MAIL_TRANSPORT', 'smtp');
$smtp_host = env_val('SMTP_HOST');
$smtp_port = (int) env_val('SMTP_PORT', 587);
$smtp_secure = env_val('SMTP_SECURE', 'tls'); // tls | ssl | null
$smtp_user = env_val('SMTP_USER');
$smtp_pass = env_val('SMTP_PASS');
// Attempt to load settings from DB safely
function get_mail_db_settings(): array {
$settings = [];
$dbPath = __DIR__ . '/../db/config.php';
if (file_exists($dbPath)) {
require_once $dbPath;
if (function_exists('db')) {
try {
$stmt = db()->query("SELECT setting_key, setting_value FROM settings");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$settings[$row['setting_key']] = $row['setting_value'];
}
} catch (Throwable $e) {
// Ignore DB errors if not initialized
}
}
}
return $settings;
}
$from_email = env_val('MAIL_FROM', 'no-reply@localhost');
$from_name = env_val('MAIL_FROM_NAME', 'App');
$dbSettings = get_mail_db_settings();
$transport = env_val('MAIL_TRANSPORT', 'smtp');
$smtp_host = !empty($dbSettings['smtp_host']) ? $dbSettings['smtp_host'] : env_val('SMTP_HOST');
$smtp_port = !empty($dbSettings['smtp_port']) ? (int)$dbSettings['smtp_port'] : (int) env_val('SMTP_PORT', 587);
$smtp_secure = isset($dbSettings['smtp_secure']) && $dbSettings['smtp_secure'] !== '' ? $dbSettings['smtp_secure'] : env_val('SMTP_SECURE', 'tls');
if (isset($dbSettings['smtp_secure']) && $dbSettings['smtp_secure'] === 'none') {
$smtp_secure = '';
}
if ($smtp_secure === 'none') $smtp_secure = ''; // Normalize None to empty for PHPMailer
$smtp_user = !empty($dbSettings['smtp_user']) ? $dbSettings['smtp_user'] : env_val('SMTP_USER');
$smtp_pass = !empty($dbSettings['smtp_pass']) ? $dbSettings['smtp_pass'] : env_val('SMTP_PASS');
$from_email = !empty($dbSettings['mail_from']) ? $dbSettings['mail_from'] : env_val('MAIL_FROM', 'no-reply@localhost');
$from_name = !empty($dbSettings['mail_from_name']) ? $dbSettings['mail_from_name'] : env_val('MAIL_FROM_NAME', 'App');
$reply_to = env_val('MAIL_REPLY_TO');
$dkim_domain = env_val('DKIM_DOMAIN');
@ -56,21 +79,15 @@ $dkim_private_key_path = env_val('DKIM_PRIVATE_KEY_PATH');
return [
'transport' => $transport,
// SMTP
'smtp_host' => $smtp_host,
'smtp_port' => $smtp_port,
'smtp_secure' => $smtp_secure,
'smtp_user' => $smtp_user,
'smtp_pass' => $smtp_pass,
// From / Reply-To
'from_email' => $from_email,
'from_name' => $from_name,
'reply_to' => $reply_to,
// DKIM (optional)
'dkim_domain' => $dkim_domain,
'dkim_selector' => $dkim_selector,
'dkim_private_key_path' => $dkim_private_key_path,
];
];

100
patch.py Normal file
View File

@ -0,0 +1,100 @@
import re
with open('register.php', 'r') as f:
content = f.read()
# 1
content = content.replace(" 'plate_no' => '',", " 'plate_no' => '',\n 'bank_account' => '',\n 'bank_name' => '',\n 'bank_branch' => '',")
# 2
content = content.replace(" 'plate_no' => trim($_POST['plate_no'] ?? ''),", " 'plate_no' => trim($_POST['plate_no'] ?? ''),\n 'bank_account' => trim($_POST['bank_account'] ?? ''),\n 'bank_name' => trim($_POST['bank_name'] ?? ''),\n 'bank_branch' => trim($_POST['bank_branch'] ?? ''),")
# 3
content = content.replace(" $plateNo = trim($_POST['plate_no'] ?? '');", " $plateNo = trim($_POST['plate_no'] ?? '');\n $bankAccount = trim($_POST['bank_account'] ?? '');\n $bankName = trim($_POST['bank_name'] ?? '');\n $bankBranch = trim($_POST['bank_branch'] ?? '');")
# 4
s4 = " if ($truckType === '' || $loadCapacity === '' || $plateNo === '') {\n $errors[] = 'Please complete truck details.';\n } elseif (!is_numeric($loadCapacity) || (float)$loadCapacity <= 0) {"
r4 = " if ($truckType === '' || $loadCapacity === '' || $plateNo === '') {\n $errors[] = 'Please complete truck details.';\n } elseif ($bankAccount === '' || $bankName === '' || $bankBranch === '') {\n $errors[] = 'Please complete bank account details.';\n } elseif (!is_numeric($loadCapacity) || (float)$loadCapacity <= 0) {"
content = content.replace(s4, r4)
# 5
s5 = " $ownerStmt = $pdo->prepare(
\"INSERT INTO truck_owner_profiles (user_id, phone, country_id, city_id, address_line, truck_type, load_capacity, plate_no, id_card_path, truck_pic_path, registration_path)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\"
);
$ownerStmt->execute([
$userId,
$phone,
$countryId,
$cityId,
$addressLine,
$truckType,
$loadCapacity,
$plateNo,
json_encode($idCardPaths, JSON_UNESCAPED_SLASHES),
$truckPic,
json_encode($regPaths, JSON_UNESCAPED_SLASHES),
]);"
r5 = " $ownerStmt = $pdo->prepare(
\"INSERT INTO truck_owner_profiles (user_id, phone, country_id, city_id, address_line, truck_type, load_capacity, plate_no, bank_account, bank_name, bank_branch, id_card_path, truck_pic_path, registration_path)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\"
);
$ownerStmt->execute([
$userId,
$phone,
$countryId,
$cityId,
$addressLine,
$truckType,
$loadCapacity,
$plateNo,
$bankAccount,
$bankName,
$bankBranch,
json_encode($idCardPaths, JSON_UNESCAPED_SLASHES),
$truckPic,
json_encode($regPaths, JSON_UNESCAPED_SLASHES),
]);"
content = content.replace(s5, r5)
# 6
s6 = " 'plate_no' => '',"
r6 = " 'plate_no' => '',\n 'bank_account' => '',\n 'bank_name' => '',\n 'bank_branch' => '',"
# careful not to replace the first one again
parts = content.split(s6)
if len(parts) == 3:
content = parts[0] + s6 + parts[1] + r6 + parts[2]
elif len(parts) == 2:
# meaning the first one was already replaced by s1/r1 (which is the same search string!)
# wait, s1 and s6 are exactly the same?
# No, s1 is " 'plate_no' => ''," and s6 is " 'plate_no' => ''," (more spaces)
content = parts[0] + r6 + parts[1]
# 7
s7 = " <div class=\"col-md-4\">
<label class=\"form-label\" for=\"plate_no\">Plate number</label>
<input type=\"text\" name=\"plate_no\" id=\"plate_no\" class=\"form-control\" value=\"<?= e($values['plate_no']) ?>\">
</div>"
r7 = " <div class=\"col-md-4\">
<label class=\"form-label\" for=\"plate_no\">Plate number</label>
<input type=\"text\" name=\"plate_no\" id=\"plate_no\" class=\"form-control\" value=\"<?= e($values['plate_no']) ?>\">
</div>
<h3 class=\"h6 mt-4 w-100\">Bank Details for Payouts</h3>
<div class=\"col-md-4 mt-2\">
<label class=\"form-label\" for=\"bank_account\">Bank Account / IBAN</label>
<input type=\"text\" name=\"bank_account\" id=\"bank_account\" class=\"form-control\" value=\"<?= e($values['bank_account']) ?>\" required>
</div>
<div class=\"col-md-4 mt-2\">
<label class=\"form-label\" for=\"bank_name\">Bank Name</label>
<input type=\"text\" name=\"bank_name\" id=\"bank_name\" class=\"form-control\" value=\"<?= e($values['bank_name']) ?>\" required>
</div>
<div class=\"col-md-4 mt-2\">
<label class=\"form-label\" for=\"bank_branch\">Branch</label>
<input type=\"text\" name=\"bank_branch\" id=\"bank_branch\" class=\"form-control\" value=\"<?= e($values['bank_branch']) ?>\" required>
</div>"
content = content.replace(s7, r7)
with open('register.php', 'w') as f:
f.write(content)
print("Replaced in register.php")

16
tmp_edit.php Normal file
View File

@ -0,0 +1,16 @@
<?php
$content = file_get_contents('includes/app.php');
$search = " plate_no VARCHAR(80) NOT NULL,
id_card_path TEXT NOT NULL,";
$replace = " plate_no VARCHAR(80) NOT NULL,
bank_account VARCHAR(100) NULL,
bank_name VARCHAR(100) NULL,
bank_branch VARCHAR(100) NULL,
id_card_path TEXT NOT NULL,";
if (strpos($content, $search) !== false) {
file_put_contents('includes/app.php', str_replace($search, $replace, $content));
echo "Replaced in includes/app.php\n";
} else {
echo "Search string not found\n";
}

105
tmp_reg_edit.php Normal file
View File

@ -0,0 +1,105 @@
<?php
$content = file_get_contents('register.php');
$s1 = " 'plate_no' => '',";
$r1 = " 'plate_no' => '',\n 'bank_account' => '',\n 'bank_name' => '',\n 'bank_branch' => '',";
$s2 = " 'plate_no' => trim(\"
$_POST['plate_no'] ?? ''\"),";
$r2 = " 'plate_no' => trim(\"
$_POST['plate_no'] ?? ''\"),\n 'bank_account' => trim(\"
$_POST['bank_account'] ?? ''\"),\n 'bank_name' => trim(\"
$_POST['bank_name'] ?? ''\"),\n 'bank_branch' => trim(\"
$_POST['bank_branch'] ?? ''\"),";
$s3 = " $plateNo = trim(\"
$_POST['plate_no'] ?? ''\");";
$r3 = " $plateNo = trim(\"
$_POST['plate_no'] ?? ''\");\n $bankAccount = trim(\"
$_POST['bank_account'] ?? ''\");\n $bankName = trim(\"
$_POST['bank_name'] ?? ''\");\n $bankBranch = trim(\"
$_POST['bank_branch'] ?? ''\");";
$s4 = " if ($truckType === '' || $loadCapacity === '' || $plateNo === '') {\n $errors[] = 'Please complete truck details.';\n } elseif (!is_numeric($loadCapacity) || (float)$loadCapacity <= 0) {";
$r4 = " if ($truckType === '' || $loadCapacity === '' || $plateNo === '') {\n $errors[] = 'Please complete truck details.';\n } elseif ($bankAccount === '' || $bankName === '' || $bankBranch === '') {\n $errors[] = 'Please complete bank account details.';\n } elseif (!is_numeric($loadCapacity) || (float)$loadCapacity <= 0) {";
$s5 = <<<PHP
$ownerStmt = $pdo->prepare(
"INSERT INTO truck_owner_profiles (user_id, phone, country_id, city_id, address_line, truck_type, load_capacity, plate_no, id_card_path, truck_pic_path, registration_path)"
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
$ownerStmt->execute([
$userId,
$phone,
$countryId,
$cityId,
$addressLine,
$truckType,
$loadCapacity,
$plateNo,
json_encode($idCardPaths, JSON_UNESCAPED_SLASHES),
$truckPic,
json_encode($regPaths, JSON_UNESCAPED_SLASHES),
]);
PHP;
$r5 = <<<PHP
$ownerStmt = $pdo->prepare(
"INSERT INTO truck_owner_profiles (user_id, phone, country_id, city_id, address_line, truck_type, load_capacity, plate_no, bank_account, bank_name, bank_branch, id_card_path, truck_pic_path, registration_path)"
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
$ownerStmt->execute([
$userId,
$phone,
$countryId,
$cityId,
$addressLine,
$truckType,
$loadCapacity,
$plateNo,
$bankAccount,
$bankName,
$bankBranch,
json_encode($idCardPaths, JSON_UNESCAPED_SLASHES),
$truckPic,
json_encode($regPaths, JSON_UNESCAPED_SLASHES),
]);
PHP;
$s7 = <<<HTML
<div class="col-md-4">
<label class="form-label" for="plate_no">Plate number</label>
<input type="text" name="plate_no" id="plate_no" class="form-control" value="<?= e($values['plate_no']) ?>">
</div>
HTML;
$r7 = <<<HTML
<div class="col-md-4">
<label class="form-label" for="plate_no">Plate number</label>
<input type="text" name="plate_no" id="plate_no" class="form-control" value="<?= e($values['plate_no']) ?>">
</div>
<h3 class="h6 mt-4 mb-2 w-100">Bank Details for Payouts</h3>
<div class="col-md-4 mt-2">
<label class="form-label" for="bank_account">Bank Account / IBAN</label>
<input type="text" name="bank_account" id="bank_account" class="form-control" value="<?= e($values['bank_account']) ?>">
</div>
<div class="col-md-4 mt-2">
<label class="form-label" for="bank_name">Bank Name</label>
<input type="text" name="bank_name" id="bank_name" class="form-control" value="<?= e($values['bank_name']) ?>">
</div>
<div class="col-md-4 mt-2">
<label class="form-label" for="bank_branch">Branch</label>
<input type="text" name="bank_branch" id="bank_branch" class="form-control" value="<?= e($values['bank_branch']) ?>">
</div>
HTML;
$content = str_replace($s1, $r1, $content);
$content = str_replace($s2, $r2, $content);
$content = str_replace($s3, $r3, $content);
$content = str_replace($s4, $r4, $content);
$content = str_replace($s5, $r5, $content);
$content = str_replace($s7, $r7, $content);
file_put_contents('register.php', $content);
echo "Replaced in register.php\n";