#!/usr/bin/php-cgi -dcgi.force_redirect=0
<?php
# encoding: utf-8
# api: cgi
# type: config
# category: admin
# title: Extra config
# description: Additional list of options to configure, read from ext/* PMD
# version: 0.1
# state: beta
# config:
# { name: project-twitter, type: str, value: "", description: "Twitter handle for project (e.g. @sqlite1)" }
# { name: project-license, type: select, select: "0BSD|AAL|ADSL|AFL-3.0|AGPL-1.0|AGPL-3.0|AGPL-3.0-or-later|Apache-2.0|APSL-2.0|Artistic-1.0|Artistic-2.0|BSD-1-Clause|BSD-2-Clause|BSD-2-Clause-FreeBSD|BSD-2-Clause-NetBSD|BSD-2-Clause-Patent|BSD-3-Clause|BSD-3-Clause-Attribution|BSD-3-Clause-Clear|BSD-3-Clause-Modification|BSD-4-Clause|BSD-4-Clause-Shortened|BSL-1.0|CAL-1.0|CC0-1.0|CC-BY-2.0|CC-BY-3.0|CC-BY-4.0|CC-BY-NC-2.0|CC-BY-NC-4.0|CC-BY-NC-ND-2.0|CC-BY-NC-ND-3.0|CC-BY-NC-ND-4.0|CC-BY-NC-SA-2.0|CC-BY-NC-SA-3.0|CC-BY-NC-SA-4.0|CC-BY-ND-4.0|CC-BY-SA-2.0|CC-BY-SA-4.0|CDDL-1.1|CPL-1.0|ECL-2.0|EFL-2.0|EPL-2.0|EUPL-1.2|GFDL-1.1|GFDL-1.3-only|GFDL-1.3-or-later|GPL-1.0|GPL-1.0+|GPL-2.0|GPL-2.0+|GPL-2.0-only|GPL-3.0|GPL-3.0+|IPL-1.0|ISC|LGPL-2.0|LGPL-2.1|LGPL-2.1+|LGPL-3.0|LGPL-3.0+|MIT|MIT-0|MIT-Modern-Variant|MPL-1.0|MPL-1.1|MPL-2.0|MS-PL|MS-RL|NPL-1.1|OFL-1.0|OSL-2.0|OSL-3.0|PSF-2.0|Python-2.0|SPL-1.0|TCL|Unlicense|W3C|WTFPL|X11|Zend-2.0|ZPL-2.1", value: "", description: "Source code license (SPDX identifier)" }
# { name: project-description, type: text, value: "", description: "Fossil repository and project description" }
# new: -
#
# Reads the #config:{} fields, and updates fossils’ config table.
# Allows extroot scripts to provide additional options, or just
# an alternative to the builtin settings.
#
error_reporting(E_ALL);
#-- fossil HTML output
function page_md($text) {
header("Content-Type: text/html; charset=utf-8");
print <<<EOF
<div class='fossil-doc' data-title='Extra configuration'>
<style>
.config-list label {
display: block;
margin-bottom: 10pt;
border-left: 3pt #ddd solid;
border-radius: 5pt 0 0 5pt;
padding-left: 10pt;
}
</style>
$text
EOF;
}
#-- database (== fossil repo)
function db($sql="", $params=[]) {
static $db;
if (empty($db)) {
$db = new PDO("sqlite:$_SERVER[FOSSIL_REPOSITORY]");
}
if ($params) {
$stmt = $db->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
else {
return $db->query($sql)->fetchAll(PDO::FETCH_ASSOC);
}
}
function get_config($name, $default) {
$r = db("SELECT value FROM config WHERE name=?", [$name]);
return $r ? $r[0]["value"] : $default;
}
function h($s) {
return htmlspecialchars($s, ENT_QUOTES, "utf-8");
}
#-- filtered file list
function ls($dir) {
$ls = [];
foreach (glob("$dir/*") as $fn) {
if (is_file($fn) and is_executable($fn) and is_readable($fn)) {
$ls[] = basename($fn);
}
}
return $ls;
}
#-- plugin meta data reading (pluginconf version)
function meta($fn) {
$src = file_get_contents($fn, false, NULL, 0, 4096);
$src = preg_replace("~\R~", "\n", $src);
preg_match_all("~(^\h{0,4}(#(?!!)|//|/?\*).*\n)+~m", $src, $uu);
$src = implode("", $uu[0]);
$src = preg_replace("~^\h{0,4}(#|//|/?\*)\h{0,3}\r*~m", "", $src);
preg_match_all("~^([\w-]+):(.*$\\n(?:\n(?![\w-]+:).+$\\n)*)~xm", $src, $uu);
$r = array_combine($uu[1], $uu[2]);
return $r;
}
#-- split up config: field
function config($meta, $r=[]) {
if (empty($meta["config"])) {
return [];
}
preg_match_all("~\{ (.+?) \} | \< (.+?) \>~x", $meta["config"], $uu);
foreach ($uu[0] as $row) {
preg_match_all("~ [\"':$]?(\w*)[\"']? \s*[:=]+\s* (?: \"([^\"]*)\" | '([^']*)' | ([^,]*) )~x", $row, $uu, PREG_SET_ORDER);
$opt = [];
foreach ($uu as $f) {
$f = array_values(array_filter($f, "strlen"));
$opt[$f[1]] = isset($f[2]) ? $f[2] : "";
}
$r[] = $opt;
}
return $r;
}
#-- run
page_md("<div class=config-list>\n");
foreach (ls(__DIR__) as $fn) {
$meta = meta($fn);
$h = "h";
if ($config = config($meta)) {
$title = $meta["title"] ?: $fn;
print "<h3>$title</h3>\n";
foreach ($config as $opt) {
if (empty($opt["name"])) {
continue;
}
$name = $opt["name"];
$value = get_config($name, $opt["value"]);
print "<label><b>{$h($name)}</b><br>\n";
switch ($opt["type"]) {
case "long":
case "text":
print "<textarea name={$h($name)} rows=4 cols=70>{$h($value)}</textarea>";
break;
case "choose":
case "select":
print "<select name={$h($name)}>\n";
$opts = preg_split("~[|;,]~", $opt["select"]);
if (!in_array($value, $opts)) {
$opts[-1] = $value;
}
foreach ($opts as $o) {
$selected = $o == $value ? " selected" : "";
print "<option value=\"{$h($o)}\"$selected>{$h($o)}</option>\n";
}
print "</select>";
break;
default:
print "<input type=\"$opt[type]\" name={$h($name)} value=\"{$h($value)}\" size=60>";
}
print "<br>\n<small>{$h($opt['description'])}</small></label>\n\n";
}
}
}
?></div>