Camel case data hinting, replacement refactor, showsource instead of sourcepreview option

This commit is contained in:
Conner Harkness 2025-09-25 09:08:33 -06:00
parent 11501e240b
commit a4aab45046
2 changed files with 137 additions and 88 deletions

View File

@ -78,3 +78,17 @@ declare @Fruit varchar(100) = ?; -- Options: Apple=0,Orange=1,Banana=2
```
The above will still allow a user to select a fruit's name from the dropdown, but only one of the corresponding values 0, 1, or 2 will be sent to the query as a `varchar(100)`.
---
### SQL Row and Column Hinting
All data with column names starting with an underscore `_` will be hidden from the output. To have finer control of how a row or cell of data appears, you can select and position special columns to control how the output appears.
* `__NextCellClass` — Apply this HTML class to the very next data cell
**Note:** To apply more than one `__NextCellClass` hint, additional identifiers must be used, e.g. `__NextCellClass0` or `__NextCellClassXYZ`.
* `__RowClass` — Apply this HTML class to the entire row and all data cells.
* `__Section` — Use to categorize similar and subsequent rows under a section with this name.

View File

@ -5,9 +5,6 @@
$strQueryDir = "files/sql";
// $varFiles = is_dir($strQueryDir)? scandir($strQueryDir) : [];
// $varFiles = array_diff($varFiles, [".", ".."]);
function removeQueryDir(&$strInput)
{
global $strQueryDir;
@ -39,88 +36,75 @@
$strFileDataSource = file_get_contents("{$strQueryDir}/{$strSelection}");
$strFileData = $strFileDataSource;
// Translate occurrences of {{ Date: next monday }} into yyyy-MM-dd format:
// Can be used in string literals or default values in comments!
preg_match_all(
"/\{\{\s*?Date\:\s*?(.*)\s*?\}\}/i",
$strFileData,
$varDateReplacements);
for ($i = 0; $i < count($varDateReplacements[0]); $i++)
$fncReplaceDate = function($strInput)
{
try
{
$strMatch = $varDateReplacements[0][$i];
$strMatchSafe = preg_quote($strMatch);
$strDateString = $varDateReplacements[1][$i];
$strFileData = preg_replace(
"/{$strMatchSafe}/i",
date_create($strDateString)->format("Y-m-d"),
$strFileData);
}
catch (Exception $x) {}
}
return
date_create($strInput)
->format("Y-m-d");
};
// WARNING: Can be abused.
// Translate occurrences of {{ SQL: select 'test' }} into the string value of the first cell of the first row:
// Can be used in string literals or default values in comments!
preg_match_all(
"/\{\{\s*SQL\:\s*(.*)\s+?\}\}/i",
$strFileData,
$varSQLReplacements);
for ($i = 0; $i < count($varSQLReplacements[0]); $i++)
$fncReplaceSQL = function($strSQL)
{
try
{
$strMatch = $varSQLReplacements[0][$i];
$strMatchSafe = preg_quote($strMatch);
$strSQLString = $varSQLReplacements[1][$i];
$varTempRows = $c->query($strSQLString);
global $c;
$varRows = $c->query($strSQL);
//Respond::json($varTempRows);
if (count($varRows) > 0)
foreach ($varRows[0] as $k => $v)
return $varRows[0][$k];
};
$strFirstCell = "";
if (count($varTempRows) > 0)
foreach ($varTempRows[0] as $k => $v)
{
$strFirstCell = $varTempRows[0][$k];
break;
}
$strFileData = preg_replace(
"/{$strMatchSafe}/i",
$strFirstCell,
$strFileData);
}
catch (Exception $x) {}
}
// $_SERVER Key replacements:
preg_match_all(
"/\{\{\s*([A-Z_]{1,})\s*\}\}/i",
$strFileData,
$varServerKeyReplacements);
//Respond::json($_SERVER);
for ($i = 0; $i < count($varServerKeyReplacements[0]); $i++)
$fncReplaceServer = function($strInput)
{
try
{
$strMatch = $varServerKeyReplacements[0][$i];
$strMatchSafe = preg_quote($strMatch);
$strKey = $varServerKeyReplacements[1][$i];
// Take no chances on possible SQL injection:
$strValue = $_SERVER[$strInput];
$strValue = preg_replace("/\'/i", "", $strValue);
if (array_key_exists($strKey, $_SERVER))
return
$strValue;
};
$varReplaceMap = [
["SQL", $fncReplaceSQL],
["Date", $fncReplaceDate],
["Server", $fncReplaceServer]
];
foreach ($varReplaceMap as $varReplace)
{
$strKey = $varReplace[0];
$fncReplace = $varReplace[1];
preg_match_all(
"/\{\{\s+{$strKey}\:\s+(.+?)\s+\}\}/i",
$strFileData,
$varMatches);
//if ($varReplace[0] == "Server")
// Respond::json($varMatches);
for ($i = 0; $i < count($varMatches[0]); $i++)
{
$strMatch = $varMatches[0][$i];
$strMatchSafe = preg_quote($strMatch);
$strInput = $varMatches[1][$i];
$strOutput = $fncReplace($strInput);
while (preg_match("/{$strMatchSafe}/i", $strFileData))
{
$strFileData = preg_replace(
"/{$strMatchSafe}/i",
$_SERVER[$strKey],
$strOutput,
$strFileData);
}
}
catch (Exception $x) {}
}
//ob_clean();
//header("Content-Type: text/plain");
//echo $strFileData;
//ob_end_flush();
//exit;
// Get the inputs:
preg_match_all(
"/declare\s+\@([A-Za-z0-9]{1,})\s+(.+)\s+=\s+\?;(\s+-- ([A-Za-z0-9]{1,})\:\s(.*))?/i",
@ -200,12 +184,12 @@
{
try
{
$varRows = $c->query($strQueryPath, $varPosted);
$varRows = $c->query($strFileData, $varPosted);
$strQueryView = "{$strQueryPath}.php";
if (count($varRows) > 0)
{
if (array_key_exists("_section", $varRows[0]))
if (array_key_exists("__Section", $varRows[0]))
{
$intSectioned = 1;
$intSortable = 0;
@ -575,7 +559,7 @@
<?php if ($strSelection !== null && strlen($strSelection) > 0): ?>
<?php if (array_key_exists("sourcepreview", $varOptions)): ?>
<?php if (array_key_exists("showsource", $varOptions)): ?>
<style>
#source-preview {
line-height: 1em;
@ -646,10 +630,10 @@
<div class="row my-3">
<?php foreach ($varRows as $r): ?>
<?php
// Allow SQL data to control row classes with _row_class column:
// Allow SQL data to control row classes with __RowClass column:
$strRowClass = "";
if (array_key_exists("_row_class", $r))
$strRowClass = $r["_row_class"];
if (array_key_exists("__RowClass", $r))
$strRowClass = $r["__RowClass"];
$strNextCellClass = "";
?>
@ -678,8 +662,8 @@
if (strlen($strNextCellClass) > 0)
$strCellClass = $strNextCellClass;
// Allow SQL data to controll next cell class with _next_cell_class column:
if (preg_match("/^_next_cell_class/i", $col))
// Allow SQL data to controll next cell class with __NextCellClass column:
if (preg_match("/^__NextCellClass/i", $col))
$strNextCellClass = $r[$col];
// Hide columns that begin with underscore:
@ -738,20 +722,20 @@
?>
<?php foreach ($varRows as $r): ?>
<?php
// Allow SQL data to control row classes with _row_class column:
// Allow SQL data to control row classes with __RowClass column:
$strRowClass = "";
if (array_key_exists("_row_class", $r))
$strRowClass = $r["_row_class"];
if (array_key_exists("__RowClass", $r))
$strRowClass = $r["__RowClass"];
$strNextCellClass = "";
?>
<?php if ($intSectioned && $strLastSection !== $r["_section"]): ?>
<?php if ($intSectioned && $strLastSection !== $r["__Section"]): ?>
<tr>
<td class="<?= $strSectionClass; ?>" colspan="<?= $intVisibleColumnCount; ?>"><?= $r["_section"]; ?></td>
<td class="<?= $strSectionClass; ?>" colspan="<?= $intVisibleColumnCount; ?>"><?= $r["__Section"]; ?></td>
</tr>
<?php
$strLastSection = $r["_section"];
$strLastSection = $r["__Section"];
?>
<?php endif; ?>
@ -766,8 +750,8 @@
if (strlen($strNextCellClass) > 0)
$strCellClass = $strNextCellClass;
// Allow SQL data to controll next cell class with _next_cell_class column:
if (preg_match("/^_next_cell_class/i", $col))
// Allow SQL data to controll next cell class with __NextCellClass column:
if (preg_match("/^__NextCellClass/i", $col))
$strNextCellClass = $r[$col];
// Hide columns that begin with underscore:
@ -775,6 +759,7 @@
continue;
?>
<td class="<?= $strCellClass; ?>" data-column-name="<?= $col; ?>"><?= $r[$col]; ?></td>
<?php
@ -973,3 +958,53 @@
<meta http-equiv="refresh" content="<?= $varOptions["autorefresh"]; ?>">
<?php endif; ?>
<?php if (array_key_exists("saveto", $varOptions)): ?>
<script>
$(function() {
var saveTo = "<?= $varOptions["saveto"]; ?>";
var saveColumns = "<?= $varOptions["savecolumns"]; ?>";
saveColumns = saveColumns.split(",");
saveColumnsArray.forEach(function(item, index) {
$(`td[data-column-name="${item}"]`).each(function(i, x) {
x = $(x);
var cellText = x.text().trim();
x.html("");
var inputElement = $("<input type='text' />");
x.append(inputElement);
inputElement.val(cellText);
});
});
$("#table tr input[type='text']").on("input", function() {
var parentTr = $(this).parents("tr").first();
parentTr.attr("data-save-row", 1);
});
fnSave = function()
{
$("tr[data-save-row]").each(function(i, x) {
x = $(x);
var o = {};
x.find("input").each(function(i2, x2) {
x2 = $(x2);
var cell = x2.parents("td").first();
var columnName = cell.attr("data-column-name");
o[columnName] = x2.val();
});
console.log(o);
});
};
});
</script>
<?php endif; ?>