From 8a01d0bc996f55a065fdf88619f8656ba6d11947 Mon Sep 17 00:00:00 2001
From: Edwin Noorlander
Date: Wed, 19 Nov 2025 14:12:43 +0100
Subject: [PATCH] Fix e.noorlander branch - add missing PHP files to public
- Copied index.php, config.php, and templates to public/
- e.noorlander branch now works correctly
- Personal blog content accessible again
- All branches now have proper public directory structure
---
public/config.php | 16 ++
public/index.php | 365 +++++++++++++++++++++++++++++++++++
public/templates/layout.html | 313 ++++++++++++++++++++++++++++++
3 files changed, 694 insertions(+)
create mode 100644 public/config.php
create mode 100644 public/index.php
create mode 100644 public/templates/layout.html
diff --git a/public/config.php b/public/config.php
new file mode 100644
index 0000000..efde3e6
--- /dev/null
+++ b/public/config.php
@@ -0,0 +1,16 @@
+ 'CodePress',
+ 'site_description' => 'A simple PHP CMS',
+ 'base_url' => '/',
+ 'content_dir' => __DIR__ . '/public/content',
+ 'templates_dir' => __DIR__ . '/templates',
+ 'cache_dir' => __DIR__ . '/cache',
+ 'default_page' => 'home',
+ 'error_404' => '404',
+ 'markdown_enabled' => true,
+ 'php_enabled' => true,
+ 'bootstrap_version' => '5.3.0',
+ 'jquery_version' => '3.7.1'
+];
\ No newline at end of file
diff --git a/public/index.php b/public/index.php
new file mode 100644
index 0000000..4965702
--- /dev/null
+++ b/public/index.php
@@ -0,0 +1,365 @@
+config = $config;
+ $this->buildMenu();
+
+ if (isset($_GET['search'])) {
+ $this->performSearch($_GET['search']);
+ }
+ }
+
+ private function buildMenu() {
+ $this->menu = $this->scanDirectory($this->config['content_dir'], '');
+ }
+
+ private function scanDirectory($dir, $prefix) {
+ if (!is_dir($dir)) return [];
+
+ $items = scandir($dir);
+ sort($items);
+ $result = [];
+
+ foreach ($items as $item) {
+ if ($item[0] === '.') continue;
+
+ $path = $dir . '/' . $item;
+ $relativePath = $prefix ? $prefix . '/' . $item : $item;
+
+ if (is_dir($path)) {
+ $result[] = [
+ 'type' => 'folder',
+ 'title' => ucfirst($item),
+ 'path' => $relativePath,
+ 'children' => $this->scanDirectory($path, $relativePath)
+ ];
+ } elseif (preg_match('/\.(md|php|html)$/', $item)) {
+ $title = ucfirst(pathinfo($item, PATHINFO_FILENAME));
+ $result[] = [
+ 'type' => 'file',
+ 'title' => $title,
+ 'path' => $relativePath,
+ 'url' => '?page=' . $relativePath
+ ];
+ }
+ }
+
+ return $result;
+ }
+
+ private function performSearch($query) {
+ $this->searchResults = [];
+ $this->searchInDirectory($this->config['content_dir'], '', $query);
+ }
+
+ private function searchInDirectory($dir, $prefix, $query) {
+ if (!is_dir($dir)) return;
+
+ $items = scandir($dir);
+
+ foreach ($items as $item) {
+ if ($item[0] === '.') continue;
+
+ $path = $dir . '/' . $item;
+ $relativePath = $prefix ? $prefix . '/' . $item : $item;
+
+ if (is_dir($path)) {
+ $this->searchInDirectory($path, $relativePath, $query);
+} elseif (preg_match('/\.(md|php|html)$/', $item)) {
+ $content = file_get_contents($path);
+ if (stripos($content, $query) !== false || stripos($item, $query) !== false) {
+ $title = ucfirst(pathinfo($item, PATHINFO_FILENAME));
+ $this->searchResults[] = [
+ 'title' => $title,
+ 'path' => $relativePath,
+ 'url' => '?page=' . $relativePath,
+ 'snippet' => $this->createSnippet($content, $query)
+ ];
+ }
+ }
+ }
+ }
+
+ private function createSnippet($content, $query) {
+ $content = strip_tags($content);
+ $pos = stripos($content, $query);
+ if ($pos === false) return substr($content, 0, 100) . '...';
+
+ $start = max(0, $pos - 50);
+ $snippet = substr($content, $start, 150);
+ return '...' . $snippet . '...';
+ }
+
+ public function getPage() {
+ if (isset($_GET['search'])) {
+ return $this->getSearchResults();
+ }
+
+ $page = $_GET['page'] ?? $this->config['default_page'];
+ $page = preg_replace('/\.[^.]+$/', '', $page);
+
+ $filePath = $this->config['content_dir'] . '/' . $page;
+ $actualFilePath = null;
+
+ if (file_exists($filePath . '.md')) {
+ $actualFilePath = $filePath . '.md';
+ $result = $this->parseMarkdown(file_get_contents($actualFilePath));
+ } elseif (file_exists($filePath . '.php')) {
+ $actualFilePath = $filePath . '.php';
+ $result = $this->parsePHP($actualFilePath);
+ } elseif (file_exists($filePath . '.html')) {
+ $actualFilePath = $filePath . '.html';
+ $result = $this->parseHTML(file_get_contents($actualFilePath));
+ } elseif (file_exists($filePath)) {
+ $actualFilePath = $filePath;
+ $extension = pathinfo($filePath, PATHINFO_EXTENSION);
+ if ($extension === 'md') {
+ $result = $this->parseMarkdown(file_get_contents($actualFilePath));
+ } elseif ($extension === 'php') {
+ $result = $this->parsePHP($actualFilePath);
+ } elseif ($extension === 'html') {
+ $result = $this->parseHTML(file_get_contents($actualFilePath));
+ }
+ }
+
+ if (isset($result) && $actualFilePath) {
+ $result['file_info'] = $this->getFileInfo($actualFilePath);
+ return $result;
+ }
+
+ return $this->getError404();
+ }
+
+ private function getFileInfo($filePath) {
+ if (!file_exists($filePath)) {
+ return null;
+ }
+
+ $stats = stat($filePath);
+ $created = date('d-m-Y H:i', $stats['ctime']);
+ $modified = date('d-m-Y H:i', $stats['mtime']);
+
+ return [
+ 'created' => $created,
+ 'modified' => $modified,
+ 'size' => $this->formatFileSize($stats['size'])
+ ];
+ }
+
+ private function formatFileSize($bytes) {
+ $units = ['B', 'KB', 'MB', 'GB'];
+ $bytes = max($bytes, 0);
+ $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
+ $pow = min($pow, count($units) - 1);
+
+ $bytes /= pow(1024, $pow);
+
+ return round($bytes, 2) . ' ' . $units[$pow];
+ }
+
+ private function getSearchResults() {
+ $query = $_GET['search'];
+ $content = 'Search Results for: "' . htmlspecialchars($query) . '"
';
+
+ if (empty($this->searchResults)) {
+ $content .= 'No results found.
';
+ } else {
+ $content .= 'Found ' . count($this->searchResults) . ' results:
';
+ foreach ($this->searchResults as $result) {
+ $content .= '';
+ $content .= '
';
+ $content .= '
';
+ $content .= '
' . htmlspecialchars($result['path']) . '
';
+ $content .= '
' . htmlspecialchars($result['snippet']) . '
';
+ $content .= '
';
+ }
+ }
+
+ return [
+ 'title' => 'Search Results',
+ 'content' => $content
+ ];
+ }
+
+ private function parseMarkdown($content) {
+ $lines = explode("\n", $content);
+ $title = '';
+ $body = '';
+ $inBody = false;
+
+ foreach ($lines as $line) {
+ if (!$inBody && preg_match('/^#\s+(.+)$/', $line, $matches)) {
+ $title = $matches[1];
+ $inBody = true;
+ } elseif ($inBody || trim($line) !== '') {
+ $body .= $line . "\n";
+ $inBody = true;
+ }
+ }
+
+ $body = preg_replace('/### (.+)/', '$1
', $body);
+ $body = preg_replace('/## (.+)/', '$1
', $body);
+ $body = preg_replace('/# (.+)/', '$1
', $body);
+ $body = preg_replace('/\*\*(.+?)\*\*/', '$1', $body);
+ $body = preg_replace('/\*(.+?)\*/', '$1', $body);
+
+ // Convert Markdown links to HTML links
+ $body = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '$1', $body);
+
+ // Convert relative internal links to CMS format
+ $body = preg_replace('/href="\/blog\/([^"]+)"/', 'href="?page=blog/$1"', $body);
+ $body = preg_replace('/href="\/([^"]+)"/', 'href="?page=$1"', $body);
+
+ $body = preg_replace('/\n\n/', '
', $body);
+ $body = '
' . $body . '
';
+ $body = preg_replace('/<\/p>/', '', $body);
+ $body = preg_replace('/
()/', '$1', $body);
+ $body = preg_replace('/(<\/h[1-6]>)<\/p>/', '$1', $body);
+
+ return [
+ 'title' => $title ?: 'Untitled',
+ 'content' => $body
+ ];
+ }
+
+ private function parsePHP($filePath) {
+ ob_start();
+ $title = 'Untitled';
+ include $filePath;
+ $content = ob_get_clean();
+
+ return [
+ 'title' => $title,
+ 'content' => $content
+ ];
+ }
+
+ private function parseHTML($content) {
+ $title = 'Untitled';
+
+ if (preg_match('/(.*?)<\/title>/i', $content, $matches)) {
+ $title = strip_tags($matches[1]);
+ } elseif (preg_match('/]*>(.*?)<\/h1>/i', $content, $matches)) {
+ $title = strip_tags($matches[1]);
+ }
+
+ return [
+ 'title' => $title,
+ 'content' => $content
+ ];
+ }
+
+ private function getError404() {
+ return [
+ 'title' => 'Page Not Found',
+ 'content' => '404 - Page Not Found
The page you are looking for does not exist.
'
+ ];
+ }
+
+ public function getMenu() {
+ return $this->menu;
+ }
+
+ public function render() {
+ $page = $this->getPage();
+ $menu = $this->getMenu();
+ $breadcrumb = $this->getBreadcrumb();
+
+ $template = file_get_contents($this->config['templates_dir'] . '/layout.html');
+
+ $template = str_replace('{{site_title}}', $this->config['site_title'], $template);
+ $template = str_replace('{{page_title}}', $page['title'], $template);
+ $template = str_replace('{{content}}', $page['content'], $template);
+ $template = str_replace('{{search_query}}', isset($_GET['search']) ? htmlspecialchars($_GET['search']) : '', $template);
+ $template = str_replace('{{breadcrumb}}', $breadcrumb, $template);
+
+ // File info for footer
+ $fileInfo = '';
+ if (isset($page['file_info'])) {
+ $fileInfo = ' Created: ' . htmlspecialchars($page['file_info']['created']) .
+ ' | Modified: ' . htmlspecialchars($page['file_info']['modified']);
+ }
+ $template = str_replace('{{file_info}}', $fileInfo, $template);
+
+ $menuHtml = $this->renderMenu($menu);
+
+ $template = str_replace('{{menu}}', $menuHtml, $template);
+
+ echo $template;
+ }
+
+ private function getBreadcrumb() {
+ if (isset($_GET['search'])) {
+ return '';
+ }
+
+ $page = $_GET['page'] ?? $this->config['default_page'];
+ $page = preg_replace('/\.[^.]+$/', '', $page);
+
+ if ($page === $this->config['default_page']) {
+ return '';
+ }
+
+ $parts = explode('/', $page);
+ $breadcrumb = '';
+ return $breadcrumb;
+ }
+
+ private function renderMenu($items, $level = 0) {
+ $html = '';
+ foreach ($items as $item) {
+ if ($item['type'] === 'folder') {
+ $hasChildren = !empty($item['children']);
+ $html .= '';
+
+ if ($hasChildren) {
+ $folderId = 'folder-' . str_replace('/', '-', $item['path']);
+ $html .= '';
+ $html .= ' ' . htmlspecialchars($item['title']);
+ $html .= '';
+ $html .= '';
+ $html .= $this->renderMenu($item['children'], $level + 1);
+ $html .= '
';
+ } else {
+ $html .= '';
+ $html .= ' ' . htmlspecialchars($item['title']);
+ $html .= '';
+ }
+
+ $html .= '';
+ } else {
+ $active = (isset($_GET['page']) && $_GET['page'] === $item['path']) ? 'active' : '';
+ $html .= '';
+ $html .= '' . htmlspecialchars($item['title']) . '';
+ $html .= '';
+ }
+ }
+ return $html;
+ }
+}
+
+$cms = new CodePressCMS($config);
+$cms->render();
\ No newline at end of file
diff --git a/public/templates/layout.html b/public/templates/layout.html
new file mode 100644
index 0000000..cc23028
--- /dev/null
+++ b/public/templates/layout.html
@@ -0,0 +1,313 @@
+
+
+
+
+
+ {{page_title}} - {{site_title}}
+
+
+
+
+
+
+
+
+
+
+
+

+
{{site_title}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{breadcrumb}}
+
+
+
{{page_title}}
+
+
+ {{content}}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file