Commit dc16b324 authored by Carsten  Rose's avatar Carsten Rose
Browse files

Feature #5422 / New variable class "{{'....' AS LINK}}" - implemented

parent a9d71f91
...@@ -960,12 +960,13 @@ File: `config.qfq.ini`_ ...@@ -960,12 +960,13 @@ File: `config.qfq.ini`_
Variable Variable
======== ========
Most elements of a Form, FormElement or Report might contain (QFQ) variables. Such variables are surrounded by Variables in QFQ are surrounded by double curly braces. Four different types of variable substitution functionality is
double curly braces. Three different types of functionality are provided. Access to: provided. Access to:
* `store-variables`_ * `store-variables`_
* `sql-variables`_ * `sql-variables`_
* `column-variables`_ * `row-column-variables`_
* `link-column-variables`_
Some examples, including nesting:: Some examples, including nesting::
...@@ -979,7 +980,7 @@ Some examples, including nesting:: ...@@ -979,7 +980,7 @@ Some examples, including nesting::
#--------------------------------------------- #---------------------------------------------
{{SELECT name FROM person WHERE id=1234}} {{SELECT name FROM person WHERE id=1234}}
# Columns # Row columns
#--------------------------------------------- #---------------------------------------------
{{10.pId}} {{10.pId}}
{{10.20.pId}} {{10.20.pId}}
...@@ -990,6 +991,8 @@ Some examples, including nesting:: ...@@ -990,6 +991,8 @@ Some examples, including nesting::
{{SELECT name FROM person WHERE id={{key1:C:alnumx}} }} # explained below {{SELECT name FROM person WHERE id={{key1:C:alnumx}} }} # explained below
{{SELECT name FROM person WHERE id={{SELECT id FROM pf LIMIT 1}} }} # it's more efficient to use only one query {{SELECT name FROM person WHERE id={{SELECT id FROM pf LIMIT 1}} }} # it's more efficient to use only one query
# Link Columns
{{p:form=Person&r=1|t:Edit Person|E|s AS link}}
Leading and trailing spaces inside curly braces are removed. Leading and trailing spaces inside curly braces are removed.
...@@ -1090,10 +1093,10 @@ Example ...@@ -1090,10 +1093,10 @@ Example
{{[2]SELECT id, name FROM Form}} {{[2]SELECT id, name FROM Form}}
{{[{{DB_INDEX_QFQ:Y}}]SELECT id, name FROM Form}} {{[{{DB_INDEX_QFQ:Y}}]SELECT id, name FROM Form}}
.. _`column-variables`: .. _`row-column-variables`:
Column variables Row column variables
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
Syntax: *{{<level>.<column>}}* Syntax: *{{<level>.<column>}}*
...@@ -1111,6 +1114,27 @@ specific locations in the text will be (automatically by QFQ) replaced by values ...@@ -1111,6 +1114,27 @@ specific locations in the text will be (automatically by QFQ) replaced by values
General note: using this type of variables is only the second choice. First choice is `{{column:R}}` (see General note: using this type of variables is only the second choice. First choice is `{{column:R}}` (see
`access-column-values`_) - using the STORE_RECORD is more portable cause no renumbering is needed if the level keys change. `access-column-values`_) - using the STORE_RECORD is more portable cause no renumbering is needed if the level keys change.
.. _`link-column-variables`:
Link column variables
^^^^^^^^^^^^^^^^^^^^^
These variables return a link, completely rendered in HTML. The syntax and all features of `column-link`_ are available.
The following code will render a 'new person' button::
{{p:form&form=Person|s|N|t:new person AS link}}
For better reading, the format string might be wrapped in single or double quotes (this ist optional): ::
{{"p:form&form=Person|s|N|t:new person" AS link}}
These variables are especially helpful in:
* `report`, to create create links or buttons outside of a SQL statement. E.g. in `head`, `rbeg`, ...
* `form`, to create links and buttons in labels or notes.
.. _`sanitize-class`: .. _`sanitize-class`:
Sanitize class Sanitize class
......
...@@ -616,6 +616,7 @@ if (!function_exists('ldap_escape')) { ...@@ -616,6 +616,7 @@ if (!function_exists('ldap_escape')) {
} }
const TOKEN_FOUND_IN_STORE_QUERY = 'query'; const TOKEN_FOUND_IN_STORE_QUERY = 'query';
const TOKEN_FOUND_AS_COLUMN = 'column';
const TOKEN_FOUND_AS_DEFAULT = 'default'; const TOKEN_FOUND_AS_DEFAULT = 'default';
const RANDOM_LENGTH = 32; const RANDOM_LENGTH = 32;
......
...@@ -13,6 +13,8 @@ use qfq; ...@@ -13,6 +13,8 @@ use qfq;
require_once(__DIR__ . '/../qfq/store/Store.php'); require_once(__DIR__ . '/../qfq/store/Store.php');
require_once(__DIR__ . '/../qfq/database/Database.php'); require_once(__DIR__ . '/../qfq/database/Database.php');
require_once(__DIR__ . '/helper/Support.php'); require_once(__DIR__ . '/helper/Support.php');
require_once(__DIR__ . '/helper/OnString.php');
require_once(__DIR__ . '/report/Link.php');
const EVALUATE_DB_INDEX_DEFAULT = 0; const EVALUATE_DB_INDEX_DEFAULT = 0;
/** /**
...@@ -30,6 +32,11 @@ class Evaluate { ...@@ -30,6 +32,11 @@ class Evaluate {
*/ */
private $dbArray = array(); private $dbArray = array();
/**
* @var Link
*/
private $link = null;
private $dbIndex = EVALUATE_DB_INDEX_DEFAULT; private $dbIndex = EVALUATE_DB_INDEX_DEFAULT;
private $startDelimiter = ''; private $startDelimiter = '';
private $startDelimiterLength = 0; private $startDelimiterLength = 0;
...@@ -38,6 +45,7 @@ class Evaluate { ...@@ -38,6 +45,7 @@ class Evaluate {
private $sqlKeywords = array('SELECT ', 'INSERT ', 'DELETE ', 'UPDATE ', 'SHOW ', 'REPLACE '); private $sqlKeywords = array('SELECT ', 'INSERT ', 'DELETE ', 'UPDATE ', 'SHOW ', 'REPLACE ');
private $escapeTypeDefault = ''; private $escapeTypeDefault = '';
// private $debugStack = array(); // private $debugStack = array();
...@@ -221,24 +229,44 @@ class Evaluate { ...@@ -221,24 +229,44 @@ class Evaluate {
$sqlMode = ROW_REGULAR; $sqlMode = ROW_REGULAR;
} }
// just to extract the first token: check if this is a SQL Statement // Extract token: check if this is a SQL Statement
$arr = explode(' ', $token, 2); $arrToken = explode(' ', $token);
// SQL Statement? // Variable Type 'SQL Statement'
if (in_array(strtoupper($arr[0] . ' '), $this->sqlKeywords)) { if (in_array(strtoupper($arrToken[0] . ' '), $this->sqlKeywords)) {
$foundInStore = TOKEN_FOUND_IN_STORE_QUERY; $foundInStore = TOKEN_FOUND_IN_STORE_QUERY;
return $this->dbArray[$dbIndex]->sql($token, $sqlMode); return $this->dbArray[$dbIndex]->sql($token, $sqlMode);
} }
// Variable Type '... AS LINK'
$countToken = count($arrToken);
if ($countToken > 2 && strcasecmp($arrToken[$countToken - 2], 'as') == 0) {
$type = OnString::stripFirstCharIf('_', $arrToken[$countToken - 1]);
if (strcasecmp($type, 'link') == 0) {
$str = OnString::trimQuote(substr($token, 0, strlen($token) - 8)); // strlen('_as_link')=8
if ($this->link === null) {
$this->link = new Link($this->store->getSipInstance(), $dbIndex);
}
$foundInStore = TOKEN_FOUND_AS_COLUMN;
return $this->link->renderLink($str);
}
}
// explode for: <key>:<store priority>:<sanitize class>:<escape>:<default> // explode for: <key>:<store priority>:<sanitize class>:<escape>:<default>
$arr = explode(':', $token, 5); $arrToken = explode(':', $token, 5);
$arr = array_merge($arr, [null, null, null, null, null]); // fake isset() $arrToken = array_merge($arrToken, [null, null, null, null, null]); // fake isset()
$escapeTypes = (empty($arr[3])) ? $this->escapeTypeDefault : $arr[3]; $escapeTypes = (empty($arrToken[3])) ? $this->escapeTypeDefault : $arrToken[3];
// search for value in stores // search for value in stores
$value = $this->store->getVar($arr[0], $arr[1], $arr[2], $foundInStore); $value = $this->store->getVar($arrToken[0], $arrToken[1], $arrToken[2], $foundInStore);
// escape ticks // escape ticks
if (is_string($value)) { if (is_string($value)) {
...@@ -274,9 +302,9 @@ class Evaluate { ...@@ -274,9 +302,9 @@ class Evaluate {
} }
// Not found and a default is given: take the default. // Not found and a default is given: take the default.
if ($foundInStore == '' && !empty($arr[4])) { if ($foundInStore == '' && !empty($arrToken[4])) {
$foundInStore = TOKEN_FOUND_AS_DEFAULT; $foundInStore = TOKEN_FOUND_AS_DEFAULT;
$value = str_replace('\\:', ':', $arr[4]); $value = str_replace('\\:', ':', $arrToken[4]);
} }
return $value; return $value;
......
...@@ -51,7 +51,7 @@ class OnString { ...@@ -51,7 +51,7 @@ class OnString {
} }
/** /**
* If the given $str is enclosed in SINGLE_TICK or DOUBLE_TICK, remove it. * If the given $str is enclosed in SINGLE_TICK or DOUBLE_TICK, remove it. Only the outermost are removed.
* *
* @param string $str * @param string $str
* @return string remove unquoted string * @return string remove unquoted string
......
...@@ -657,7 +657,7 @@ class Report { ...@@ -657,7 +657,7 @@ class Report {
$flagOutput = true; $flagOutput = true;
$dummy = false; $dummy = false;
// Empty columnnames are allowed: check with isset // Empty column names are allowed: check with isset
if (isset($columnName[0]) && $columnName[0] === TOKEN_COLUMN_CTRL) { if (isset($columnName[0]) && $columnName[0] === TOKEN_COLUMN_CTRL) {
$flagControl = true; $flagControl = true;
$columnName = substr($columnName, 1); $columnName = substr($columnName, 1);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment