Initial dev export (exclude uploads/runtime)
This commit is contained in:
255
modules/pages/PagesController.php
Normal file
255
modules/pages/PagesController.php
Normal file
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\Pages;
|
||||
|
||||
use Core\Http\Response;
|
||||
use Core\Services\Auth;
|
||||
use Core\Services\Database;
|
||||
use Core\Services\Shortcodes;
|
||||
use Core\Views\View;
|
||||
use PDO;
|
||||
use Throwable;
|
||||
|
||||
class PagesController
|
||||
{
|
||||
private View $view;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->view = new View(__DIR__ . '/views');
|
||||
}
|
||||
|
||||
public function show(): Response
|
||||
{
|
||||
$slug = trim((string)($_GET['slug'] ?? ''));
|
||||
if ($slug === '') {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
$db = Database::get();
|
||||
if (!$db instanceof PDO) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT title, content_html FROM ac_pages WHERE slug = :slug AND is_published = 1 LIMIT 1");
|
||||
$stmt->execute([':slug' => $slug]);
|
||||
$page = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$page) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
return new Response($this->view->render('site/show.php', [
|
||||
'title' => (string)$page['title'],
|
||||
'content_html' => Shortcodes::render((string)$page['content_html'], [
|
||||
'page_slug' => $slug,
|
||||
'page_title' => (string)$page['title'],
|
||||
]),
|
||||
]));
|
||||
}
|
||||
|
||||
public function adminIndex(): Response
|
||||
{
|
||||
if ($guard = $this->guard(['admin', 'manager', 'editor'])) {
|
||||
return $guard;
|
||||
}
|
||||
|
||||
$db = Database::get();
|
||||
$pages = [];
|
||||
if ($db instanceof PDO) {
|
||||
try {
|
||||
$stmt = $db->query("SELECT id, title, slug, is_published, is_home, is_blog_index, updated_at FROM ac_pages ORDER BY updated_at DESC");
|
||||
$pages = $stmt ? $stmt->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
} catch (Throwable $e) {
|
||||
$pages = [];
|
||||
}
|
||||
}
|
||||
|
||||
return new Response($this->view->render('admin/index.php', [
|
||||
'title' => 'Pages',
|
||||
'pages' => $pages,
|
||||
]));
|
||||
}
|
||||
|
||||
public function adminEdit(): Response
|
||||
{
|
||||
if ($guard = $this->guard(['admin', 'manager', 'editor'])) {
|
||||
return $guard;
|
||||
}
|
||||
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$page = [
|
||||
'id' => 0,
|
||||
'title' => '',
|
||||
'slug' => '',
|
||||
'content_html' => '',
|
||||
'is_published' => 0,
|
||||
'is_home' => 0,
|
||||
'is_blog_index' => 0,
|
||||
];
|
||||
|
||||
$db = Database::get();
|
||||
if ($id > 0 && $db instanceof PDO) {
|
||||
$stmt = $db->prepare("SELECT id, title, slug, content_html, is_published, is_home, is_blog_index FROM ac_pages WHERE id = :id LIMIT 1");
|
||||
$stmt->execute([':id' => $id]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if ($row) {
|
||||
$page = $row;
|
||||
}
|
||||
}
|
||||
|
||||
return new Response($this->view->render('admin/edit.php', [
|
||||
'title' => $id > 0 ? 'Edit Page' : 'New Page',
|
||||
'page' => $page,
|
||||
'error' => '',
|
||||
]));
|
||||
}
|
||||
|
||||
public function adminSave(): Response
|
||||
{
|
||||
if ($guard = $this->guard(['admin', 'manager', 'editor'])) {
|
||||
return $guard;
|
||||
}
|
||||
|
||||
$db = Database::get();
|
||||
if (!$db instanceof PDO) {
|
||||
return new Response('', 302, ['Location' => '/admin/pages']);
|
||||
}
|
||||
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
$title = trim((string)($_POST['title'] ?? ''));
|
||||
$slug = trim((string)($_POST['slug'] ?? ''));
|
||||
$content = (string)($_POST['content_html'] ?? '');
|
||||
$isPublished = isset($_POST['is_published']) ? 1 : 0;
|
||||
$isHome = isset($_POST['is_home']) ? 1 : 0;
|
||||
$isBlogIndex = isset($_POST['is_blog_index']) ? 1 : 0;
|
||||
|
||||
if ($title === '') {
|
||||
return $this->renderEditError($id, $title, $slug, $content, $isPublished, $isHome, $isBlogIndex, 'Title is required.');
|
||||
}
|
||||
|
||||
if ($slug === '') {
|
||||
$slug = $this->slugify($title);
|
||||
} else {
|
||||
$slug = $this->slugify($slug);
|
||||
}
|
||||
|
||||
try {
|
||||
if ($id > 0) {
|
||||
$chk = $db->prepare("SELECT id FROM ac_pages WHERE slug = :slug AND id != :id LIMIT 1");
|
||||
$chk->execute([':slug' => $slug, ':id' => $id]);
|
||||
} else {
|
||||
$chk = $db->prepare("SELECT id FROM ac_pages WHERE slug = :slug LIMIT 1");
|
||||
$chk->execute([':slug' => $slug]);
|
||||
}
|
||||
if ($chk->fetch()) {
|
||||
return $this->renderEditError($id, $title, $slug, $content, $isPublished, $isHome, $isBlogIndex, 'Slug already exists.');
|
||||
}
|
||||
|
||||
if ($isHome === 1) {
|
||||
$db->exec("UPDATE ac_pages SET is_home = 0");
|
||||
}
|
||||
if ($isBlogIndex === 1) {
|
||||
$db->exec("UPDATE ac_pages SET is_blog_index = 0");
|
||||
}
|
||||
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare("
|
||||
UPDATE ac_pages
|
||||
SET title = :title, slug = :slug, content_html = :content,
|
||||
is_published = :published, is_home = :is_home, is_blog_index = :is_blog_index
|
||||
WHERE id = :id
|
||||
");
|
||||
$stmt->execute([
|
||||
':title' => $title,
|
||||
':slug' => $slug,
|
||||
':content' => $content,
|
||||
':published' => $isPublished,
|
||||
':is_home' => $isHome,
|
||||
':is_blog_index' => $isBlogIndex,
|
||||
':id' => $id,
|
||||
]);
|
||||
} else {
|
||||
$stmt = $db->prepare("
|
||||
INSERT INTO ac_pages (title, slug, content_html, is_published, is_home, is_blog_index)
|
||||
VALUES (:title, :slug, :content, :published, :is_home, :is_blog_index)
|
||||
");
|
||||
$stmt->execute([
|
||||
':title' => $title,
|
||||
':slug' => $slug,
|
||||
':content' => $content,
|
||||
':published' => $isPublished,
|
||||
':is_home' => $isHome,
|
||||
':is_blog_index' => $isBlogIndex,
|
||||
]);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
return $this->renderEditError($id, $title, $slug, $content, $isPublished, $isHome, $isBlogIndex, 'Unable to save page.');
|
||||
}
|
||||
|
||||
return new Response('', 302, ['Location' => '/admin/pages']);
|
||||
}
|
||||
|
||||
public function adminDelete(): Response
|
||||
{
|
||||
if ($guard = $this->guard(['admin', 'manager'])) {
|
||||
return $guard;
|
||||
}
|
||||
$db = Database::get();
|
||||
if (!$db instanceof PDO) {
|
||||
return new Response('', 302, ['Location' => '/admin/pages']);
|
||||
}
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare("DELETE FROM ac_pages WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
}
|
||||
return new Response('', 302, ['Location' => '/admin/pages']);
|
||||
}
|
||||
|
||||
private function renderEditError(int $id, string $title, string $slug, string $content, int $isPublished, int $isHome, int $isBlogIndex, string $error): Response
|
||||
{
|
||||
$page = [
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
'slug' => $slug,
|
||||
'content_html' => $content,
|
||||
'is_published' => $isPublished,
|
||||
'is_home' => $isHome,
|
||||
'is_blog_index' => $isBlogIndex,
|
||||
];
|
||||
return new Response($this->view->render('admin/edit.php', [
|
||||
'title' => $id > 0 ? 'Edit Page' : 'New Page',
|
||||
'page' => $page,
|
||||
'error' => $error,
|
||||
]));
|
||||
}
|
||||
|
||||
private function notFound(): Response
|
||||
{
|
||||
$view = new View();
|
||||
return new Response($view->render('site/404.php', [
|
||||
'title' => 'Not Found',
|
||||
'message' => 'Page not found.',
|
||||
]), 404);
|
||||
}
|
||||
|
||||
private function slugify(string $value): string
|
||||
{
|
||||
$value = strtolower(trim($value));
|
||||
$value = preg_replace('~[^a-z0-9]+~', '-', $value) ?? $value;
|
||||
$value = trim($value, '-');
|
||||
return $value !== '' ? $value : 'page';
|
||||
}
|
||||
|
||||
private function guard(array $roles): ?Response
|
||||
{
|
||||
if (!Auth::check()) {
|
||||
return new Response('', 302, ['Location' => '/admin/login']);
|
||||
}
|
||||
if (!Auth::hasRole($roles)) {
|
||||
return new Response('', 302, ['Location' => '/admin']);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
18
modules/pages/module.php
Normal file
18
modules/pages/module.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Core\Http\Router;
|
||||
use Modules\Pages\PagesController;
|
||||
|
||||
require_once __DIR__ . '/PagesController.php';
|
||||
|
||||
return function (Router $router): void {
|
||||
$controller = new PagesController();
|
||||
$router->get('/page', [$controller, 'show']);
|
||||
|
||||
$router->get('/admin/pages', [$controller, 'adminIndex']);
|
||||
$router->get('/admin/pages/new', [$controller, 'adminEdit']);
|
||||
$router->get('/admin/pages/edit', [$controller, 'adminEdit']);
|
||||
$router->post('/admin/pages/save', [$controller, 'adminSave']);
|
||||
$router->post('/admin/pages/delete', [$controller, 'adminDelete']);
|
||||
};
|
||||
122
modules/pages/views/admin/edit.php
Normal file
122
modules/pages/views/admin/edit.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
$pageTitle = $title ?? 'Edit Page';
|
||||
$page = $page ?? [];
|
||||
$error = $error ?? '';
|
||||
ob_start();
|
||||
?>
|
||||
<section class="admin-card">
|
||||
<div class="badge">Pages</div>
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; gap:16px; margin-top:16px;">
|
||||
<div>
|
||||
<h1 style="font-size:28px; margin:0;"><?= htmlspecialchars($pageTitle, ENT_QUOTES, 'UTF-8') ?></h1>
|
||||
<p style="color: var(--muted); margin-top:6px;">Create a custom page for the site.</p>
|
||||
</div>
|
||||
<a href="/admin/pages" class="btn outline">Back</a>
|
||||
</div>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div style="margin-top:16px; color:#f3b0b0; font-size:13px;"><?= htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post" action="/admin/pages/save" style="margin-top:18px; display:grid; gap:16px;">
|
||||
<input type="hidden" name="id" value="<?= (int)($page['id'] ?? 0) ?>">
|
||||
<div class="admin-card" style="padding:16px;">
|
||||
<div style="display:grid; gap:12px;">
|
||||
<label class="label">Title</label>
|
||||
<input class="input" name="title" value="<?= htmlspecialchars((string)($page['title'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" placeholder="About">
|
||||
<label class="label">Slug</label>
|
||||
<input class="input" name="slug" value="<?= htmlspecialchars((string)($page['slug'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" placeholder="about">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; gap:12px;">
|
||||
<label class="label" style="margin:0;">Content (HTML)</label>
|
||||
<button type="button" class="btn outline small" data-media-picker="content_html">Insert Media</button>
|
||||
</div>
|
||||
<textarea class="input" name="content_html" id="content_html" rows="18" style="resize:vertical; font-family:'IBM Plex Mono', monospace; font-size:13px; line-height:1.6;"></textarea>
|
||||
<label style="display:flex; align-items:center; gap:8px; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:0.2em;">
|
||||
<input type="checkbox" name="is_published" value="1" <?= ((int)($page['is_published'] ?? 0) === 1) ? 'checked' : '' ?>>
|
||||
Published
|
||||
</label>
|
||||
<label style="display:flex; align-items:center; gap:8px; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:0.2em;">
|
||||
<input type="checkbox" name="is_home" value="1" <?= ((int)($page['is_home'] ?? 0) === 1) ? 'checked' : '' ?>>
|
||||
Set as Home Page
|
||||
</label>
|
||||
<label style="display:flex; align-items:center; gap:8px; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:0.2em;">
|
||||
<input type="checkbox" name="is_blog_index" value="1" <?= ((int)($page['is_blog_index'] ?? 0) === 1) ? 'checked' : '' ?>>
|
||||
Set as Blog Page
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex; justify-content:flex-end; gap:12px; align-items:center;">
|
||||
<button type="button" id="previewPage" class="btn outline">Preview</button>
|
||||
<button type="submit" class="btn">Save page</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php if (!empty($page['id'])): ?>
|
||||
<form method="post" action="/admin/pages/delete" onsubmit="return confirm('Delete this page?');" style="margin-top:12px;">
|
||||
<input type="hidden" name="id" value="<?= (int)($page['id'] ?? 0) ?>">
|
||||
<button type="submit" class="btn outline">Delete</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
<script>
|
||||
(function () {
|
||||
const inputEl = document.getElementById('content_html');
|
||||
const previewBtn = document.getElementById('previewPage');
|
||||
if (!inputEl || !previewBtn) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rawHtml = <?=
|
||||
json_encode((string)($page['content_html'] ?? ''), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT)
|
||||
?>;
|
||||
inputEl.value = rawHtml || '';
|
||||
|
||||
previewBtn.addEventListener('click', function () {
|
||||
const previewWindow = window.open('', 'pagePreview', 'width=1200,height=800');
|
||||
if (!previewWindow) {
|
||||
return;
|
||||
}
|
||||
const html = inputEl.value || '';
|
||||
const doc = previewWindow.document;
|
||||
doc.open();
|
||||
doc.write(`<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Page Preview</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Syne', sans-serif;
|
||||
background-color: #14151a;
|
||||
color: #f5f7ff;
|
||||
}
|
||||
.shell { max-width: 1080px; margin: 0 auto; padding: 32px 24px 64px; }
|
||||
.card {
|
||||
border-radius: 24px;
|
||||
background: rgba(20, 22, 28, 0.75);
|
||||
border: 1px solid rgba(255,255,255,0.12);
|
||||
box-shadow: 0 20px 50px rgba(0,0,0,0.3);
|
||||
padding: 28px;
|
||||
}
|
||||
a { color: #9ad4ff; }
|
||||
</style>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@500;600;700&family=IBM+Plex+Mono:wght@400;600&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<section class="card">
|
||||
${html}
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>`);
|
||||
doc.close();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
require __DIR__ . '/../../../admin/views/layout.php';
|
||||
42
modules/pages/views/admin/home.php
Normal file
42
modules/pages/views/admin/home.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
$pageTitle = 'Home Page';
|
||||
$page = $page ?? [];
|
||||
$saved = ($saved ?? '') === '1';
|
||||
ob_start();
|
||||
?>
|
||||
<section class="admin-card">
|
||||
<div class="badge">Home</div>
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; gap:16px; margin-top:16px;">
|
||||
<div>
|
||||
<h1 style="font-size:28px; margin:0;">Home Page</h1>
|
||||
<p style="color: var(--muted); margin-top:6px;">Edit the front page content. Leave title blank to hide it.</p>
|
||||
</div>
|
||||
<a href="/" class="btn outline small">View site</a>
|
||||
</div>
|
||||
|
||||
<?php if ($saved): ?>
|
||||
<div style="margin-top:16px; color:var(--accent-2); font-size:13px;">Home page updated.</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post" action="/admin/home/save" style="margin-top:18px; display:grid; gap:16px;">
|
||||
<div class="admin-card" style="padding:16px;">
|
||||
<div style="display:grid; gap:12px;">
|
||||
<label class="label">Title</label>
|
||||
<input class="input" name="title" value="<?= htmlspecialchars((string)($page['title'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" placeholder="AudioCore">
|
||||
<label class="label">Content (HTML)</label>
|
||||
<textarea class="input" name="content_html" rows="12" style="resize:vertical;"><?= htmlspecialchars((string)($page['content_html'] ?? ''), ENT_QUOTES, 'UTF-8') ?></textarea>
|
||||
<label style="display:flex; align-items:center; gap:8px; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:0.2em;">
|
||||
<input type="checkbox" name="is_published" value="1" <?= ((int)($page['is_published'] ?? 0) === 1) ? 'checked' : '' ?>>
|
||||
Published
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex; justify-content:flex-end;">
|
||||
<button type="submit" class="btn">Save home page</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
require __DIR__ . '/../../../admin/views/layout.php';
|
||||
58
modules/pages/views/admin/index.php
Normal file
58
modules/pages/views/admin/index.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
$pageTitle = 'Pages';
|
||||
$pages = $pages ?? [];
|
||||
ob_start();
|
||||
?>
|
||||
<section class="admin-card">
|
||||
<div class="badge">Pages</div>
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; gap:16px; margin-top:16px;">
|
||||
<div>
|
||||
<h1 style="font-size:28px; margin:0;">Pages</h1>
|
||||
<p style="color: var(--muted); margin-top:6px;">Manage custom content pages.</p>
|
||||
</div>
|
||||
<a href="/admin/pages/new" class="btn small">New Page</a>
|
||||
</div>
|
||||
|
||||
<div style="margin-top:18px; display:grid; gap:10px;">
|
||||
<div style="display:grid; grid-template-columns: 2fr 1fr 120px 120px 120px 160px 120px; gap:12px; font-size:11px; color:var(--muted); text-transform:uppercase; letter-spacing:0.2em;">
|
||||
<div>Title</div>
|
||||
<div>Slug</div>
|
||||
<div>Status</div>
|
||||
<div>Home</div>
|
||||
<div>Blog</div>
|
||||
<div>Updated</div>
|
||||
<div>Actions</div>
|
||||
</div>
|
||||
<?php if (!$pages): ?>
|
||||
<div style="color: var(--muted); font-size:13px;">No pages yet.</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($pages as $page): ?>
|
||||
<div style="display:grid; grid-template-columns: 2fr 1fr 120px 120px 120px 160px 120px; gap:12px; align-items:center; padding:10px 12px; border-radius:16px; border:1px solid var(--stroke); background: rgba(14,14,16,0.9);">
|
||||
<div style="font-weight:600;"><?= htmlspecialchars((string)($page['title'] ?? ''), ENT_QUOTES, 'UTF-8') ?></div>
|
||||
<div style="font-size:12px; color:var(--muted); font-family: 'IBM Plex Mono', monospace;">
|
||||
<?= htmlspecialchars((string)($page['slug'] ?? ''), ENT_QUOTES, 'UTF-8') ?>
|
||||
</div>
|
||||
<div style="font-size:12px; color:<?= ((int)($page['is_published'] ?? 0) === 1) ? 'var(--accent-2)' : 'var(--muted)' ?>;">
|
||||
<?= ((int)($page['is_published'] ?? 0) === 1) ? 'Published' : 'Draft' ?>
|
||||
</div>
|
||||
<div style="font-size:12px; color:<?= ((int)($page['is_home'] ?? 0) === 1) ? 'var(--accent-2)' : 'var(--muted)' ?>;">
|
||||
<?= ((int)($page['is_home'] ?? 0) === 1) ? 'Yes' : 'No' ?>
|
||||
</div>
|
||||
<div style="font-size:12px; color:<?= ((int)($page['is_blog_index'] ?? 0) === 1) ? 'var(--accent-2)' : 'var(--muted)' ?>;">
|
||||
<?= ((int)($page['is_blog_index'] ?? 0) === 1) ? 'Yes' : 'No' ?>
|
||||
</div>
|
||||
<div style="font-size:12px; color:var(--muted);">
|
||||
<?= htmlspecialchars((string)($page['updated_at'] ?? ''), ENT_QUOTES, 'UTF-8') ?>
|
||||
</div>
|
||||
<div style="display:flex; gap:8px;">
|
||||
<a href="/admin/pages/edit?id=<?= (int)$page['id'] ?>" class="btn outline small">Edit</a>
|
||||
<a href="/<?= htmlspecialchars((string)($page['slug'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" class="btn outline small">View</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
require __DIR__ . '/../../../admin/views/layout.php';
|
||||
13
modules/pages/views/site/show.php
Normal file
13
modules/pages/views/site/show.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
$pageTitle = $title ?? 'Page';
|
||||
$contentHtml = $content_html ?? '';
|
||||
ob_start();
|
||||
?>
|
||||
<section class="card">
|
||||
<div style="margin-top:14px; color:var(--muted); line-height:1.8;">
|
||||
<?= $contentHtml ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
require __DIR__ . '/../../../../views/site/layout.php';
|
||||
Reference in New Issue
Block a user