View Source

The actual code behind this page. No minification. No transpilation. What you see is what runs.

↓ Download PHP edition
categories.php 147 lines
<?php
require_once __DIR__ . '/includes/config.php';
$CATS_DIR = __DIR__ . '/categories';
// ── Helpers ───────────────────────────────────────────────────────────────────
function parseArticleDate(string $path): int
{
$fh = fopen($path, 'r');
if ($fh === false) return (int)filemtime($path);
$first = fgets($fh);
fclose($fh);
$pos = strpos($first, 'date=');
if ($pos !== false) {
$d = substr($first, $pos + 5, 8);
if (strlen($d) === 8 && ctype_digit($d)) {
return mktime(0, 0, 0, (int)substr($d, 4, 2), (int)substr($d, 6, 2), (int)substr($d, 0, 4));
}
}
return (int)filemtime($path);
}
function articleContent(string $path): string
{
$lines = file($path, FILE_IGNORE_NEW_LINES);
$out = [];
foreach ($lines as $line) {
if (str_starts_with(trim($line), '<!--date=')) continue;
$out[] = $line;
}
return trim(implode("\n", $out));
}
function listCategories(string $dir): array
{
if (!is_dir($dir)) return [];
$cats = [];
foreach (array_diff(scandir($dir), ['.', '..']) as $name) {
if (!is_dir("$dir/$name")) continue;
$count = count(glob("$dir/$name/*.php") ?: []);
$cats[] = ['name' => $name, 'count' => $count];
}
usort($cats, fn($a, $b) => strcmp($a['name'], $b['name']));
return $cats;
}
function listArticles(string $dir, string $cat): array
{
$files = glob("$dir/$cat/*.php") ?: [];
$arts = [];
foreach ($files as $path) {
$arts[] = [
'name' => basename($path, '.php'),
'date' => parseArticleDate($path),
];
}
usort($arts, fn($a, $b) => $b['date'] - $a['date']);
return $arts;
}
// ── Routing ───────────────────────────────────────────────────────────────────
$cat = isset($_GET['cat']) ? basename(trim($_GET['cat'])) : '';
$article = isset($_GET['article']) ? basename(trim($_GET['article'])) : '';
if ($cat && !is_dir("$CATS_DIR/$cat")) $cat = $article = '';
if ($cat && $article && !file_exists("$CATS_DIR/$cat/$article.php")) $article = '';
if (!$cat) $article = '';
// ── Page meta ─────────────────────────────────────────────────────────────────
$pageTitle = $article ? "$article — dispelled.ca"
: ($cat ? "$cat — dispelled.ca"
: 'Articles — dispelled.ca');
$currentPage = 'articles';
require_once __DIR__ . '/includes/header.php';
?>
<?php if ($article): ?>
<?php
$content = articleContent("$CATS_DIR/$cat/$article.php");
$date = parseArticleDate("$CATS_DIR/$cat/$article.php");
?>
<nav class="breadcrumb" aria-label="Breadcrumb">
<a href="<?= BASE_PATH ?>/categories.php">Articles</a>
<span>›</span>
<a href="<?= BASE_PATH ?>/categories.php?cat=<?= urlencode($cat) ?>"><?= htmlspecialchars($cat) ?></a>
<span>›</span>
<span><?= htmlspecialchars($article) ?></span>
</nav>
 
<div class="article-date"><?= date('F j, Y', $date) ?></div>
<div class="article-content prose-block">
<?= $content ?>
</div>
 
<?php elseif ($cat): ?>
<?php $arts = listArticles($CATS_DIR, $cat); ?>
<nav class="breadcrumb" aria-label="Breadcrumb">
<a href="<?= BASE_PATH ?>/categories.php">Articles</a>
<span>›</span>
<span><?= htmlspecialchars($cat) ?></span>
</nav>
 
<h1 class="page-title"><?= htmlspecialchars($cat) ?></h1>
 
<?php if (empty($arts)): ?>
<p style="color:var(--text-muted);font-family:var(--font-mono);font-size:.85rem;">No articles yet.</p>
<?php else: ?>
<ul class="article-list">
<?php foreach ($arts as $a): ?>
<li class="article-row">
<a href="<?= BASE_PATH ?>/categories.php?cat=<?= urlencode($cat) ?>&article=<?= urlencode($a['name']) ?>">
<?= htmlspecialchars($a['name']) ?>
</a>
<time class="article-row-date"><?= date('M j, Y', $a['date']) ?></time>
</li>
<?php endforeach ?>
</ul>
<?php endif ?>
<?php else: ?>
<?php $cats = listCategories($CATS_DIR); ?>
<h1 class="page-title">Articles</h1>
 
<?php if (empty($cats)): ?>
<p style="color:var(--text-muted);font-family:var(--font-mono);font-size:.85rem;">No categories yet.</p>
<?php else: ?>
<div class="cat-grid">
<?php foreach ($cats as $c): ?>
<a href="<?= BASE_PATH ?>/categories.php?cat=<?= urlencode($c['name']) ?>" class="cat-card">
<p class="cat-name"><?= htmlspecialchars($c['name']) ?></p>
<p class="cat-count"><?= $c['count'] ?> <?= $c['count'] === 1 ? 'article' : 'articles' ?></p>
</a>
<?php endforeach ?>
</div>
<?php endif ?>
<?php endif ?>
<?php require_once __DIR__ . '/includes/footer.php'; ?>