Commit 51d57d52 authored by Carsten  Rose's avatar Carsten Rose
Browse files

Merge branch 'F9905KeywordRender' into 'develop'

F9905 keyword render

See merge request !248
parents 943f386b c85c79c5
Pipeline #3217 passed with stages
in 3 minutes and 30 seconds
......@@ -22,7 +22,7 @@ Quick Form Query Extension
en
:Copyright:
2017-2019
2017-2020
:Authors:
Carsten Rose, Benjamin Baer, Marc Egger
......
......@@ -274,11 +274,8 @@ Setup a *report* to manage all *forms*:
dbIndex = {{indexQfq:Y}}
 
10 {
# List of Forms: Do not show this list of forms if there is a form given by SIP.
# Table header.
sql = SELECT CONCAT('p:{{pageAlias:T}}&form=form|A:data-reference=newForm') as _pagen, '#', 'Name', 'Title', 'Table', ''
FROM (SELECT 1) AS fake
WHERE '{{form:SE}}'=''
head = {{'b|p:id={{pageAlias:T}}&form=copyFormFromExt|t:Copy form from ExtForm|A:data-reference=copyForm' AS _link}}
<table class="table table-hover qfq-table-50 tablesorter tablesorter-filter" id="{{pageAlias:T}}-form">
tail = </table>
......@@ -385,7 +382,9 @@ Extension Manager: QFQ Configuration
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| flagProduction | yes | yes|no: used to differentiate production and development site. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| render | single | both|single: used to differentiate production and development site. |
| render | single | both|single: QFQ will show form and/or report. In most cases only one at a |
| | | time is needed. Options: 'single' (default) or 'both' (legacy). In mode |
| | | 'single' prefer 'form' over 'report'. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| maxFileSize | 10M | If empty, take minimum of 'post_max_size' and 'upload_max_filesize'. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
......@@ -700,21 +699,6 @@ Every access to QFQ related content resets the timeout.
 
After FE login, the next access to QFQ related content starts the timeout counter.
 
.. _local-documentation:
Local Documentation
-------------------
A HTML rendered version is available under: <your site>/typo3conf/ext/qfq/Documentation/html/Index.html
If you get a 'Page forbidden / not found' there might be some Webserver restrictions. E.g. the Typo3 example of `.htaccess`
in the Typo3 installation folder will forbid access to any extension documentation (which is a good idea on a productive
server). For a development server instead, deactivate the forbid rule of 'documentation'. In `.htaccess` (snippet from
Typo3 7.6 _.htaccess): ::
production: RewriteRule (?:typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(?:Configuration|Resources/Private|Tests?|Documentation|docs?)/ - [F]
development: RewriteRule (?:typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(?:Configuration|Resources/Private|Tests?|docs?)/ - [F]
.. _concept:
 
Concept
......@@ -769,7 +753,7 @@ backend for orientation.
QFQ Keywords (Bodytext)
^^^^^^^^^^^^^^^^^^^^^^^
 
**All of the named parameter are optional.**
**All of these parameters are optional.**
 
+-------------------+---------------------------------------------------------------------------------+
| Name | Explanation |
......@@ -793,6 +777,8 @@ QFQ Keywords (Bodytext)
+-------------------+---------------------------------------------------------------------------------+
| sqlLogMode | Overwrites configuration_: `SQL_LOG_MODE`_ . Only affects `Report`, not `Form`. |
+-------------------+---------------------------------------------------------------------------------+
| render | See `report-render`_. Overwrites configuration_: render. |
+-------------------+---------------------------------------------------------------------------------+
| <level>.fbeg | Start token for every field (=column) |
+-------------------+---------------------------------------------------------------------------------+
| <level>.fend | End token for every field (=column) |
......@@ -839,6 +825,33 @@ QFQ Keywords (Bodytext)
| | | To retrieve the content: `{{<level>.line.content}}`. See `syntax-of-report`_ |
+-------------------+---------------------------------------------------------------------------------+
 
.. _`report-render`:
Report: render
--------------
QFQ will render Report or Form in three situations:
#. Browser: The QFQ content is described by QFQ-Report syntax.
#. Browser: The QFQ content is described by a QFQ-Form.
#. API: The QFQ content is handled without Typo3. Typically a single tt-content record is specified in the request - only
that one is rendered by QFQ. This mode is typically used to export data like Excel Export.
Option 1 and 2 are distinguished by the parameter `form` (STORE_SIP or STORE_TYPO3). If 'form' is given, in most cases only a Form
should be shown (not the report).
+--------+-------------------------------------------------------------------------+
| render | Use |
+========+=========================================================================+
| single | Display Form or Report, but not both at the same time. If |
| | a SIP parameter 'form' is given, the form is rendered, else the report. |
+--------+-------------------------------------------------------------------------+
| both | Display Form and Report, both at the same time. |
+--------+-------------------------------------------------------------------------+
| api | Create output only when called via API (no Typo3). |
+--------+-------------------------------------------------------------------------+
.. _`qfq-database`:
 
QFQ Database
......@@ -2247,10 +2260,11 @@ General
* Inside the QFQ record: `form = <formname>`. E.g.:
 
* Static: `form = Person`
* Dynamic: `form = {{form:SE}}` (the left `form` is a keyword for QFQ, the right `form` is a free chooseable variable name)
* Dynamic 1: `form = {{form:SE}}` (the left `form` is a keyword for QFQ, the right `form` is a variable name)
* Dynamic 2: `form = {{SELECT f.name FROM Form AS f WHERE f.id=...}}` (the left `form` is a keyword for QFQ, the right `form` is a variable name)
 
* With the `Dynamic` option, it's easily possible to use one Typo3 page and display different forms on that specific
page. This is nice to configure few Typo 3 pages. The disadvantage is that the user might loose the navigation.
page.
 
Form process order
------------------
......@@ -4901,6 +4915,29 @@ already a lock for a `tablename` / `record id` pair, the most restrictive will b
Best practice
-------------
 
View: List vs. Detail
^^^^^^^^^^^^^^^^^^^^^
As 'list' a number of data/rows shown on the page is meant.
As 'detail' a form is meant, which shows one single data record and let the user edit it.
To provide an easy understandable navigation structure, it's nice for the user to stay on the same page, even the user is
in 'detail' or 'list' mode. Create a single QFQ tt-content record on a fresh page::
form = {{form:SE}}
10.sql = SELECT p.name, CONCAT('p:{{pageAlias:T}}&form=Person&r=', p.id) AS _pagee FROM Person AS p
10.rend = <br>
* If the page is called without any parameter, a list of persons is shown.
* Behind each name, a button is shown. A click on it opens the form 'Person' (with the selected person record) on the same page.
Mode 'list' or 'detail' is detected automatically: if a form is given via STORE_SIP or STORE_TYPO3, the form (=detail) is
shown else the report (=list).
Custom default value only for 'new records'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
......@@ -7376,10 +7413,10 @@ Excel export
 
This chapter explains how to create Excel files on the fly.
 
Hint: For up/downloading of excel files (without modification), check the generic Form
Hint: For just up/downloading of excel files (without modification), check the generic Form
`input-upload`_ element and the report 'download' (`column_pdf`_) function.
 
The Excel file is build in the moment when the user request it by clicking on a
The Excel file is build in the moment when the user request it, by clicking on a
download link.
 
Mode building:
......@@ -7408,7 +7445,7 @@ Setup
result as the instructions for filling the excel file.
* Parameters can be passed: `uid:<tt-content record id>?param=<value1>&param2=<value2>` and will be accessible in the SIP Store (S) in the
QFQ PageContent.
* Use the regular QFQ Report syntax to create some output.
* Use the regular QFQ Report syntax to create output.
* The newline at the end of every line needs to be CHAR(10). To make it simpler, the special column name `... AS _XLS`
(see _XLS, _XLSs, _XLSb, _XLSn) can be used.
* One option per line.
......@@ -7452,26 +7489,26 @@ This fills D11, E11, F11, D12
In Report Syntax::
 
# With ... AS _XLS (token explicit given)
10.sql = SELECT 'position=D10' AS _XLS,
's=Hello' AS _XLS,
's=World' AS _XLS,
's=First Line' AS _XLS,
'newline' AS _XLS,
's=Second line' AS _XLS,
'n=123' AS _XLS,
10.sql = SELECT 'position=D10' AS _XLS
, 's=Hello' AS _XLS
, 's=World' AS _XLS
, 's=First Line' AS _XLS
, 'newline' AS _XLS
, 's=Second line' AS _XLS
, 'n=123' AS _XLS
 
# With ... AS _XLSs (token generated internally)
20.sql = SELECT 'position=D20' AS _XLS,
'Hello' AS _XLSs,
'World' AS _XLSs,
'First Line' AS _XLSs,
'newline' AS _XLS,
'Second line' AS _XLSs,
'n=123' AS _XLS,
20.sql = SELECT 'position=D20' AS _XLS
, 'Hello' AS _XLSs
, 'World' AS _XLSs
, 'First Line' AS _XLSs
, 'newline' AS _XLS
, 'Second line' AS _XLSs
, 'n=123' AS _XLS
 
# With ... AS _XLSb (token generated internally and content is base64 encoded)
30.sql = SELECT 'position=D30' AS _XLS,
'<some content with special characters like newline/carriage return>' AS _XLSb
30.sql = SELECT 'position=D30' AS _XLS
, '<some content with special characters like newline/carriage return>' AS _XLSb
 
.. _`excel-export-sample`:
 
......@@ -7487,6 +7524,35 @@ Excel export samples (54 is a example <tt-content record id>)::
# With parameter (via SIP) - get the Parameter on page 'exceldata' with '{{arg1:S}}' and '{{arg2:S}}'
SELECT CONCAT('d:final.xlsx|t:Excel (parameter)|uid:54&arg1=hello&arg2=world') AS _excel
 
Best practice
"""""""""""""
To keep the link of the Excel export close to the Excel export definition, the option `report-render`_ can be used.
On a **single** T3 page create **two** QFQ tt-content records:
tt-content record 1:
* Type: QFQ
* Content::
render = single
10.sql = SELECT CONCAT('d:new.xlsx|t:Excel (new)|uid:54|M:excel|s:1') AS _link
tt-content record 2 (uid=54):
* Type: QFQ
* Content::
render = api
10.sql = SELECT 'position=D10' AS _XLS
, 's=Hello' AS _XLS
, 's=World' AS _XLS
, 's=First Line' AS _XLS
, 'newline' AS _XLS
, 's=Second line' AS _XLS
, 'n=123' AS _XLS
.. _dropdownMenu:
 
Dropdown Menu
......@@ -8296,11 +8362,14 @@ last used (STORE_USER) or (first time call during browser session) takes the def
, ' <button class="btn disabled ', IF({{semId:Y0}}=sc.id, 'btn-success', 'btn-default'), '">',sc.name, '</button> '
, CONCAT('p:{{pageAlias:T}}&semId=', sn.id, '|t:', QBAR(sn.name), '|s|b|G:glyphicon-chevron-right|R') AS _link
FROM Semester AS sc
LEFT JOIN semester AS sp
ON sp.id=sc.id-1
LEFT JOIN semester AS sn
ON sc.id+1=sn.id AND sn.show_semester_from<=CURDATE()
WHERE sc.id={{semId:SUY}} AND '{{form:SE}}'=''
WHERE sc.id={{semId:SUY}}
ORDER BY sc.semester_von
head = <div class="btn-group" style="position: absolute; top: 15px; right: 25px;">
tail = </div><p></p>
......@@ -8634,8 +8703,7 @@ has the form be used. The following report includes the regular `form-editor`_ a
, '</th><th><em>Last</em>'
, '</th><th><em>PageId</em></th>'
FROM (SELECT '') AS fake
WHERE '{{form:SE}}'=''
AND {{formIdHistory:S0}}=0
WHERE {{formIdHistory:S0}}=0
head = <table class="table table-hover qfq-table-50 tablesorter tablesorter-filter" id="{{pageAlias:T}}-form">
rbeg = <thead class="qfq-sticky"><tr>
rend = </tr></thead><tbody>
......@@ -8743,7 +8811,7 @@ to edit `AutoCron` jobs::
10 {
# Table header.
sql = SELECT CONCAT('p:{{pageAlias:T}}&form=cron') AS _pagen, 'id', 'Next run','Frequency','Comment'
, 'Last run','In progress', 'Status', 'Auto generated' FROM (SELECT 1) AS fake WHERE '{{form:SE}}'=''
, 'Last run','In progress', 'Status', 'Auto generated'
head = <table class='table table-hover qfq-table-50'>
tail = </table>
rbeg = <thead><tr>
......
......@@ -654,10 +654,10 @@ const SYSTEM_THUMBNAIL_DIR_PUBLIC = 'thumbnailDirPublic';
const SYSTEM_THUMBNAIL_DIR_PUBLIC_DEFAULT = 'typo3temp/qfqThumbnail';
const SYSTEM_DOCUMENTATION_QFQ = 'documentation';
const SYSTEM_DOCUMENTATION_QFQ_URL = 'https://docs.typo3.org/p/IMATHUZH/qfq/master/en-us/Manual.html';
const SYSTEM_DOCUMENTATION_QFQ_URL = 'https://qfq.io/doc';
// Not stored in config.qfq.ini, but used in STORE_SYSTEM
// Not stored in config.qfq.php, but used in STORE_SYSTEM
// Information for: Log / Debug / Exception
const SYSTEM_SQL_RAW = 'sqlRaw'; // Type: SANITIZE_ALL / String. SQL Query (before substitute). Useful for error reporting.
const SYSTEM_SQL_FINAL = 'sqlFinal'; // Type: SANITIZE_ALL / String. SQL Query (after substitute). Useful for error reporting.
......@@ -1517,7 +1517,7 @@ const TOKEN_DEBUG_BODYTEXT = TYPO3_DEBUG_SHOW_BODY_TEXT;
const TOKEN_DB_INDEX = F_DB_INDEX;
const TOKEN_CONTENT = 'content';
const TOKEN_VALID_LIST = 'sql|twig|head|althead|altsql|tail|shead|stail|rbeg|rend|renr|rsep|fbeg|fend|fsep|fskipwrap|rbgd|debug|form|r|debugShowBodyText|dbIndex|sqlLog|sqlLogMode|content';
const TOKEN_VALID_LIST = 'sql|twig|head|althead|altsql|tail|shead|stail|rbeg|rend|renr|rsep|fbeg|fend|fsep|fskipwrap|rbgd|debug|form|r|debugShowBodyText|dbIndex|sqlLog|sqlLogMode|content|render';
const TOKEN_COLUMN_CTRL = '_';
......
......@@ -27,7 +27,6 @@ use IMATHUZH\Qfq\Core\Store\FillStoreForm;
use IMATHUZH\Qfq\Core\Store\Session;
use IMATHUZH\Qfq\Core\Store\Sip;
use IMATHUZH\Qfq\Core\Store\Store;
use IMATHUZH\Qfq\Core\Typo3\T3Handler;
/*
* Form will be called
......@@ -244,13 +243,20 @@ class QuickFormQuery {
public function process() {
$html = '';
$render = $this->store->getVar(SYSTEM_RENDER, STORE_TYPO3 . STORE_SYSTEM);
if ($render == SYSTEM_RENDER_API && isset($GLOBALS['TYPO3_CONF_VARS'])) {
return '';
}
if ($this->store->getVar(TYPO3_DEBUG_SHOW_BODY_TEXT, STORE_TYPO3) === 'yes') {
$htmlId = HelperFormElement::buildFormElementId($this->formSpec[F_ID], 0, 0, 0);
$html .= Support::doTooltip($htmlId . HTML_ID_EXTENSION_TOOLTIP, $this->t3data['bodytext']);
}
$html .= $this->doForm(FORM_LOAD);
$html .= $this->doReport();
if ($render == SYSTEM_RENDER_BOTH || $render == SYSTEM_RENDER_API || ($render == SYSTEM_RENDER_SINGLE && $html == '')) {
$html .= $this->doReport();
}
// Only needed if there are potential 'download'-links, which shall show a popup during processing of the download.
if ($this->store->getVar(SYSTEM_DOWNLOAD_POPUP, STORE_SYSTEM) == DOWNLOAD_POPUP_REQUEST) {
......@@ -344,7 +350,7 @@ class QuickFormQuery {
$formModeNew = '';
$build = null;
$recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT . STORE_ZERO);
$recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT . STORE_ZERO, SANITIZE_ALLOW_DIGIT, $foundInStore);
$this->setParameterLanguageFieldName();
$formName = $this->loadFormSpecification($formMode, $recordId, $foundInStore, $formLogMode);
......
......@@ -311,6 +311,7 @@ class Config {
SYSTEM_DB_INDEX_DATA => DB_INDEX_DEFAULT,
SYSTEM_DB_INDEX_QFQ => DB_INDEX_DEFAULT,
SYSTEM_RENDER => SYSTEM_RENDER_SINGLE,
SYSTEM_DATE_FORMAT => 'yyyy-mm-dd',
SYSTEM_SHOW_DEBUG_INFO => SYSTEM_SHOW_DEBUG_INFO_AUTO,
SYSTEM_MAIL_LOG => SYSTEM_MAIL_LOG_FILE,
......
......@@ -9,7 +9,6 @@
namespace IMATHUZH\Qfq\Tests\Unit\Core\Store;
use IMATHUZH\Qfq\Core\Database\Database;
use IMATHUZH\Qfq\Core\Store\Store;
use PHPUnit\Framework\TestCase;
......@@ -410,6 +409,7 @@ class StoreTest extends TestCase {
SYSTEM_SECURITY_FAILED_AUTH_DELAY => '3',
SYSTEM_SQL_LOG_MODE_AUTOCRON => 'error',
F_CLASS => 'qfq-notify',
SYSTEM_RENDER => SYSTEM_RENDER_SINGLE,
];
......
Supports Markdown
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