475765e31f
Add an explicit template renderer with HTML views and partials for the app, bootstrap, package, and catalog pages. Move shared reporting setup into config/reporting.php and relocate stylesheet assets under css/.
154 lines
3.6 KiB
PHP
154 lines
3.6 KiB
PHP
<?php
|
|
/*
|
|
* rktpkgs.php
|
|
*
|
|
* Maakt een volledige HTML-index van de Racket package catalogus.
|
|
*
|
|
* Bron:
|
|
* https://pkgs.racket-lang.org/pkgs-all
|
|
*
|
|
* Output:
|
|
* Alleen HTML.
|
|
*
|
|
* Package-links:
|
|
* /package?name=<pkg-name>&next=<id>
|
|
*
|
|
* Regels:
|
|
* - Geen filterveld.
|
|
* - Geen git-adressen tonen.
|
|
* - Geen package-details tonen.
|
|
* - Geen package-downloads implementeren in dit script.
|
|
* - De package-naam zelf is de link.
|
|
* - Eén next-id per gegenereerde HTML-pagina.
|
|
*
|
|
* .htaccess:
|
|
*
|
|
* Options -MultiViews
|
|
* RewriteEngine On
|
|
* RewriteRule ^racket-pkg-index$ rktpkgs.php [L,QSA]
|
|
*/
|
|
|
|
require_once __DIR__ . '/config/reporting.php';
|
|
|
|
require_once __DIR__ . '/private/nexttoken.php';
|
|
require_once __DIR__ . '/private/lib/catalog-http.php';
|
|
require_once __DIR__ . '/private/lib/racket-data.php';
|
|
require_once __DIR__ . '/private/Template.php';
|
|
|
|
$TOKENS = new NextTokenStore(__DIR__ . '/data/racket-sandbox.sqlite');
|
|
|
|
@set_time_limit(180);
|
|
ignore_user_abort(false);
|
|
|
|
define('CATALOG_PKGS_ALL', 'https://pkgs.racket-lang.org/pkgs-all');
|
|
|
|
define('CACHE_DIR', __DIR__ . '/data');
|
|
define('CACHE_FILE', CACHE_DIR . '/pkgs-all.rktd');
|
|
define('CACHE_META_FILE', CACHE_DIR . '/pkgs-all.meta.json');
|
|
define('CACHE_TTL', 3600);
|
|
|
|
/*
|
|
* Eén next-id voor alle package-links op deze pagina.
|
|
*/
|
|
$NEXT_ID = $TOKENS->create();
|
|
|
|
function h($s)
|
|
{
|
|
return htmlspecialchars((string)$s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
|
}
|
|
|
|
function current_scheme()
|
|
{
|
|
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
|
|
return strtolower(trim(explode(',', $_SERVER['HTTP_X_FORWARDED_PROTO'])[0]));
|
|
}
|
|
|
|
return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
|
}
|
|
|
|
function current_host()
|
|
{
|
|
return $_SERVER['HTTP_HOST'] ?? 'localhost';
|
|
}
|
|
|
|
function make_url($path, $query = array())
|
|
{
|
|
global $NEXT_ID;
|
|
|
|
$query['next'] = $NEXT_ID;
|
|
|
|
return current_scheme() . '://' . current_host() . $path . '?' . http_build_query($query);
|
|
}
|
|
|
|
function html_response($html, $status = 200)
|
|
{
|
|
http_response_code($status);
|
|
header('Content-Type: text/html; charset=utf-8');
|
|
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
|
header('Pragma: no-cache');
|
|
|
|
echo $html;
|
|
exit;
|
|
}
|
|
|
|
function fail_html($message, $status = 500)
|
|
{
|
|
html_response(
|
|
RacketSandboxTemplate::renderFile('protocol-error.html', array(
|
|
'title' => 'Error',
|
|
'message' => $message,
|
|
)),
|
|
$status
|
|
);
|
|
}
|
|
|
|
function get_pkgs_all_text()
|
|
{
|
|
try {
|
|
return catalog_http_fetch_cached(
|
|
CATALOG_PKGS_ALL,
|
|
CACHE_FILE,
|
|
CACHE_META_FILE,
|
|
CACHE_TTL,
|
|
'rktsndbx-rktpkgs/1.0',
|
|
180
|
|
);
|
|
} catch (Throwable $e) {
|
|
fail_html($e->getMessage());
|
|
}
|
|
}
|
|
|
|
function serve_index()
|
|
{
|
|
global $NEXT_ID;
|
|
|
|
$text = get_pkgs_all_text();
|
|
$names = rktd_extract_top_level_package_names($text);
|
|
|
|
if (count($names) === 0) {
|
|
fail_html('Geen package-namen gevonden in pkgs-all.');
|
|
}
|
|
|
|
$rows = '';
|
|
|
|
foreach ($names as $i => $name) {
|
|
$url = make_url('/package', array('name' => $name));
|
|
|
|
$rows .= RacketSandboxTemplate::renderFile('partials/package-index-row.html', array(
|
|
'id' => $name,
|
|
'index' => (string)($i + 1),
|
|
'url' => $url,
|
|
'name' => $name,
|
|
)) . "\n";
|
|
}
|
|
|
|
html_response(RacketSandboxTemplate::renderFile('racket-pkg-index.html', array(
|
|
'package_count' => (string)count($names),
|
|
'next_id' => $NEXT_ID,
|
|
'package_rows_html' => $rows,
|
|
)));
|
|
}
|
|
|
|
$TOKENS->check_valid_next('html');
|
|
serve_index();
|