Commit 89162ba2 authored by Carsten  Rose's avatar Carsten Rose
Browse files

Feature: #4014 / Bodoytext: values after '=' might be surrounded by single/double ticks

parent 3a6ad35e
......@@ -1043,6 +1043,9 @@ Very specific: Also, it's possible that the content of a variable is again (incl
is sometimes used in text templates, where the template is retrieved from a record and
specific locations in the text will be (automatically by QFQ) replaced by values from other sources.
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.
.. _`sanitize-class`:
Sanitize class
......@@ -1345,7 +1348,8 @@ Store: *RECORD* - R
* Sanitized: *no*
* Current record loaded in Form.
* *Form*: Current record.
* *Report*: See `access-column-values`_
* If r=0, all values are empty.
+------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
......@@ -4664,11 +4668,7 @@ There is a set of **variables** that will get replaced before the SQL-Query gets
``{{<name>[:<store/s>[:...]]}}``
Variables from specific stores.
``{{<name>:R}}`` - use case of the above generic definition.
STORE_RECORD is automatically merged with a) the existing STORE_RECORD content and b) the *current row*. Use the STORE_RECORD
to access outer and/or previous level values.
In case of previous level values: only the one of the last record is available.
Always access variables without an optional leading '_' - it's removed before the variable is copied to STORE_RECORD.
``{{<name>:R}}`` - use case of the above generic definition. See also `access-column-values`_.
``{{<level>.<columnname>}}``
Similar to ``{{<name>:R}}`` but more specific. There is no sanitize class, escape mode or default value.
......@@ -4697,10 +4697,11 @@ Processing of the resulting rows and columns:
`SELECT id AS _id`.
This might be useful to store values, which will be used later on in another query via the `{{id:R}}` or
`{{level.columnname}}` variable. To suppress printing of a column, use a underscore as column name prefix. E.g.
`{{<level>.columnname}}` variable. To suppress printing of a column, use a underscore as column name prefix. E.g.
`SELECT id AS _id`
*Reserved column names* have a special meaning and will be processed in a special way. See `Processing of columns in the SQL result`_ for details.
*Reserved column names* have a special meaning and will be processed in a special way. See
`Processing of columns in the SQL result`_ for details.
There are extensive ways to wrap columns and rows. See :ref:`wrapping-rows-and-columns`
......@@ -4764,7 +4765,7 @@ Example::
20.sql = SELECT 'a warm welcome'
'some additional', 'columns'
FROM smartTable
FROM anotherable
WHERE id>100
20.head = <h3>
......@@ -4773,7 +4774,7 @@ Example::
Join mode: SQL
''''''''''''''
This is the default. All lines are joined with a space in between. E.g.: ::
This is the default. All lines are joined with a *space* in between. E.g.: ::
10.sql = SELECT 'hello world'
FROM mastertable
......@@ -4785,8 +4786,8 @@ Notice the space between "...world'" and "FROM ...".
Join mode: strip whitespace
'''''''''''''''''''''''''''
Ending a line with a '\\' forces the removing off all leading and trailing whitespaces in that line and do not insert an
extra space in between. E.g.: ::
Ending a line with a '\\' strips all leading and trailing whitespaces of that line joins the line directly (no extra
space in between). E.g.: ::
10.sql = SELECT 'hello world', 'd:final.pdf \
|p:id=export \
......@@ -4821,6 +4822,20 @@ This is equal to: ::
10.5.sql = SELECT ...
10.5.head = ...
Leading / trailing spaces
^^^^^^^^^^^^^^^^^^^^^^^^^
By default, leading or trailing whitespaces are removed from strings behind '='. E.g. 'rend = test ' becomes 'test' for
rend. To prevent any leading or trailing spaces, surround them by using single or double ticks. Example: ::
10.sql = SELECT name FROM Person
10.rsep = ' '
10.head = "Names: "
Braces character for nesting
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default, curly braces '{}' are used for nesting. Alternatively angle braces '<>', round braces '()' or square
braces '[]' are also possible. To define the braces to use, the **first line** of the bodytext has to be a comment line and the
last character of that line must be one of '{}[]()<>'. The corresponding braces are used for that QFQ record. E.g.: ::
......@@ -4893,7 +4908,7 @@ Example STORE_RECORD: ::
The line '10.10' will output 'dummy' in cases where there is at least one corresponding address.
If there are no addresses (all persons) it reports the person id.
If there is at least one address, it reports 'dummy', cause that's the last stored content. This behaviour might change in the future.
If there is at least one address, it reports 'dummy', cause that's the last stored content.
Example 'Level Key': ::
......@@ -4942,7 +4957,7 @@ Wrapping rows and columns: Level keys
Order and nesting of queries, will be defined with a typoscript-like syntax: level.sublevel1.subsublevel2. ...
Each 'level' directive needs a final key, e.g: 20.30.10. **sql**. A key **sql** is necessary in order to process a level.
All `QFQ Keywords (Bodytext)`_.
See all `QFQ Keywords (Bodytext)`_.
Processing of columns in the SQL result
---------------------------------------
......@@ -5328,8 +5343,8 @@ Example `_pdf`, `_zip`: ::
Use the `--print-media-type` as wkhtml option to access the page with media type 'printer'. Depending on the website
configuration this switches off navigation and background images.
Rendering 'official' look-alike PDF letters
'''''''''''''''''''''''''''''''''''''''''''
Rendering PDF letters
'''''''''''''''''''''
`wkhtmltopdf`, with the header and footer options, can be used to render multi page PDF letters (repeating header,
pagination) in combination with dynamic content. Such PDFs might look-alike official letters, together with logo and signature.
......@@ -6265,7 +6280,7 @@ Two columns
::
# Add the formating information as a coloum
# Add the formatting information as a coloum
10.sql = SELECT p.firstName, " " , p.lastName, "<br>" FROM exp_person AS p
..
......@@ -6291,7 +6306,7 @@ One column 'rend'
::
10.sql = SELECT p.name FROM exp_person AS p
10.sql = SELECT p.firstName, " " , p.lastName FROM exp_person AS p
10.rend = <br>
..
......@@ -6321,10 +6336,7 @@ More HTML
..
Result:
::
Result: ::
o Billie Holiday
o Elvis Presley
......@@ -6394,6 +6406,21 @@ Same as above, but written in the nested notation ::
}
}
Best practice *recommendation* for using parameter - see `access-column-values`_
10 {
sql = SELECT p.id AS _pId, p.name FROM exp_person AS p
rend = <br>
10 {
# inner query
sql = SELECT a.street FROM exp_address AS a WHERE a.pId='{{pId:R}}'
rend = <br>
}
}
* Columns starting with a '_' won't be printed but can be accessed as regular columns.
Recent List
......
......@@ -8,6 +8,8 @@
namespace qfq;
require_once(__DIR__ . '/../Constants.php');
class OnString {
/**
......@@ -26,4 +28,56 @@ class OnString {
return substr($haystack, strrpos($haystack, $needle) + 1);
}
/**
* Strips the first char $c from $data if the first char is equal to $c.
* Example: with $c='_' the $data='_pId' becomes 'pId'
*
* @param $c
* @param $data
* @return string
*/
public static function stripFirstCharIf($c, $data) {
if (empty($data)) {
return $data;
}
if ($data[0] == $c) {
$data = substr($data, 1);
}
return $data;
}
/**
* If the given $str is enclosed in SINGLE_TICK or DOUBLE_TICK, remove it.
*
* @param string $str
* @return string remove unquoted string
*/
public static function trimQuote($str) {
$len = strlen($str);
if ($len < 2) {
return $str;
}
switch ($str[0]) {
case SINGLE_TICK:
if ($str[$len - 1] == SINGLE_TICK) {
return substr($str, 1, $len - 2);
}
break;
case DOUBLE_TICK:
if ($str[$len - 1] == DOUBLE_TICK) {
return substr($str, 1, $len - 2);
}
break;
default:
break;
}
return $str;
}
}
......@@ -1338,26 +1338,6 @@ class Support {
}
}
/**
* Strips the first char $c from $data if the first char is equal to $c.
* Example: with $c='_' the $data='_pId' becomes 'pId'
*
* @param $c
* @param $data
* @return string
*/
public static function stripFirstCharIf($c, $data) {
if (empty($data)) {
return $data;
}
if ($data[0] == $c) {
$data = substr($data, 1);
}
return $data;
}
/**
* @param $mode
......
......@@ -210,7 +210,7 @@ class Report {
foreach ($ttLineArray as $index => $line) {
// Fill $frArray, $indexArray, $resultArray
$this->parseFRLine($line);
$this->parseLine($line);
}
// Sort array
......@@ -230,7 +230,7 @@ class Report {
*
* @throws UserReportException
*/
private function parseFRLine($ttLine) {
private function parseLine($ttLine) {
// 10.50.5.sql = select ...
$arr = explode("=", trim($ttLine), 2);
......@@ -248,8 +248,9 @@ class Report {
return;
}
// select ...
// select ... - if needed, trim surrounding single ticks
$value = trim($arr[1]);
$value = OnString::trimQuote($value);
// 10.50.5.sql
$arrKey = explode('.', $key);
......@@ -613,7 +614,7 @@ class Report {
$flagOutput = false;
$renderedColumn = $this->renderColumn($ii, $keys[$ii], $row[$ii], $full_level, $rowIndex, $flagOutput);
$keyAssoc = Support::stripFirstCharIf(TOKEN_COLUMN_CTRL, $keys[$ii]);
$keyAssoc = OnString::stripFirstCharIf(TOKEN_COLUMN_CTRL, $keys[$ii]);
if ($keyAssoc != '') {
$assoc[$keyAssoc] = $row[$ii];
}
......
......@@ -21,6 +21,9 @@ use qfq;
class OnStringTest extends \PHPUnit_Framework_TestCase {
/**
*
*/
public function testStrrstr() {
$this->assertEquals('', OnString::strrstr('', ''));
......@@ -28,4 +31,34 @@ class OnStringTest extends \PHPUnit_Framework_TestCase {
$this->assertEquals('limit', OnString::strrstr('hello world to the limit', ' '));
$this->assertEquals('', OnString::strrstr('', ' '));
}
/**
*
*/
public function testStripFirstCharIf() {
$this->assertEquals('', OnString::stripFirstCharIf('', ''));
$this->assertEquals('', OnString::stripFirstCharIf('c', ''));
$this->assertEquals('', OnString::stripFirstCharIf('c', 'c'));
$this->assertEquals('def', OnString::stripFirstCharIf('c', 'cdef'));
$this->assertEquals('def', OnString::stripFirstCharIf('c', 'def'));
$this->assertEquals('def', OnString::stripFirstCharIf('cd', 'def'));
}
/**
*
*/
public function testTrimQuote() {
$this->assertEquals('', OnString::trimQuote(''));
$this->assertEquals('test', OnString::trimQuote('test'));
$this->assertEquals(' test ', OnString::trimQuote(' test '));
$this->assertEquals('" test ', OnString::trimQuote('" test '));
$this->assertEquals('" test \'', OnString::trimQuote('" test \''));
$this->assertEquals('\' test "', OnString::trimQuote('\' test "'));
$this->assertEquals(' test ', OnString::trimQuote('" test "'));
$this->assertEquals(' test ', OnString::trimQuote("' test '"));
$this->assertEquals(' te"st ', OnString::trimQuote("' te\"st '"));
$this->assertEquals(' te\'st ', OnString::trimQuote("' te'st '"));
}
}
\ No newline at end of file
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