misuzu/src/Info/InfoRoutes.php

124 lines
4 KiB
PHP

<?php
namespace Misuzu\Info;
use Index\Routing\IRouter;
use Index\Routing\IRouteHandler;
use Misuzu\Template;
use Misuzu\Parsers\Parser;
class InfoRoutes implements IRouteHandler {
private const DOCS_PATH = MSZ_ROOT . '/docs';
private const PROJECT_PATHS = [
'misuzu' => MSZ_ROOT,
'index' => MSZ_ROOT . '/vendor/flashwave/index',
];
private const PROJECT_SUFFIXES = [
'misuzu' => 'Misuzu Project » %s',
'index' => 'Index Project » %s',
];
public function registerRoutes(IRouter $router): void {
$router->get('/info', $this->getIndex(...));
$router->get('/info/:name', $this->getDocsPage(...));
$router->get('/info/:project/:name', $this->getProjectPage(...));
$router->get('/info.php', function($response) {
$response->redirect(url('info'), true);
});
$router->get('/info.php/:name', function($response, $request, string $name) {
$response->redirect(url('info', ['title' => $name]), true);
});
$router->get('/info.php/:project/:name', function($response, $request, string $project, string $name) {
$response->redirect(url('info', ['title' => $project . '/' . $name]), true);
});
}
private static function checkName(string $name): bool {
return preg_match('#^([A-Za-z0-9_]+)$#', $name) === 1;
}
public function getIndex() {
return Template::renderRaw('info.index');
}
public function getDocsPage($response, $request, string $name) {
if(!self::checkName($name))
return 404;
return $this->serveMarkdownDocument(
sprintf('%s/%s.md', self::DOCS_PATH, $name)
);
}
public function getProjectPage($response, $request, string $project, string $name) {
if(!array_key_exists($project, self::PROJECT_PATHS))
return 404;
if(!self::checkName($name))
return 404;
$projectPath = self::PROJECT_PATHS[$project];
$titleSuffix = array_key_exists($project, self::PROJECT_SUFFIXES) ? self::PROJECT_SUFFIXES[$project] : '';
$attempts = 0;
$licenceHack = false;
for(;;) {
$path = match(++$attempts) {
1 => sprintf('%s/%s', $projectPath, $name),
2 => sprintf('%s/%s.md', $projectPath, $name),
3 => sprintf('%s/%s', $projectPath, strtoupper($name)),
4 => sprintf('%s/%s.md', $projectPath, strtoupper($name)),
5 => sprintf('%s/%s', $projectPath, strtolower($name)),
6 => sprintf('%s/%s.md', $projectPath, strtolower($name)),
default => '',
};
if($path === '') {
if(!$licenceHack) {
$isBritish = strtolower($name) === 'licence';
$isAmerican = strtolower($name) === 'license';
if($isBritish || $isAmerican) {
$attempts = 0;
$licenceHack = true;
$name = $isAmerican ? 'licence' : 'license';
continue;
}
}
return 404;
}
if(is_file($path))
break;
}
return $this->serveMarkdownDocument($path, $titleSuffix);
}
private function serveMarkdownDocument(string $path, string $titleFormat = '') {
if(!is_file($path))
return 404;
$body = file_get_contents($path);
if(str_starts_with($body, '#')) {
$offset = strpos($body, "\n");
$title = trim(substr($body, 1, $offset));
$body = substr($body, $offset);
} else
$title = ucfirst(basename($path));
if($titleFormat !== '')
$title = sprintf($titleFormat, $title);
$body = Parser::instance(Parser::MARKDOWN)->parseText($body);
return Template::renderRaw('info.view', [
'document' => [
'title' => $title,
'content' => $body,
],
]);
}
}