AntCMS/src/AntCMS/AntCMS.php

231 lines
7.8 KiB
PHP

<?php
namespace AntCMS;
use AntCMS\AntMarkdown;
use AntCMS\AntKeywords;
use AntCMS\AntPages;
use AntCMS\AntConfig;
class AntCMS
{
/**
* Renders a page based on the provided page name.
*
* @param string $page The name of the page to be rendered
* @return string The rendered HTML of the page
*/
public function renderPage(string $page)
{
$start_time = microtime(true);
$content = $this->getPage($page);
if (!$content || !is_array($content)) {
$this->renderException("404");
}
$markdown = AntMarkdown::renderMarkdown($content['content']);
$pageTemplate = $this->getPageLayout(null, $page);
$params = array(
'AntCMSTitle' => $content['title'],
'AntCMSDescription' => $content['description'],
'AntCMSAuthor' => $content['author'],
'AntCMSKeywords' => $content['keywords'],
);
$pageTemplate = str_replace('<!--AntCMS-Body-->', $markdown, $pageTemplate);
$pageTemplate = AntTwig::renderWithTiwg($pageTemplate, $params);
$end_time = microtime(true);
$elapsed_time = round($end_time - $start_time, 4);
if (AntConfig::currentConfig('debug')) {
$pageTemplate = str_replace('<!--AntCMS-Debug-->', '<p>Took ' . $elapsed_time . ' seconds to render the page. </p>', $pageTemplate);
}
return $pageTemplate;
}
/**
* Returns the default layout of the active theme unless otherwise specified.
*
* @param string|null $theme optional - the theme to get the page layout for.
* @param string $currentPage optional - What page is the active page.
* @return string the default page layout
*/
public function getPageLayout(string $theme = null, string $currentPage = '')
{
$siteInfo = AntCMS::getSiteInfo();
$pageTemplate = $this->getThemeTemplate('default_layout', $theme);
$pageTemplate = str_replace('<!--AntCMS-Navigation-->', AntPages::generateNavigation($this->getThemeTemplate('nav_layout', $theme), $currentPage), $pageTemplate);
$pageTemplate = str_replace('<!--AntCMS-SiteTitle-->', $siteInfo['siteTitle'], $pageTemplate);
return str_replace('<!--AntCMS-SiteLink-->', '//' . AntConfig::currentConfig('baseURL'), $pageTemplate);
}
/**
* Render an exception page with the provided exception code.
*
* @param string $exceptionCode The exception code to be displayed on the error page
* @return never
*/
public function renderException(string $exceptionCode)
{
$pageTemplate = $this->getPageLayout();
$pageTemplate = str_replace('<!--AntCMS-Title-->', 'An error ocurred', $pageTemplate);
$pageTemplate = str_replace('<!--AntCMS-Body-->', '<h1>An error ocurred</h1><p>That request caused an exception code (' . $exceptionCode . ')</p>', $pageTemplate);
echo $pageTemplate;
exit;
}
/**
* @param string $page
* @return array<mixed>|false
*/
public function getPage(string $page)
{
$page = strtolower($page);
$pagePath = AntDir . "/Content/{$page}";
$pagePath = AntTools::repairFilePath($pagePath);
if (is_dir($pagePath)) {
$pagePath .= '/index.md';
} else {
$pagePath = (file_exists($pagePath)) ? $pagePath : $pagePath . '.md';
}
if (file_exists($pagePath)) {
try {
$pageContent = file_get_contents($pagePath);
$pageHeaders = AntCMS::getPageHeaders($pageContent);
// Remove the AntCMS section from the content
$pageContent = preg_replace('/\A--AntCMS--.*?--AntCMS--/sm', '', $pageContent);
return ['content' => $pageContent, 'title' => $pageHeaders['title'], 'author' => $pageHeaders['author'], 'description' => $pageHeaders['description'], 'keywords' => $pageHeaders['keywords']];
} catch (\Exception) {
return false;
}
} else {
return false;
}
}
/**
* @param string $layout
* @param string|null $theme
* @return string
*/
public function getThemeTemplate(string $layout = 'default_layout', string $theme = null)
{
$theme = $theme ?? AntConfig::currentConfig('activeTheme');
if (!is_dir(antThemePath . '/' . $theme)) {
$theme = 'Default';
}
$templatePath = AntTools::repairFilePath(antThemePath . '/' . $theme . '/' . 'Templates');
$defaultTemplates = AntTools::repairFilePath(antThemePath . '/Default/Templates');
$templates = AntTools::getFileList($templatePath, 'twig');
try {
if (in_array($layout . '.html.twig', $templates)) {
$template = file_get_contents(AntTools::repairFilePath($templatePath . '/' . $layout . '.html.twig'));
} else {
$template = file_get_contents(AntTools::repairFilePath($defaultTemplates . '/' . $layout . '.html.twig'));
}
} catch (\Exception) {
}
if (empty($template)) {
if ($layout == 'default_layout') {
$template = '
<!DOCTYPE html>
<html>
<head>
<title>{{ AntCMSTitle }}</title>
<meta name="description" content="{{ AntCMSDescription }}">
<meta name="author" content="{{ AntCMSAuthor }}">
<meta name="keywords" content="{{ AntCMSKeywords }}">
</head>
<body>
<p>AntCMS had an error when fetching the page template, please contact the site administrator.</p>
<!--AntCMS-Body-->
</body>
</html>';
} else {
$template = '
<h1>There was an error</h1>
<p>AntCMS had an error when fetching the page template, please contact the site administrator.</p>';
}
}
return $template;
}
/**
* @param string $pageContent
* @return array<mixed>
*/
public static function getPageHeaders(string $pageContent)
{
$AntKeywords = new AntKeywords();
$pageHeaders = [
'title' => 'AntCMS',
'author' => 'AntCMS',
'description' => 'AntCMS',
'keywords' => '',
];
// First get the AntCMS header and store it in the matches varible
preg_match('/\A--AntCMS--.*?--AntCMS--/sm', $pageContent, $matches);
if (isset($matches[0])) {
$header = $matches[0];
// Then remove it from the page content so it doesn't cause issues if we try to generate the keywords
$pageContent = str_replace($header, '', $pageContent);
preg_match('/Title: (.*)/', $header, $matches);
$pageHeaders['title'] = trim($matches[1] ?? 'AntCMS');
preg_match('/Author: (.*)/', $header, $matches);
$pageHeaders['author'] = trim($matches[1] ?? 'AntCMS');
preg_match('/Description: (.*)/', $header, $matches);
$pageHeaders['description'] = trim($matches[1] ?? 'AntCMS');
preg_match('/Keywords: (.*)/', $header, $matches);
$pageHeaders['keywords'] = trim($matches[1] ?? '');
}
return $pageHeaders;
}
/**
* @return mixed
*/
public static function getSiteInfo()
{
return AntConfig::currentConfig('siteInfo');
}
/**
* @param string $path
* @return void
*/
public function serveContent(string $path)
{
if (!file_exists($path)) {
$this->renderException('404');
} else {
$asset_mime_type = mime_content_type($path);
header('Content-Type: ' . $asset_mime_type);
readfile($path);
}
}
}