Commit dfc4ef75 authored by Marc Egger's avatar Marc Egger
Browse files

Refs #12145 Display the backup path in json form-editor and add documentation

parent 4491fbe6
Pipeline #5115 failed with stages
in 2 minutes and 47 seconds
......@@ -99,7 +99,7 @@ General
* With the `Dynamic` option, it's easily possible to use one Typo3 page and display different forms on that specific
page.
* Forms are synced between the database and form files. See :ref:`formAsfile`.
* If a form is edited using the json form editor then a backup of the previous version is saved. See :ref:`formAsFile`.
Form process order
------------------
......@@ -2295,7 +2295,7 @@ Most of the slaveId concept is part of sqlInsert / sqlUpdate - see below.
After an INSERT (= *sqlInsert*) the `last_insert_id()` is copied to *{{slaveId:V}}* automatically.
FormElement.parameter: sqlBefore / sqlInsert / sqlUpdate / sqlDelete / sqlAfter
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.. tip::
......@@ -2395,6 +2395,16 @@ Situation 2: master.id=slave.xId (1:n)
# For Templategroups: sqlHonorFormElements = myStreet%d, myCity%d
FormElement.parameter: saveFormJson, saveFormJsonName (System)
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
* *FormElement.parameter.saveFormJson* and *FormElement.parameter.saveFormJsonName*
* These parameters are used in the json form editor. See :ref:`formAsFile`.
* If both parameters are present in an action FormElement then the form with name given by `saveFormJsonName` is
overwritten by the json string given by `saveFormJson` when the action element is processed.
* A backup of the previous version of the form is saved before overwriting. See :ref:`formAsFile`.
Type: sendmail
^^^^^^^^^^^^^^
......@@ -3505,8 +3515,6 @@ Table: Person
Import/merge form
-----------------
* ATTENTION * : This currently does not work. To copy merge forms you may just copy/merge the form files. See :ref:`formAsFile`.
The form `copyFormFromExt` copies a form from table `ExtForm / ExtFormElement` to `Form / FormElement`. The import/merge
form:
......@@ -3532,19 +3540,41 @@ If there are several T3/QFQ instances and if forms should be imported frequently
20.sql = CREATE OR REPLACE table ExtFormElement SELECT * FROM <db xyz>.FormElement
.. _`formAsFile`
.. _`formAsFile`:
Form As File
------------
Json Form Editor
^^^^^^^^^^^^^^^^
The json form editor allows developers to view/edit/copy/paste forms in the json format.
* The json form editor can be accessed via the standard form-editor report. See: :ref:`form-editor`
* All fields of the Form and the FormElements Table are encoded into one big json object. Each formElement is represented as an object contained in the top-level array called `FormElement_ff`.
* Form and FormElement **ids are not encoded into the json string**. Therefore the json may be freely copied and pasted i.e. reused without fear of overwriting the original form.
* **Container** : Container FormElements are referenced via their name instead of their id by other FormElements. The additional key `containerName_ff` is added to the json of a FormElemnt to reference a container.
* **Form Backups** : If a form is edited using the json form editor then a backup of the previous version is saved in the directory `form/.backup` inside the qfq project directory (:ref:`qfq-project-path-php`).
* Cron job to remove old backups: :ref:`removeFormBackupCron`
Auto Sync
^^^^^^^^^
**ATTENTION** : The synchronisation between form files and Form/FormElement tables has been disabled in favor of the json form editor. It might be enabled again in a future version.
* **Sync** : Forms are synced between the database and form files located in the form directory contained in the qfq project directory. See: :ref:`qfq-project-path-php`
* The form files have precedence over database forms. i.e. If the form has changed both in the file and database since the last sync, then the database changes are lost. (But there is a backup, see bellow).
* If a form exists in the database but was never exported to a file (i.e. column `fileStats` in the Form table is empty) then the form is not deleted but kept and exported to a new form file.
* **ATTENTION** : Form and FormElement changes in the database are only registered if they are performed by the form editor. Otherwise they might get overwritten during the next file sync!
* **First Export** : If there is no form directory then it is created and all forms are exported from the database once.
* **Form Backups** : On every change of a form (both in file and in database) a new backup file is saved in `qfqProject/form/.backup`
* To restore a backup file just copy it into the parent folder (`form`) and rename it to `<formName>.json`. (Don't forget to adjust the file read/write rights accordingly)
* Cron job to remove old backups: :ref:`removeFormBackupCron`
* **Form Copy** : To copy a form simply duplicate the corresponding form file `<formName>.json` and rename the duplicate accordingly `<newFormName>.json>`. (Don't forget to adjust the file read/write rights accordingly)
......@@ -205,7 +205,7 @@ Setup
* If the Extension Manager stops after importing: check your memory limit in php.ini.
* Copy/rename the file *<site path>/typo3conf/ext/qfq/example.qfq.json* to *<site path>/fileadmin/protected/qfqProject/qfq.json*.
* Copy/rename the file *<site path>/fileadmin/protected/qfqProject/conf/example.qfq.json* to *<site path>/fileadmin/protected/qfqProject/conf/qfq.json*.
Configure the necessary settings :ref:`configuration`
The configuration file is outside of the extension directory, to not loose it during de-install and install again.
......@@ -276,10 +276,6 @@ Setup a *report* to manage all *forms*:
file=_formEditor
To keep the overview about all forms, it's useful to know which form has been used, how often, on which
page and when. Find these information included in the :ref:`form-editor-usage` report.
.. _install-checklist:
Installation: Check List
......@@ -300,11 +296,14 @@ Installation: Check List
Configuration
-------------
.. _qfq-project-path-php
.. _qfq-project-path-php:
qfq.project.path.php
^^^^^^^^^^^^^^^^^^^^
The file `qfq.project.path.php` provides the path to the qfqProject directory.
* The qfqProject directory contains the qfq configuration file (see :ref:`qfq.json`) as well as forms and reports which are saved as files. See :ref:`formAsFile` and :ref:`reportAsFile`.
* The file `qfq.project.path.php` is located/created in the root directory of the application. (Where index.php is located)
* This file only returns the path to the qfq project directory where logs, config (`qfq.json`), report files and form files are located.
* If the file does not exist, it is created and the project path is set as follows:
......@@ -325,7 +324,7 @@ Example: *typo3conf/config.qfq.php*: ::
return 'fileadmin/protected/qfqProject'; // path relative to app directory (i.e. location of this file).
.. _qfq.json
.. _qfq.json:
qfq.json
^^^^^^^^
......@@ -719,3 +718,13 @@ Specifying a higher value produces an error in the front end.
Every access to QFQ related content resets the timeout.
After FE login, the next access to QFQ related content starts the timeout counter.
.. _`removeFormBackupCron`:
Cron Job: Remove Form Backup Files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following cron job may be used to automatically remove form backup files (see :ref:`formAsFile`) which are older than 31 days. Be sure to adjust the path accordingly: ::
0 19 * * * find /var/www/html/fileadmin/protected/qfqProject/form/.backup/ -type f -mtime +31 -exec rm {} \;
......@@ -698,6 +698,8 @@ Summary:
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|_<nonReservedName> |Suppress output. Column names with leading underscore are used to select data from the database and make it available in other parts of the report without generating any output. |
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|_formJson[Base64] |System internal. Return form with given id as json string (`SELECT '<formId>' AS _formJson`). `_formJsonBase64` returns the json string encoded in base 64. |
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
.. _column-link:
......@@ -3051,6 +3053,8 @@ Report As File
* The path of the created file is given by the typo3 page structure
* The tt-content element body is replaced with `file=<path-to-new-file>`
* **Backups** : Whenever a report file is edited via the frontend report editor then a backup of the previous version is saved in the `.backup` directory located in the same directory as the report file.
Example tt-content body::
file=Home/myPage/qfq-report.qfqr
......
......@@ -327,9 +327,15 @@ Store: *SYSTEM* - Y
* Sanitized: *no*
See :ref:`configuration` for a list of all settings.
All settings can be accessed via this store. See :ref:`configuration` for a list of all settings.
Additional variables:
+-------------------------+------------------------------------------------------------------------------+
| Name | Explanation |
+=========================+==============================================================================+
| qfqProjectPath | Absolute path to the qfq project directory. See :ref:`qfq-project-path-php` |
+-------------------------+------------------------------------------------------------------------------+
.. _STORE_USER:
......@@ -343,4 +349,4 @@ As soon as a value is set in the store, it remains as long as the browser sessio
Values can be set in report via ``... AS "_=<var name>"``
See also: :ref:`store_user_examples`
\ No newline at end of file
See also: :ref:`store_user_examples`
......@@ -38,94 +38,6 @@
System
======
.. _form-editor-usage:
FormEditor with usage
---------------------
With a large number of forms, it's important to know how often a form has been used, on which pages it's used and when
has the form be used. The following report includes the regular :ref:`form-editor` as well::
#
# Form
#
# a) List of forms: {{form:S}}='', {{formIdHistory:S}}=''
# b) Edit Form: {{form:S}} - Open form {{form:S}} with record {{r:S}} - typically the FormEditor
# c) Use history of a given form: {{formIdHistory:S}}
#
# {{form:S}}
# {{formIdHistory:S0}} - usage history of form '{{formIdHistory:S}}'
form={{form:SE}}
10 {
# List of Forms: Do not show this list of forms if there is a form given by SIP.
# Table header.
sql = SELECT '<th data-sorter="false" class="filter-false">'
, CONCAT('p:{{pageAlias:T}}&form=Form&') as _pagen
, '</th><th>Name'
, '</th><th>Title'
, '</th><th>Table'
, '</th><th>#'
, '</th><th><em>First</em>'
, '</th><th><em>Last</em>'
, '</th><th><em>PageId</em></th>'
FROM (SELECT '') AS fake
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>
tail = </tbody></table>
20 {
# All forms
sql = SELECT CONCAT('p:{{pageAlias:T}}&form=Form&r=', f.id) as _pagee
, CONCAT(f.name, ' <span class="text-muted">(', f.id, ')</span>')
, QMORE(strip_tags(f.title),50)
, f.tableName
, CONCAT('p:{{pageAlias:T}}&formIdHistory=', f.id, '|s|b|t:<span class="badge">', COUNT(fsl.id), '</span>'
, IF(COUNT(fsl.id)=0, '|r:3','') ) as _link
, CONCAT( '<em><span title="',MIN(fsl.created), '">', DATE_FORMAT( MIN( fsl.created), '%d.%m.%Y'), '</span></em>')
, CONCAT( '<em><span title="',MAX(fsl.created), '">', DATE_FORMAT( MAX( fsl.created), '%d.%m.%Y'), '</span></em>')
, CONCAT('<em>', GROUP_CONCAT(DISTINCT fsl.pageId ORDER BY fsl.pageId), '<em>')
FROM Form AS f
LEFT JOIN FormSubmitLog AS fsl
ON fsl.formId=f.id
WHERE {{formIdHistory:S0}}=0
GROUP BY f.id
ORDER BY f.name
rbeg = <tr>
rend = </tr>
fbeg = <td>
fend = </td>
}
}
30 {
# History of a Form {{formIdHistory:S0}}
sql = SELECT f.name
, fsl.feUser
, fsl.recordId
, fsl.pageId
, fsl.created
FROM FormSubmitLog AS fsl, Form AS f
WHERE fsl.formId={{formIdHistory:S0}}
AND fsl.formId=f.id
ORDER BY fsl.created DESC
head = <table class="table table-hover qfq-table-50 tablesorter tablesorter-filter" id="{{pageAlias:T}}-formHistory">
<thead class="qfq-sticky"><tr><th>Form</th><th>feUser</th><th>recordId</th><th>pageId</th><th>Submit</th></tr></thead><tbody>
tail = </tbody></table>
rbeg = <tr>
rend = </tr>
fbeg = <td>
fend = </td>
altsql = SELECT IF('{{formIdHistory:S0}}'='0', '', '<div class="alert alert-warning">History is empty</div>')
}
.. _`autocron`:
AutoCron
......
......@@ -691,6 +691,8 @@ const CSS_REQUIRED_LEFT = 'required-left';
//const SYSTEM_FORM_ELEMENT_DEF = 'formElementDefinition'; // Type: SANITIZE_ALL / AssocArray. Formelement which are processed at the moment. Useful for error reporting.
//const SYSTEM_FORM_ELEMENT_FIELD = 'formElementField'; // Type: SANITIZE_ALNUMX / String. Fieldname of processed Formelement. Useful for error reporting.
const SYSTEM_QFQ_PROJECT_PATH = 'qfqProjectPath';
const MODE_HTML = 'html';
const MODE_JSON = 'json';
......
......@@ -329,6 +329,7 @@ class Store {
private static function fillStoreSystem($PhpUnitOverloadAbsoluteConfigFilePath = '') {
$config = Config::getConfigArray($PhpUnitOverloadAbsoluteConfigFilePath);
$config[SYSTEM_QFQ_PROJECT_PATH] = Path::absoluteProject();
self::setStore($config, STORE_SYSTEM, true);
}
......
......@@ -29,7 +29,7 @@
"parameterLanguageD": "",
"recordLockTimeoutSeconds": 900,
"deleted": "no",
"modified": "2021-03-22 15:36:04",
"modified": "2021-04-08 09:41:26",
"created": "2021-03-22 11:42:00",
"FormElement_ff": [
{
......@@ -69,7 +69,7 @@
"clientJs": "",
"feGroup": "",
"deleted": "no",
"modified": "2021-03-29 11:00:19",
"modified": "2021-04-08 10:32:57",
"created": "2021-03-22 11:57:51"
},
{
......@@ -99,7 +99,7 @@
"adminNote": "",
"tooltip": "",
"placeholder": "",
"value": "#!report\r\n\r\n10.sql = SELECT {{r:S0}} AS _formJson\r\n\r\n15.sql = SELECT IF({{r:S0}}=0, 'Plsease save this form first.', '')",
"value": "#!report\r\n\r\n10.sql = SELECT {{r:S0}} AS _formJson\r\n\r\n15.sql = SELECT IF({{r:S0}}=0, 'Please save this form first.', '')",
"sql1": "",
"parameter": "",
"parameterLanguageA": "",
......@@ -109,7 +109,7 @@
"clientJs": "",
"feGroup": "",
"deleted": "no",
"modified": "2021-03-30 09:36:37",
"modified": "2021-04-08 10:45:40",
"created": "2021-03-22 11:44:22"
},
{
......@@ -149,7 +149,7 @@
"clientJs": "",
"feGroup": "",
"deleted": "no",
"modified": "2021-03-29 14:04:12",
"modified": "2021-04-08 09:41:26",
"created": "2021-03-24 14:44:04"
},
{
......@@ -189,7 +189,7 @@
"clientJs": "",
"feGroup": "",
"deleted": "no",
"modified": "2021-03-30 09:13:40",
"modified": "2021-04-08 09:41:26",
"created": "2021-03-30 09:13:40"
},
{
......@@ -229,8 +229,48 @@
"clientJs": "",
"feGroup": "",
"deleted": "no",
"modified": "2021-03-30 09:14:48",
"modified": "2021-04-08 09:41:26",
"created": "2021-03-30 09:14:48"
},
{
"dynamicUpdate": "no",
"enabled": "yes",
"name": "myBackupNote",
"label": "Backups",
"mode": "show",
"modeSql": "",
"class": "native",
"type": "note",
"subrecordOption": "",
"encode": "specialchar",
"checkType": "auto",
"checkPattern": "",
"onChange": "",
"ord": 60,
"tabindex": 0,
"size": "",
"maxLength": "",
"labelAlign": "default",
"bsLabelColumns": "",
"bsInputColumns": "",
"bsNoteColumns": "",
"rowLabelInputNote": "row,label,\/label,input,\/input,note,\/note,\/row",
"note": "",
"adminNote": "",
"tooltip": "",
"placeholder": "",
"value": "{{ SELECT IF('{{id:RE}}'!='', 'Form backup location: {{qfqProjectPath:Y}}\/form\/.backup\/{{id:RE}}\/', 'Please save this form first.') }}",
"sql1": "",
"parameter": "",
"parameterLanguageA": "",
"parameterLanguageB": "",
"parameterLanguageC": "",
"parameterLanguageD": "",
"clientJs": "",
"feGroup": "",
"deleted": "no",
"modified": "2021-04-08 12:40:55",
"created": "2021-04-08 10:40:09"
}
]
}
\ No newline at end of file
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