Commit 9341c03f authored by Carsten  Rose's avatar Carsten Rose
Browse files

Merge branch 'develop' into 'master'

Develop

See merge request !251
parents 36e6c456 af5b9e6b
Pipeline #3223 passed with stages
in 3 minutes and 27 seconds
......@@ -9,7 +9,7 @@ variables:
stages:
- before
- build
# - selenium
- selenium
documentation:
stage: before
......@@ -48,29 +48,30 @@ release:
- scp qfq_${VERSION}_*.zip w16:qfq/releases/
- mv qfq_${VERSION}_*.zip build/qfq.zip
# selenium:
# stage: selenium
# script:
# - unzip -q build/qfq.zip -d qfq
# - cd docker/
# - ./run_qfq_docker.sh -no-deploy
# - ./deploy_to_container.sh ../qfq
# - ./run_selenium_tests_docker.sh
# - echo "hello"
# after_script:
# # remove containers and move logs to persistent location
# - cd docker; ./remove-containers.sh <<< "y"
# - cd ..
# - umask 002
# - mkdir "$SELENIUM_LOGS_PATH/$CI_COMMIT_SHORT_SHA"
# - cp extension/Tests/selenium/selenium_logs/* "$SELENIUM_LOGS_PATH/$CI_COMMIT_SHORT_SHA/"
# - echo "Selenium Logs copied to $SELENIUM_LOGS_PATH/$CI_COMMIT_SHORT_SHA/"
# - echo "Or download result (log/screenshot) in gitlab under CI/CD > Pipelines <job> > right side 'Artifacts'"
selenium:
stage: selenium
script:
- unzip -q build/qfq.zip -d qfq
- cd docker/
- ./run_qfq_docker.sh -no-deploy
- ./deploy_to_container.sh ../qfq
- ./run_selenium_tests_docker.sh
- echo "hello"
after_script:
# remove containers and move logs to persistent location
- cd docker; ./remove-containers.sh <<< "y"
- cd ..
- umask 002
- mkdir "$SELENIUM_LOGS_PATH/$CI_COMMIT_SHORT_SHA"
- cp extension/Tests/selenium/selenium_logs/* "$SELENIUM_LOGS_PATH/$CI_COMMIT_SHORT_SHA/"
- echo "Selenium Logs copied to $SELENIUM_LOGS_PATH/$CI_COMMIT_SHORT_SHA/"
- echo "Or download result (log/screenshot) in gitlab under CI/CD > Pipelines <job> > right side 'Artifacts'"
# artifacts:
# expire_in: 1 week
# paths:
# - extension/Tests/selenium/selenium_logs/
artifacts:
expire_in: 1 week
when: on_failure
paths:
- extension/Tests/selenium/selenium_logs/
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="Definitions_1egqcwa" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="2.2.4">
<bpmn:collaboration id="Collaboration_0gqz3wa">
<bpmn:participant id="Participant_1d0jmhs" name="Form Load" processRef="Process_1" />
<bpmn:participant id="Participant_16ldzur" name="Form Save" processRef="Process_0tyry81" />
<bpmn:participant id="Participant_0jwt14j" name="Form Delete" processRef="Process_1f1bv9d" />
</bpmn:collaboration>
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_18h7xec</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Task_087ysca" name="FE Action: beforeLoad">
<bpmn:incoming>SequenceFlow_18h7xec</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_1i2qd5c</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_0zvugq3" name="BuildForm">
<bpmn:incoming>SequenceFlow_1i2qd5c</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_087ugzg</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_19kacyh" name="FE Action: afterLoad">
<bpmn:incoming>SequenceFlow_087ugzg</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_1fuoqzt</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_156p4pi" name="Show Form">
<bpmn:incoming>SequenceFlow_1fuoqzt</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_0unt63n</bpmn:outgoing>
</bpmn:task>
<bpmn:endEvent id="EndEvent_0o91ed3">
<bpmn:incoming>SequenceFlow_0unt63n</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="SequenceFlow_18h7xec" sourceRef="StartEvent_1" targetRef="Task_087ysca" />
<bpmn:sequenceFlow id="SequenceFlow_1i2qd5c" sourceRef="Task_087ysca" targetRef="Task_0zvugq3" />
<bpmn:sequenceFlow id="SequenceFlow_087ugzg" sourceRef="Task_0zvugq3" targetRef="Task_19kacyh" />
<bpmn:sequenceFlow id="SequenceFlow_1fuoqzt" sourceRef="Task_19kacyh" targetRef="Task_156p4pi" />
<bpmn:sequenceFlow id="SequenceFlow_0unt63n" sourceRef="Task_156p4pi" targetRef="EndEvent_0o91ed3" />
<bpmn:textAnnotation id="TextAnnotation_09ovyvr">
<bpmn:text>incl. all Template Groups, Pills and Fieldsets</bpmn:text>
</bpmn:textAnnotation>
<bpmn:association id="Association_0az66lx" sourceRef="Task_0zvugq3" targetRef="TextAnnotation_09ovyvr" />
</bpmn:process>
<bpmn:process id="Process_0tyry81" isExecutable="false">
<bpmn:startEvent id="StartEvent_09cyjcj">
<bpmn:outgoing>SequenceFlow_1clg7oh</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Task_0qkggn2" name="FE Action: beforeSave, beforeInsert, beforeUpdate">
<bpmn:incoming>SequenceFlow_1clg7oh</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_1b7k0nc</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_1clg7oh" sourceRef="StartEvent_09cyjcj" targetRef="Task_0qkggn2" />
<bpmn:task id="Task_0jjjjc4" name="Collect FE Native (column in primary table). &#10;Write data to primary table">
<bpmn:incoming>SequenceFlow_1b7k0nc</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_0nf0hx1</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_1b7k0nc" sourceRef="Task_0qkggn2" targetRef="Task_0jjjjc4" />
<bpmn:task id="Task_0rqrevv" name="Do sqlBefore, sqlInsert/sqlUpdate, sqlDelete, sqlAfter">
<bpmn:incoming>SequenceFlow_0nf0hx1</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_0qljx5b</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_0nf0hx1" sourceRef="Task_0jjjjc4" targetRef="Task_0rqrevv" />
<bpmn:task id="Task_01k0x08" name="Do FE upload">
<bpmn:incoming>SequenceFlow_0qljx5b</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_14n2tiv</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_0qljx5b" sourceRef="Task_0rqrevv" targetRef="Task_01k0x08" />
<bpmn:task id="Task_1gou88c" name="Do FE Action: afterSave, afterUpdate, afterInsert, sendmail">
<bpmn:incoming>SequenceFlow_14n2tiv</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_0wg7tov</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_14n2tiv" sourceRef="Task_01k0x08" targetRef="Task_1gou88c" />
<bpmn:task id="Task_0om9ezo" name="Paste QFQ Record Clipboard">
<bpmn:incoming>SequenceFlow_0wg7tov</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_1d0mgd0</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_0wg7tov" sourceRef="Task_1gou88c" targetRef="Task_0om9ezo" />
<bpmn:endEvent id="EndEvent_18haf6h">
<bpmn:incoming>SequenceFlow_1d0mgd0</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="SequenceFlow_1d0mgd0" sourceRef="Task_0om9ezo" targetRef="EndEvent_18haf6h" />
<bpmn:association id="Association_1c19y0j" sourceRef="Task_0rqrevv" targetRef="TextAnnotation_1p9ftgc" />
<bpmn:textAnnotation id="TextAnnotation_1p9ftgc">
<bpmn:text>FE native</bpmn:text>
</bpmn:textAnnotation>
<bpmn:association id="Association_0yrxesu" sourceRef="Task_1gou88c" targetRef="TextAnnotation_0kybenx" />
<bpmn:textAnnotation id="TextAnnotation_0kybenx">
<bpmn:text>E.g.: Non primary table columns</bpmn:text>
</bpmn:textAnnotation>
</bpmn:process>
<bpmn:process id="Process_1f1bv9d" isExecutable="false">
<bpmn:startEvent id="StartEvent_0my9753">
<bpmn:outgoing>SequenceFlow_1s6gjr4</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Task_0u53rg6" name="FE Action: beforeDelete">
<bpmn:incoming>SequenceFlow_1s6gjr4</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_1myjsww</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_1cuzajj" name="Delete Record">
<bpmn:incoming>SequenceFlow_1myjsww</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_01wmt7s</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_1fy0529" name="FE Action: afterDelete">
<bpmn:incoming>SequenceFlow_01wmt7s</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_1wxchhg</bpmn:outgoing>
</bpmn:task>
<bpmn:endEvent id="EndEvent_1ky7g3k">
<bpmn:incoming>SequenceFlow_1wxchhg</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="SequenceFlow_1s6gjr4" sourceRef="StartEvent_0my9753" targetRef="Task_0u53rg6" />
<bpmn:sequenceFlow id="SequenceFlow_1myjsww" sourceRef="Task_0u53rg6" targetRef="Task_1cuzajj" />
<bpmn:sequenceFlow id="SequenceFlow_01wmt7s" sourceRef="Task_1cuzajj" targetRef="Task_1fy0529" />
<bpmn:sequenceFlow id="SequenceFlow_1wxchhg" sourceRef="Task_1fy0529" targetRef="EndEvent_1ky7g3k" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_0gqz3wa">
<bpmndi:BPMNShape id="Participant_1d0jmhs_di" bpmnElement="Participant_1d0jmhs">
<dc:Bounds x="123" y="89" width="1137" height="242" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="172" y="195" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Participant_16ldzur_di" bpmnElement="Participant_16ldzur">
<dc:Bounds x="123" y="332" width="1138" height="234" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Participant_0jwt14j_di" bpmnElement="Participant_0jwt14j">
<dc:Bounds x="123" y="561" width="1138" height="200" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_087ysca_di" bpmnElement="Task_087ysca">
<dc:Bounds x="258" y="173" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_18h7xec_di" bpmnElement="SequenceFlow_18h7xec">
<di:waypoint x="208" y="213" />
<di:waypoint x="258" y="213" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_0zvugq3_di" bpmnElement="Task_0zvugq3">
<dc:Bounds x="408" y="173" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1i2qd5c_di" bpmnElement="SequenceFlow_1i2qd5c">
<di:waypoint x="358" y="213" />
<di:waypoint x="408" y="213" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_19kacyh_di" bpmnElement="Task_19kacyh">
<dc:Bounds x="558" y="173" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_087ugzg_di" bpmnElement="SequenceFlow_087ugzg">
<di:waypoint x="508" y="213" />
<di:waypoint x="558" y="213" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_156p4pi_di" bpmnElement="Task_156p4pi">
<dc:Bounds x="704" y="173" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1fuoqzt_di" bpmnElement="SequenceFlow_1fuoqzt">
<di:waypoint x="658" y="213" />
<di:waypoint x="704" y="213" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="EndEvent_0o91ed3_di" bpmnElement="EndEvent_0o91ed3">
<dc:Bounds x="850" y="195" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0unt63n_di" bpmnElement="SequenceFlow_0unt63n">
<di:waypoint x="804" y="213" />
<di:waypoint x="850" y="213" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="TextAnnotation_09ovyvr_di" bpmnElement="TextAnnotation_09ovyvr">
<dc:Bounds x="418" y="109" width="170" height="41" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Association_0az66lx_di" bpmnElement="Association_0az66lx">
<di:waypoint x="480" y="173" />
<di:waypoint x="492" y="150" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="StartEvent_09cyjcj_di" bpmnElement="StartEvent_09cyjcj">
<dc:Bounds x="185" y="440" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_0qkggn2_di" bpmnElement="Task_0qkggn2">
<dc:Bounds x="271" y="418" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1clg7oh_di" bpmnElement="SequenceFlow_1clg7oh">
<di:waypoint x="221" y="458" />
<di:waypoint x="271" y="458" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_0jjjjc4_di" bpmnElement="Task_0jjjjc4">
<dc:Bounds x="421" y="418" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1b7k0nc_di" bpmnElement="SequenceFlow_1b7k0nc">
<di:waypoint x="371" y="458" />
<di:waypoint x="421" y="458" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_01k0x08_di" bpmnElement="Task_01k0x08">
<dc:Bounds x="712" y="418" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_0rqrevv_di" bpmnElement="Task_0rqrevv">
<dc:Bounds x="563" y="418" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0nf0hx1_di" bpmnElement="SequenceFlow_0nf0hx1">
<di:waypoint x="521" y="458" />
<di:waypoint x="563" y="458" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="TextAnnotation_1p9ftgc_di" bpmnElement="TextAnnotation_1p9ftgc">
<dc:Bounds x="563" y="355" width="100" height="30" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Association_1c19y0j_di" bpmnElement="Association_1c19y0j">
<di:waypoint x="613" y="418" />
<di:waypoint x="613" y="385" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_0qljx5b_di" bpmnElement="SequenceFlow_0qljx5b">
<di:waypoint x="663" y="458" />
<di:waypoint x="712" y="458" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_1gou88c_di" bpmnElement="Task_1gou88c">
<dc:Bounds x="861" y="418" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_14n2tiv_di" bpmnElement="SequenceFlow_14n2tiv">
<di:waypoint x="812" y="458" />
<di:waypoint x="861" y="458" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_0om9ezo_di" bpmnElement="Task_0om9ezo">
<dc:Bounds x="1010" y="418" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0wg7tov_di" bpmnElement="SequenceFlow_0wg7tov">
<di:waypoint x="961" y="458" />
<di:waypoint x="1010" y="458" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="EndEvent_18haf6h_di" bpmnElement="EndEvent_18haf6h">
<dc:Bounds x="1159" y="440" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1d0mgd0_di" bpmnElement="SequenceFlow_1d0mgd0">
<di:waypoint x="1110" y="458" />
<di:waypoint x="1159" y="458" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="TextAnnotation_0kybenx_di" bpmnElement="TextAnnotation_0kybenx">
<dc:Bounds x="792" y="355" width="238" height="30" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Association_0yrxesu_di" bpmnElement="Association_0yrxesu">
<di:waypoint x="911" y="418" />
<di:waypoint x="911" y="385" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="StartEvent_0my9753_di" bpmnElement="StartEvent_0my9753">
<dc:Bounds x="188" y="639" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_0u53rg6_di" bpmnElement="Task_0u53rg6">
<dc:Bounds x="274" y="617" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1cuzajj_di" bpmnElement="Task_1cuzajj">
<dc:Bounds x="424" y="617" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1fy0529_di" bpmnElement="Task_1fy0529">
<dc:Bounds x="574" y="617" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_1ky7g3k_di" bpmnElement="EndEvent_1ky7g3k">
<dc:Bounds x="719" y="639" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1s6gjr4_di" bpmnElement="SequenceFlow_1s6gjr4">
<di:waypoint x="224" y="657" />
<di:waypoint x="274" y="657" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_1myjsww_di" bpmnElement="SequenceFlow_1myjsww">
<di:waypoint x="374" y="657" />
<di:waypoint x="424" y="657" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_01wmt7s_di" bpmnElement="SequenceFlow_01wmt7s">
<di:waypoint x="524" y="657" />
<di:waypoint x="574" y="657" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_1wxchhg_di" bpmnElement="SequenceFlow_1wxchhg">
<di:waypoint x="674" y="657" />
<di:waypoint x="719" y="657" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
......@@ -40,4 +40,5 @@ Software distributed together with QFQ
* Twig - https://twig.symfony.com
* Twitter typeahead JS - https://twitter.github.io/typeahead.js/
* bootstrap-validator.js - https://github.com/1000hz/bootstrap-validator
* Event Emitter - https://git.io/ee
\ No newline at end of file
* Event Emitter - https://git.io/ee
* FullCalendar - https://fullcalendar.io/
This diff is collapsed.
......@@ -265,6 +265,38 @@ module.exports = function (grunt) {
}
]
},
fullCalendar: {
files: [
{
cwd: 'node_modules/fullcalendar/dist',
src: '*.min.js',
dest: typo3_js,
expand: true,
flatten: false
},
{
cwd: 'node_modules/fullcalendar/dist',
src: '*.min.css',
dest: typo3_css,
expand: true,
flatten: false
},
{
cwd: 'node_modules/fullcalendar/dist',
src: '*.min.*',
dest: "js/",
expand: true,
flatten: false
},
{
cwd: 'node_modules/moment/min',
src: 'moment.min.js',
dest: typo3_js,
expand: true,
flatten: false
},
]
},
eventEmitter: {
files: [
{
......
This diff is collapsed.
This diff is collapsed.
......@@ -56,14 +56,14 @@ ENGINE=$2
# checks if an engine is not specified
if [ -z $ENGINE ]; then
# defines the default engine to use during tests
export BROWSER=$DEFAULT_ENGINE
export SELENIUM_BROWSER=$DEFAULT_ENGINE
# defines the path to the drivers of the engine
export DRIVER_PATH="${PWD}/${DEFAULT_ENGINE}driver"
export SELENIUM_DRIVER_PATH="${PWD}/${DEFAULT_ENGINE}driver"
else
# defines the engine to use during tests
export BROWSER=$ENGINE
export SELENIUM_BROWSER=$ENGINE
# defines the path to the drivers of the engine
export DRIVER_PATH="${PWD}/${ENGINE}driver"
export SELENIUM_DRIVER_PATH="${PWD}/${ENGINE}driver"
fi
# stores the default headless option
......
......@@ -253,7 +253,7 @@ abstract class AbstractBuildForm {
$this->store->setStore($row, STORE_PARENT_RECORD, true);
$this->store->setVar(F_MULTI_COL_ID, $row[$idName], STORE_PARENT_RECORD); // In case '_id' is used, both '_id' and 'id' should be accessible.
$record = $this->dbArray[$this->dbIndexData]->sql('SELECT * FROM `' . $this->formSpec[F_TABLE_NAME] . '` WHERE id=' . $row[F_MULTI_COL_ID], ROW_EXPECT_1);
$record = $this->dbArray[$this->dbIndexData]->sql('SELECT * FROM `' . $this->formSpec[F_TABLE_NAME] . '` WHERE `id`=' . $row[F_MULTI_COL_ID], ROW_EXPECT_1);
$this->store->setStore($record, STORE_RECORD, true);
$jsonTmp = array();
......@@ -555,7 +555,7 @@ abstract class AbstractBuildForm {
$record = array();
if ($recordId != 0) {
$record = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE $primaryKey=?", ROW_EXPECT_1, [$recordId], "Record to load not found.");
$record = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM `$tableName` WHERE `$primaryKey`=?", ROW_EXPECT_1, [$recordId], "Record to load not found.");
}
return OnArray::getMd5($record);
......@@ -742,7 +742,7 @@ abstract class AbstractBuildForm {
$primaryKey = $this->formSpec[F_PRIMARY_KEY];
if ($recordId > 0 && $this->store->getVar($primaryKey, STORE_RECORD) === false) {
$tableName = $this->formSpec[F_TABLE_NAME];
$row = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE $primaryKey = ?", ROW_EXPECT_1,
$row = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM `$tableName` WHERE `$primaryKey` = ?", ROW_EXPECT_1,
array($recordId), "Form '" . $this->formSpec[F_NAME] . "' failed to load record '$primaryKey'='$recordId' from table '" .
$this->formSpec[F_TABLE_NAME] . "'.");
$this->store->setStore($row, STORE_RECORD);
......@@ -2108,7 +2108,7 @@ abstract class AbstractBuildForm {
} elseif (!empty($formElement[SUBRECORD_PARAMETER_FORM])) {
// Read table from form specified in subrecord
$formName = $formElement[SUBRECORD_PARAMETER_FORM];
$form = $this->dbArray[$this->dbIndexQfq]->sql("SELECT * FROM Form AS f WHERE f." . F_NAME . " LIKE ? AND f.deleted='no'",
$form = $this->dbArray[$this->dbIndexQfq]->sql("SELECT * FROM `Form` AS f WHERE `f`.`" . F_NAME . "` LIKE ? AND `f`.`deleted`='no'",
ROW_REGULAR, [$formName]);
if (count($form) > 0) {
$dndTable = $form[0][F_TABLE_NAME];
......@@ -2228,21 +2228,21 @@ abstract class AbstractBuildForm {
* @param array $formElement
* @param array $primaryRecord
* @param string $rcText
* @param string $nameColumnId
* @param string $rcNameColumnId
*
* @return bool
* @throws \UserFormException
*/
private function prepareSubrecord(array $formElement, array $primaryRecord, &$rcText, &$nameColumnId) {
private function prepareSubrecord(array $formElement, array $primaryRecord, &$rcText, &$rcNameColumnId) {
if (!isset($primaryRecord['id'])) {
if (!isset($primaryRecord[$rcNameColumnId])) {
$rcText = 'Please save this record first.';
return false;
}
if (!is_array($formElement[FE_SQL1])) {
throw new \UserFormException('Missing \'sql1\' Query', ERROR_MISSING_SQL1);
throw new \UserFormException('Missing \'sql1\' query', ERROR_MISSING_SQL1);
}
// No records?
......@@ -2253,17 +2253,16 @@ abstract class AbstractBuildForm {
}
// Check if $nameColumnId column exist.
if (!isset($formElement[FE_SQL1][0][$nameColumnId])) {
if (!isset($formElement[FE_SQL1][0][$rcNameColumnId])) {
// no: try fallback.
$nameColumnId = '_id';
$rcNameColumnId = '_' . $rcNameColumnId;
if (!isset($formElement[FE_SQL1][0][$rcNameColumnId])) {
throw new \UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => "Missing column $rcNameColumnId in subrecord query", ERROR_MESSAGE_TO_DEVELOPER => '']),
ERROR_SUBRECORD_MISSING_COLUMN_ID);
if (!isset($formElement[FE_SQL1][0][$nameColumnId])) {
throw new \UserFormException('Missing column \'id\' or \'_id\' in subrecord query', ERROR_SUBRECORD_MISSING_COLUMN_ID);
}
}
if (!isset($formElement[FE_SQL1][0][$nameColumnId])) {
throw new \UserFormException('Missing column \'id\' (or "_id") in \'sql1\' Query', ERROR_DB_MISSING_COLUMN_ID);
}
return true;
......@@ -2372,7 +2371,7 @@ abstract class AbstractBuildForm {
* @throws \UserFormException
*/
private function getFormTable($formName) {
$row = $this->dbArray[$this->dbIndexQfq]->sql("SELECT " . F_TABLE_NAME . " FROM Form AS f WHERE f.name = ?", ROW_EXPECT_0_1, [$formName]);
$row = $this->dbArray[$this->dbIndexQfq]->sql("SELECT `" . F_TABLE_NAME . "` FROM `Form` AS f WHERE `f`.`name` = ?", ROW_EXPECT_0_1, [$formName]);
if (isset($row[F_TABLE_NAME])) {
return $row[F_TABLE_NAME];
}
......
......@@ -252,7 +252,7 @@ class BuildFormBootstrap extends AbstractBuildForm {
break;
case 'formElement':
if (false !== ($formId = $this->store->getVar(FE_FORM_ID, STORE_SIP . STORE_RECORD))) {
$row = $this->dbArray[$this->dbIndexQfq]->sql("SELECT f.name FROM Form AS f WHERE id=" . $formId, ROW_EXPECT_1);
$row = $this->dbArray[$this->dbIndexQfq]->sql("SELECT `f`.`name` FROM `Form` AS f WHERE `id`=" . $formId, ROW_EXPECT_1);
$form = current($row);
}
break;
......
......@@ -63,15 +63,15 @@ const RETURN_URL = 'return_url';
const RETURN_SIP = 'return_sip';
const RETURN_ARRAY = 'return_array';
const SQL_FORM_ELEMENT_BY_ID = "SELECT * FROM FormElement AS fe WHERE fe.id = ?";
const SQL_FORM_ELEMENT_RAW = "SELECT * FROM FormElement AS fe WHERE fe.formId = ? AND fe.deleted = 'no' AND fe.enabled='yes' ORDER BY fe.ord, fe.id";
const SQL_FORM_ELEMENT_SPECIFIC_CONTAINER = "SELECT *, ? AS 'nestedInFieldSet' FROM FormElement AS fe WHERE fe.formId = ? AND fe.deleted = 'no' AND FIND_IN_SET(fe.class, ? ) AND fe.feIdContainer = ? AND fe.enabled='yes' ORDER BY fe.ord, fe.id";
const SQL_FORM_ELEMENT_ALL_CONTAINER = "SELECT *, ? AS 'nestedInFieldSet' FROM FormElement AS fe WHERE fe.formId = ? AND fe.deleted = 'no' AND FIND_IN_SET(fe.class, ? ) AND fe.enabled='yes' ORDER BY fe.ord, fe.id";
const SQL_FORM_ELEMENT_SIMPLE_ALL_CONTAINER = "SELECT fe.id, fe.feIdContainer, fe.name, fe.value, fe.label, fe.type, fe.encode, fe.checkType, fe.checkPattern, fe.mode, fe.modeSql, fe.parameter, fe.dynamicUpdate FROM FormElement AS fe, Form AS f WHERE f.name = ? AND f.id = fe.formId AND fe.deleted = 'no' AND fe.class = 'native' AND fe.enabled='yes' ORDER BY fe.ord, fe.id";
const SQL_FORM_ELEMENT_CONTAINER_TEMPLATE_GROUP = "SELECT fe.id, fe.name, fe.label, fe.maxLength, fe.parameter FROM FormElement AS fe, Form AS f WHERE f.name = ? AND f.id = fe.formId AND fe.deleted = 'no' AND fe.class = 'container' AND fe.type='templateGroup' AND fe.enabled='yes' ORDER BY fe.ord, fe.id";
const SQL_FORM_ELEMENT_TEMPLATE_GROUP_FE_ID = "SELECT * FROM FormElement AS fe WHERE fe.id = ? AND fe.deleted = 'no' AND fe.class = 'container' AND fe.type='templateGroup' AND fe.enabled='yes' ";
const SQL_FORM_ELEMENT_BY_ID = "SELECT * FROM `FormElement` AS fe WHERE `fe`.`id` = ?";
const SQL_FORM_ELEMENT_RAW = "SELECT * FROM `FormElement` AS `fe` WHERE `fe`.`formId` = ? AND `fe`.`deleted` = 'no' AND `fe`.`enabled`='yes' ORDER BY `fe`.`ord`, `fe`.`id`";
const SQL_FORM_ELEMENT_SPECIFIC_CONTAINER = "SELECT *, ? AS 'nestedInFieldSet' FROM `FormElement` AS fe WHERE `fe`.`formId` = ? AND `fe`.`deleted` = 'no' AND FIND_IN_SET(`fe`.`class`, ? ) AND `fe`.`feIdContainer` = ? AND `fe`.`enabled`='yes' ORDER BY `fe`.`ord`, `fe`.`id`";
const SQL_FORM_ELEMENT_ALL_CONTAINER = "SELECT *, ? AS 'nestedInFieldSet' FROM `FormElement` AS `fe` WHERE `fe`.`formId` = ? AND `fe`.`deleted` = 'no' AND FIND_IN_SET(`fe`.`class`, ? ) AND `fe`.`enabled`='yes' ORDER BY `fe`.`ord`, `fe`.`id`";
const SQL_FORM_ELEMENT_SIMPLE_ALL_CONTAINER = "SELECT `fe`.`id`, `fe`.`feIdContainer`, `fe`.`name`, `fe`.`value`, `fe`.`label`, `fe`.`type`, `fe`.`encode`, `fe`.`checkType`, `fe`.`checkPattern`, `fe`.`mode`, `fe`.`modeSql`, `fe`.`parameter`, `fe`.`dynamicUpdate` FROM `FormElement` AS fe, `Form` AS f WHERE `f`.`name` = ? AND `f`.`id` = `fe`.`formId` AND `fe`.`deleted` = 'no' AND `fe`.`class` = 'native' AND `fe`.`enabled`='yes' ORDER BY `fe`.`ord`, `fe`.`id`";
const SQL_FORM_ELEMENT_CONTAINER_TEMPLATE_GROUP = "SELECT `fe`.`id`, `fe`.`name`, `fe`.`label`, `fe`.`maxLength`, `fe`.`parameter` FROM `FormElement` AS fe, `Form` AS f WHERE `f`.`name` = ? AND `f`.`id` = `fe`.`formId` AND `fe`.`deleted` = 'no' AND `fe`.`class` = 'container' AND `fe`.`type`='templateGroup' AND `fe`.`enabled`='yes' ORDER BY `fe`.`ord`, `fe`.`id`";
const SQL_FORM_ELEMENT_TEMPLATE_GROUP_FE_ID = "SELECT * FROM `FormElement` AS fe WHERE `fe`.`id` = ? AND `fe`.`deleted` = 'no' AND `fe`.`class` = 'container' AND `fe`.`type`='templateGroup' AND `fe`.`enabled`='yes' ";
//const SQL_FORM_ELEMENT_NATIVE_TG_COUNT = "SELECT fe.*, IFNULL(feTg.maxLength,0) AS _tgCopies FROM FormElement AS fe LEFT JOIN FormElement AS feTg ON fe.feIdContainer=feTg.id AND feTg.deleted = 'no' AND feTg.class = 'container' AND feTg.type='templateGroup' AND feTg.enabled='yes' WHERE fe.formId = ? AND fe.deleted = 'no' AND fe.class = 'native' AND fe.enabled='yes'";
const SQL_FORM_ELEMENT_NATIVE_TG_COUNT = "SELECT fe.*, IFNULL(feTg.maxLength,0) AS _tgCopies FROM FormElement AS fe LEFT JOIN FormElement AS feTg ON fe.feIdContainer=feTg.id AND feTg.deleted = 'no' AND feTg.class = 'container' AND feTg.type='templateGroup' AND feTg.enabled='yes' WHERE fe.formId = ? AND fe.deleted = 'no' AND (fe.class = 'native' OR (fe.class = 'container' AND fe.type='pill')) AND fe.enabled='yes'";
const SQL_FORM_ELEMENT_NATIVE_TG_COUNT = "SELECT `fe`.*, IFNULL(`feTg`.`maxLength`,0) AS _tgCopies FROM `FormElement` AS fe LEFT JOIN `FormElement` AS feTg ON `fe`.`feIdContainer`=`feTg`.`id` AND `feTg`.`deleted` = 'no' AND `feTg`.`class` = 'container' AND `feTg`.`type`='templateGroup' AND `feTg`.`enabled`='yes' WHERE `fe`.`formId` = ? AND `fe`.`deleted` = 'no' AND (`fe`.`class` = 'native' OR (`fe`.`class` = 'container' AND `fe`.`type`='pill')) AND `fe`.`enabled`='yes'";
const NAME_TG_COPIES = '_tgCopies'; // Number of templatesGroup copies to create on the fly. Also used in SQL_FORM_ELEMENT_NATIVE_TG_COUNT.
const FE_TG_INDEX = '_tgIndex'; // Index of the current copy of a templateGroup FE.
......@@ -325,7 +325,7 @@ const ERROR_DB_CLOSE_MYSQLI_RESULT = 2009;
const ERROR_DB_CLOSE_MYSQLI_STMT = 2010;
const ERROR_DB_UNKNOWN_COLUMN = 2011;
const ERROR_DB_UNKNOWN_COMMAND = 2012;
const ERROR_DB_MISSING_COLUMN_ID = 2013;
const ERROR_DB_COLUMN_NOT_FOUND_IN_TABLE = 2014;
const ERROR_DB_SET_CHARSET = 2015;
const ERROR_DB_MULTI_QUERY_FAILED = 2016;
......@@ -516,6 +516,10 @@ const SYSTEM_REDIRECT_ALL_MAIL_TO = 'redirectAllMailTo';
const SYSTEM_THROW_GENERAL_ERROR = 'throwExceptionGeneralError';
const SYSTEM_FLAG_PRODUCTION = 'flagProduction';
const SYSTEM_RENDER = 'render';
const SYSTEM_RENDER_SINGLE = 'single';
const SYSTEM_RENDER_BOTH = 'both';
const SYSTEM_RENDER_API = 'api';
const SYSTEM_SHOW_DEBUG_INFO = 'showDebugInfo';
const SYSTEM_SHOW_DEBUG_INFO_YES = 'yes';
......@@ -650,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.
......@@ -1513,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 = '_';
......@@ -1581,9 +1585,18 @@ const COLUMN_MAILTO = "mailto";
const COLUMN_SENDMAIL = "sendmail";
const COLUMN_VERTICAL = "vertical";
const COLUMN_NO_WRAP = "noWrap";
const COLUMN_HIDE = "hide";
const C_FULL = 'full';
const C_TITLE = 'title';
const C_NO_WRAP = 'noWrap';
const C_SPECIAL = 'special';
const C_HIDE = 'hide';
const COLUMN_WRAP_TOKEN = '+';
const COLUMN_STORE_USER = '=';