Commit 25fdfea7 authored by Carsten  Rose's avatar Carsten Rose
Browse files

Preparation to implement 'action'

parent d1f1fec3
...@@ -207,7 +207,7 @@ Only variables that are known in a specified store can be substituted. ...@@ -207,7 +207,7 @@ Only variables that are known in a specified store can be substituted.
+-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+
| C | Client: POST variable, if not found: GET variable | Parameter sent from the Client (=Browser). | | C | Client: POST variable, if not found: GET variable | Parameter sent from the Client (=Browser). |
+-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+
| T | Typo3: a) Bodytext (ttcontent record), b) Typo3 internal varibles like feUser, ... | See Typo3 tt_content record configuration | | T | Typo3: a) Bodytext (ttcontent record), b) Typo3 internal variables like feUser, ... | See Typo3 tt_content record configuration |
+-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+
| V | Vars - Generic variables | | | V | Vars - Generic variables | |
+-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+
...@@ -508,9 +508,9 @@ Class: Native ...@@ -508,9 +508,9 @@ Class: Native
| | 'container') | | | | 'container') | |
+---------------+-----------------------------+---------------------------------------------------------------------------------------------------+ +---------------+-----------------------------+---------------------------------------------------------------------------------------------------+
|type | enum('checkbox', 'date', 'time', 'datetime', 'dateJQW', 'datetimeJQW', 'extra', 'gridJQW', 'text', 'note', 'password', | |type | enum('checkbox', 'date', 'time', 'datetime', 'dateJQW', 'datetimeJQW', 'extra', 'gridJQW', 'text', 'note', 'password', |
| | 'radio', 'select', 'subrecord', 'textarea', 'timeJQW', 'upload', 'fieldset', 'pill', 'before_load', 'before_save', | | | 'radio', 'select', 'subrecord', 'textarea', 'timeJQW', 'upload', 'fieldset', 'pill', 'beforeLoad', 'beforeSave', |
| | 'before_insert', 'before_update', 'before_delete', 'after_load', 'after_save', 'after_insert', 'after_update', 'after_delete', | | | 'beforeInsert', 'beforeUpdate', 'beforeDelete', 'afterLoad', 'afterSave', 'afterInsert', 'afterUpdate', 'afterDelete', |
| | 'feGroup', 'sendmail') | | | 'sendmail') |
+---------------+-----------------------------+---------------------------------------------------------------------------------------------------+ +---------------+-----------------------------+---------------------------------------------------------------------------------------------------+
|checkType | enum('min|max', 'pattern', | | |checkType | enum('min|max', 'pattern', | |
| | 'number', 'email') | | | | 'number', 'email') | |
...@@ -905,57 +905,52 @@ current record either to finalize the upload or to delete a previous uploaded fi ...@@ -905,57 +905,52 @@ current record either to finalize the upload or to delete a previous uploaded fi
Class: Action Class: Action
------------- -------------
Type: before load Type: beforeLoad
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
* Former: formallow * Former: formallow
* Function: a) fire SQL, b) allow / deny access * Function: a) fire SQL, b) allow / deny access
* respects 'processRow' * respects 'processRow'
Type: after load Type: afterLoad
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
* Probably not implemented: no usecase. * Probably not implemented: no usecase.
* Function: fire SQL * Function: fire SQL
* respects 'processRow' * respects 'processRow'
Type: before save Type: beforeSave
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
* Former: lookup * Former: lookup
* Function: a) fire SQL, b) allow / deny access * Function: a) fire SQL, b) allow / deny access
* respects 'processRow' * respects 'processRow'
Type: after save Type: afterSave
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
* Maybe successor of *addnupdate* * Maybe successor of *addnupdate*
* Function: fire SQL * Function: fire SQL
* respects 'processRow' * respects 'processRow'
Type: before /after insert Type: beforeInsert / afterInsert
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Function: a) fire SQL, b) (before) allow / deny access * Function: a) fire SQL, b) (before) allow / deny access
* respects 'processRow' * respects 'processRow'
Type: before /after update Type: beforeUpdate / afterUpdate
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Function: a) fire SQL, b) (before) allow / deny access * Function: a) fire SQL, b) (before) allow / deny access
* respects 'processRow' * respects 'processRow'
Type: before / after delete Type: beforeDelete / afterDelete
^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Function: a) fire SQL, b) (before) allow / deny access * Function: a) fire SQL, b) (before) allow / deny access
* respects 'processRow' * respects 'processRow'
Type: addnupdate
^^^^^^^^^^^^^^^^
* Probably not implemented: no usecase. Probably replaced by after save | after insert. Depends on functionality of 'after ...'.
Type: sendmail Type: sendmail
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
......
...@@ -375,6 +375,7 @@ abstract class AbstractBuildForm { ...@@ -375,6 +375,7 @@ abstract class AbstractBuildForm {
$note = ($formElement[F_BS_NOTE_COLUMNS] == '') ? $this->formSpec[F_BS_NOTE_COLUMNS] : $formElement[F_BS_NOTE_COLUMNS]; $note = ($formElement[F_BS_NOTE_COLUMNS] == '') ? $this->formSpec[F_BS_NOTE_COLUMNS] : $formElement[F_BS_NOTE_COLUMNS];
$this->fillWrapLabelInputNote($label, $input, $note); $this->fillWrapLabelInputNote($label, $input, $note);
} }
// Get default value // Get default value
$value = ($formElement['value'] === '') ? $this->store->getVar($formElement['name'], $storeUse, $value = ($formElement['value'] === '') ? $this->store->getVar($formElement['name'], $storeUse,
$formElement['checkType']) : $formElement['value']; $formElement['checkType']) : $formElement['value'];
...@@ -1014,7 +1015,8 @@ abstract class AbstractBuildForm { ...@@ -1014,7 +1015,8 @@ abstract class AbstractBuildForm {
// enum('a','b','c', ...) >> [ 'a', 'b', 'c', ... ] // enum('a','b','c', ...) >> [ 'a', 'b', 'c', ... ]
// set('a','b','c', ...) >> [ 'a', 'b', 'c', ... ] // set('a','b','c', ...) >> [ 'a', 'b', 'c', ... ]
$items = OnArray::trimArray(explode(',', substr($fieldTypeDefinition, $startPosition, $length - $startPosition - 1)), "'"); $values = substr($fieldTypeDefinition, $startPosition, $length - $startPosition - 1);
$items = OnArray::trimArray(explode(',', $values), "'");
$fieldType = substr($fieldTypeDefinition, 0, $startPosition - 1); $fieldType = substr($fieldTypeDefinition, 0, $startPosition - 1);
return $items; return $items;
......
...@@ -141,6 +141,9 @@ const ERROR_NOT_APPLICABLE = 1057; ...@@ -141,6 +141,9 @@ const ERROR_NOT_APPLICABLE = 1057;
const ERROR_FORMELEMENT_TYPE = 1058; const ERROR_FORMELEMENT_TYPE = 1058;
const ERROR_MISSING_OPEN_DELIMITER = 1059; const ERROR_MISSING_OPEN_DELIMITER = 1059;
const ERROR_MISSING_CLOSE_DELIMITER = 1060; const ERROR_MISSING_CLOSE_DELIMITER = 1060;
const ERROR_EXPECTED_ARRAY = 1061;
const ERROR_REPORT_FAILED_ACTION = 1062;
const ERROR_MISSING_MESSAGE_FAIL = 1063;
// Store // Store
const ERROR_STORE_VALUE_ALREADY_CODPIED = 1100; const ERROR_STORE_VALUE_ALREADY_CODPIED = 1100;
...@@ -416,20 +419,40 @@ const FE_SUBRECORD_ROW_CLASS = '_rowClass'; ...@@ -416,20 +419,40 @@ const FE_SUBRECORD_ROW_CLASS = '_rowClass';
const FE_SUBRECORD_ROW_TITLE = '_rowTitle'; const FE_SUBRECORD_ROW_TITLE = '_rowTitle';
// FormElement columns: real // FormElement columns: real
const FE_NAME = 'name';
const FE_TYPE = 'type'; const FE_TYPE = 'type';
const FE_MODE = 'mode'; const FE_MODE = 'mode';
const FE_MODE_SQL = 'modeSql'; const FE_MODE_SQL = 'modeSql';
// TODO: Konstante FE_DYNAMIC_UPDATE ueberall einsetzen // TODO: Konstante FE_DYNAMIC_UPDATE ueberall einsetzen
const FE_DYNAMIC_UPDATE = 'dynamicUpdate'; const FE_DYNAMIC_UPDATE = 'dynamicUpdate';
// FormElement Types
const FE_TYPE_EXTRA = 'extra';
// FormElement columns: via parameter field // FormElement columns: via parameter field
const FE_DATE_FORMAT = 'dateFormat'; // value: FORMAT_DATE_INTERNATIONAL | FORMAT_DATE_GERMAN const FE_DATE_FORMAT = 'dateFormat'; // value: FORMAT_DATE_INTERNATIONAL | FORMAT_DATE_GERMAN
const FE_SHOW_SECONDS = 'showSeconds'; // value: 0|1 const FE_SHOW_SECONDS = 'showSeconds'; // value: 0|1
const FE_SHOW_ZERO = 'showZero'; // value: 0|1 const FE_SHOW_ZERO = 'showZero'; // value: 0|1
const FE_PATH_FILE_NAME = 'pathFileName'; // Target pathFilename for an uploaded file. const FE_PATH_FILE_NAME = 'pathFileName'; // Target pathFilename for an uploaded file.
const FE_SQL_VALIDATE = 'sqlValidate'; // Action: Query to validate form load
const FE_EXPECT_RECORDS = 'expectRecords'; // Action: expected number of rows of FE_SQL_VALIDATE
const FE_MESSAGE_FAIL = 'messageFail'; // Action: Message to display, if FE_SQL_VALIDATE fails.
const FE_SLAVE_ID = 'slaveId'; // Action; Value or Query to compute id of slave record.
const FE_SQL_UPDATE = 'sqlUpdate'; // Action: Update Statement for slave record
const FE_SQL_INSERT = 'sqlInsert'; // Action: Insert Statement to create slave record.
const FE_SQL_DELETE = 'sqlDelete'; // Action: Delete Statement to delete unused slave record.
// FormElement Types
const FE_TYPE_EXTRA = 'extra';
const FE_TYPE_BEFORE_LOAD = 'beforeLoad';
const FE_TYPE_BEFORE_SAVE = 'beforeSave';
const FE_TYPE_BEFORE_INSERT = 'beforeInsert';
const FE_TYPE_BEFORE_UPDATE = 'beforeUpdate';
const FE_TYPE_BEFORE_DELETE = 'beforeDelete';
const FE_TYPE_AFTER_LOAD = 'afterLoad';
const FE_TYPE_AFTER_SAVE = 'afterSave';
const FE_TYPE_AFTER_INSERT = 'afterInsert';
const FE_TYPE_AFTER_UPDATE = 'afterUpdate';
const FE_TYPE_AFTER_DELETE = 'afterDelete';
const ACTION_KEYWORD_SLAVE_ID = 'slaveId';
// SUPPORT // SUPPORT
const PARAM_T3_ALL = 't3 all'; const PARAM_T3_ALL = 't3 all';
......
...@@ -102,16 +102,16 @@ class Database { ...@@ -102,16 +102,16 @@ class Database {
} }
/** /**
* Fires query $sql and fetches result als assoc array (all modes but ROW_KEYS) or as num array (mode: ROW_EKYS). Throws exception. * Fires query $sql and fetches result as assoc array (all modes but ROW_KEYS) or as num array (mode: ROW_KEYS). Throws exception.
* *
* $mode * $mode
* ROW_REGULAR: Return 2-dimensional assoc array. Every query row is one array row. * ROW_REGULAR: Return 2-dimensional assoc array. Every query row is one array row.
* ROW_IMPLODE_ALL: Return string. All cells of all rows imploded to one string. * ROW_IMPLODE_ALL: Return string. All cells of all rows imploded to one string.
* ROW_EXPECT_0: Return empty string if there is now record row, Else an exception. * ROW_EXPECT_0: Return empty string if there is no record row, Else an exception.
* ROW_EXPECT_1: Return 1-dimensional assoc array if there are exact one row. Else an exception. * ROW_EXPECT_1: Return 1-dimensional assoc array if there are exact one row. Else an exception.
* ROW_EXPECT_0_1: Return empty string if there is no row. Return 1- dimensional assoc array if there is one row. Else an exception. * ROW_EXPECT_0_1: Return empty string if there is no row. Return 1- dimensional assoc array if there is one row. Else an exception.
* ROW_EXPECT_GE_1: Like 'ROW_REGULAR'. Throws an exception if there is an empty resultset. * ROW_EXPECT_GE_1: Like 'ROW_REGULAR'. Throws an exception if there is an empty resultset.
* ROW_KEYS: Return 2-dimensional num(!) array. Every query row is one array row. In $keys are the column names. * ROW_KEYS: Return 2-dimensional num(!) array. Every query row is one array row. $keys are the column names.
* *
* @param $sql * @param $sql
* @param string $mode * @param string $mode
......
...@@ -30,6 +30,12 @@ class Evaluate { ...@@ -30,6 +30,12 @@ class Evaluate {
// private $debugStack = array(); // private $debugStack = array();
/**
* @param \qfq\Store $store
* @param Database $db
* @param string $startDelimiter
* @param string $endDelimiter
*/
public function __construct(Store $store, Database $db, $startDelimiter = '{{', $endDelimiter = '}}') { public function __construct(Store $store, Database $db, $startDelimiter = '{{', $endDelimiter = '}}') {
$this->store = $store; $this->store = $store;
$this->db = $db; $this->db = $db;
...@@ -102,9 +108,11 @@ class Evaluate { ...@@ -102,9 +108,11 @@ class Evaluate {
$debugLocal[] = $debugIndent . "REPLACE: $match"; $debugLocal[] = $debugIndent . "REPLACE: $match";
if ($foundInStore === '') { if ($foundInStore === '') {
// Encode the non replaceable part as preparation not to process again and to recode at the end.
// Encode the non replaceable part as preparation not to process again. Recode them at the end.
$evaluated = Support::encryptDoubleCurlyBraces($this->startDelimiter . $match . $this->endDelimiter); $evaluated = Support::encryptDoubleCurlyBraces($this->startDelimiter . $match . $this->endDelimiter);
$debugLocal[] = $debugIndent . "BY: <nothing found - not replaced>"; $debugLocal[] = $debugIndent . "BY: <nothing found - not replaced>";
} else { } else {
$flagTokenReplaced = true; $flagTokenReplaced = true;
...@@ -189,6 +197,9 @@ class Evaluate { ...@@ -189,6 +197,9 @@ class Evaluate {
return $value; return $value;
} }
/**
* @return string
*/
public function getDebug() { public function getDebug() {
return '<pre>' . implode("\n", $this->debugStack) . '</pre>'; return '<pre>' . implode("\n", $this->debugStack) . '</pre>';
} }
......
...@@ -41,6 +41,7 @@ require_once(__DIR__ . '/../qfq/BuildFormTable.php'); ...@@ -41,6 +41,7 @@ require_once(__DIR__ . '/../qfq/BuildFormTable.php');
require_once(__DIR__ . '/../qfq/BuildFormBootstrap.php'); require_once(__DIR__ . '/../qfq/BuildFormBootstrap.php');
require_once(__DIR__ . '/../qfq/report/Report.php'); require_once(__DIR__ . '/../qfq/report/Report.php');
require_once(__DIR__ . '/../qfq/BodytextParser.php'); require_once(__DIR__ . '/../qfq/BodytextParser.php');
require_once(__DIR__ . '/form/FormAction.php');
/* /*
* Form will be called * Form will be called
...@@ -211,6 +212,7 @@ class QuickFormQuery { ...@@ -211,6 +212,7 @@ class QuickFormQuery {
private function doForm($mode) { private function doForm($mode) {
$data = ''; $data = '';
$foundInStore = ''; $foundInStore = '';
$formAction = new formAction($this->formSpec, $this->db, $this->phpUnit);
// Fill STORE_FORM // Fill STORE_FORM
if ($mode === FORM_UPDATE || $mode === FORM_SAVE) { if ($mode === FORM_UPDATE || $mode === FORM_SAVE) {
...@@ -246,25 +248,35 @@ class QuickFormQuery { ...@@ -246,25 +248,35 @@ class QuickFormQuery {
switch ($mode) { switch ($mode) {
case FORM_LOAD: case FORM_LOAD:
case FORM_UPDATE: case FORM_UPDATE:
$recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT);
$formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_LOAD);
$data = $build->process($mode); $data = $build->process($mode);
$formAction->elements($recordId, $this->feSpecAction, FE_TYPE_AFTER_LOAD);
break; break;
case FORM_SAVE: case FORM_SAVE:
$recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP);
$formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_INSERT . ',' . FE_TYPE_BEFORE_UPDATE . ',' . FE_TYPE_BEFORE_SAVE);
// If an old record exist: load it. Necessary to delete uploaded files which should be overwritten. // If an old record exist: load it. Necessary to delete uploaded files which should be overwritten.
$this->fillStoreRecord($this->formSpec[F_TABLE_NAME], $this->store->getVar(SIP_RECORD_ID, STORE_SIP)); $this->fillStoreRecord($this->formSpec[F_TABLE_NAME], $recordId);
$save = new Save($this->formSpec, $this->feSpecAction, $this->feSpecNative); $save = new Save($this->formSpec, $this->feSpecAction, $this->feSpecNative);
$rc = $save->process(); $rc = $save->process();
// Reload fresh saved record and fill STORE_RECORD with it // Reload fresh saved record and fill STORE_RECORD with it.
$this->fillStoreRecord($this->formSpec[F_TABLE_NAME], $rc); $this->fillStoreRecord($this->formSpec[F_TABLE_NAME], $rc);
$formAction->elements($recordId, $this->feSpecAction, FE_TYPE_AFTER_INSERT . ',' . FE_TYPE_AFTER_UPDATE . ',' . FE_TYPE_AFTER_SAVE);
$htmlElementNameIdZero = false; $htmlElementNameIdZero = false;
// Retrieve current STORE_SIP. // Retrieve current STORE_SIP.
$sipArray = $this->store->getStore(STORE_SIP); $sipArray = $this->store->getStore(STORE_SIP);
if ($sipArray[SIP_RECORD_ID] == 0) { if ($sipArray[SIP_RECORD_ID] == 0) {
// After insert: a new SIP for the new record id is required // After insert: a new SIP for the new record id is required.
$this->newRecordCreateSip($sipArray, $rc); $this->newRecordCreateSip($sipArray, $rc);
$htmlElementNameIdZero = true; $htmlElementNameIdZero = true;
} }
...@@ -329,8 +341,9 @@ class QuickFormQuery { ...@@ -329,8 +341,9 @@ class QuickFormQuery {
$this->store->setVar(SYSTEM_FORM_ELEMENT, '', STORE_SYSTEM); $this->store->setVar(SYSTEM_FORM_ELEMENT, '', STORE_SYSTEM);
// FE: Action // FE: Action
$this->feSpecAction = $this->eval->parseArray($this->db->sql(SQL_FORM_ELEMENT_ALL_CONTAINER, ROW_REGULAR, // $this->feSpecAction = $this->eval->parseArray($this->db->sql(SQL_FORM_ELEMENT_ALL_CONTAINER, ROW_REGULAR,
['no', $this->formSpec["id"], 'action'])); // ['no', $this->formSpec["id"], 'action']));
$this->feSpecAction = $this->db->sql(SQL_FORM_ELEMENT_ALL_CONTAINER, ROW_REGULAR, ['no', $this->formSpec["id"], 'action']);
HelperFormElement::explodeParameterInArrayElements($this->feSpecAction); HelperFormElement::explodeParameterInArrayElements($this->feSpecAction);
// FE: Native & Container // FE: Native & Container
......
<?php
/**
* Created by PhpStorm.
* User: crose
* Date: 5/29/16
* Time: 5:24 PM
*/
namespace qfq;
require_once(__DIR__ . '/../Constants.php');
require_once(__DIR__ . '/../Database.php');
require_once(__DIR__ . '/../store/Store.php');
require_once(__DIR__ . '/../Evaluate.php');
/**
* Class formAction
* @package qfq
*/
class formAction {
// private $feSpecNative = array(); // copy of all formElement.class='native' of the loaded form
private $formSpec = array(); // copy of the loaded form
private $primaryTableName = '';
/**
* @var Database
*/
private $db = null;
/**
* @var Store
*/
private $store = null;
/**
* @var Evaluate instantiated class
*/
protected $evaluate = null;
/**
* @param array $formSpec
* @param Database $db
* @param bool|false $phpUnit
*/
public function __construct(array $formSpec, Database $db, $phpUnit = false) {
$this->formSpec = $formSpec;
$this->primaryTableName = Support::setIfNotSet($formSpec,F_TABLE_NAME);
$this->db = $db;
$this->store = Store::getInstance('', $phpUnit);
$this->evaluate = new Evaluate($this->store, $this->db);
}
/**
* @param $table
* @param $recordId
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
private function fillStoreRecord($table, $recordId) {
if (!is_string($table) || $table === '') {
throw new UserFormException("");
}
if ($recordId !== false && $recordId > 0) {
$record = $this->db->sql("SELECT * FROM $table WHERE id = ?", ROW_EXPECT_1, [$recordId]);
$this->store->setVarArray($record, STORE_RECORD, true);
}
}
/**
* @param integer $recordId
* @param array $feSpecAction
* @param string $feTypeList
* On FormLoad: FE_TYPE_BEFORE_LOAD, FE_TYPE_AFTER_LOAD
* Before Save: FE_TYPE_BEFORE_SAVE, FE_TYPE_BEFORE_INSERT, FE_TYPE_BEFORE_UPDATE, FE_TYPE_BEFORE_DELETE
* After Save: FE_TYPE_AFTER_SAVE, FE_TYPE_AFTER_INSERT, FE_TYPE_AFTER_UPDATE, FE_TYPE_AFTER_DELETE
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
public function elements($recordId, array $feSpecAction, $feTypeList) {
// get current data record
// if ($recordId > 0 && $this->store->getVar('id', STORE_RECORD) === false) {
// $row = $this->db->sql("SELECT * FROM " . $this->formSpec[F_TABLE_NAME] . " WHERE id = ?", ROW_EXPECT_1, array($recordId));
// $this->store->setVarArray($row, STORE_RECORD);
// }
// Iterate over all Action FormElements
foreach ($feSpecAction as $fe) {
if (false === Support::findInSet($fe[FE_TYPE], $feTypeList)) {
continue;
}
if ($fe[FE_TYPE] !== FE_TYPE_BEFORE_LOAD && $fe[FE_TYPE] !== FE_TYPE_AFTER_LOAD) {
// Always work on recent data: previous actions might modify the data
$this->fillStoreRecord($this->primaryTableName, $recordId);
}
// Preparation for Log, Debug
$this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($fe), STORE_SYSTEM);
$this->validate($fe);
$this->doSlave($fe, $recordId);
}
}
/**
* @param array $fe
* @return int
* @throws CodeException
* @throws UserFormException
*/
private function doSlave(array $fe, $recordId) {
$flagUpdateMasterRecord = false;
// Get the slaveId
$tmp = Support::setIfNotSet($fe, FE_SLAVE_ID);
$slaveId = $this->evaluate->parse($tmp);
if ($slaveId === '' && $fe[FE_NAME] !== '') {
// if the current action element has the same name as a real master record column: take that value as an id
$slaveId = $this->store->getVar($fe[FE_NAME], STORE_RECORD);
if ($slaveId !== false) {
$flagUpdateMasterRecord = true;
}
}
if ($slaveId === '' || $slaveId === false) {
$slaveId = 0;
}
// put the slaveId to the store: it's used and replaced in the update statement.
$this->store->setVar(ACTION_KEYWORD_SLAVE_ID, $slaveId, STORE_VAR, true);
if ($slaveId == 0) {
$slaveId = $this->evaluate->parse($fe[FE_SQL_INSERT]);
} else {
$this->evaluate->parse($fe[FE_SQL_UPDATE]);
}
if ($flagUpdateMasterRecord) {
$this->db->sql("UPDATE " . $this->primaryTableName . " SET " . $fe[FE_NAME] . " = $slaveId WHERE id = ? LIMIT 1", ROW_REGULAR, [ $recordId ] );
}
return $slaveId;
}
/**
* If there is a query defined in fe.parameter.FE_SQL_VALIDATE: fire them.
* Count the selected records and compare them with fe.parameter.FE_EXPECT_RECORDS.
* If match: everything is fine, do nothing.
* Else throw the error message in fe.parameter.FE_MESSAGE_FAIL
*
* @param array $fe
* @throws UserFormException
*/
private function validate(array $fe) {
// Is there something to check?
if (Support::setIfNotSet($fe, FE_SQL_VALIDATE) === '') {
return;
}
$expect = Support::setIfNotSet($fe, FE_EXPECT_RECORDS, '0');
$msg = Support::setIfNotSet($fe, FE_MESSAGE_FAIL);
if ($msg === '') {
throw new UserFormException("Missing error message. Column: " . FE_MESSAGE_FAIL, ERROR_MISSING_MESSAGE_FAIL);
}
// Do the check
$result = $this->evaluate->parse($fe[FE_SQL_VALIDATE]);
if (!is_array($result)) {
throw new UserFormException("Expected an array for '" . FE_SQL_VALIDATE . "', got a scalar. Please check for {{!...", ERROR_EXPECTED_ARRAY);
}
if (count($result) == $expect) {
return; // check succesfully passed
}
$msg = $this->evaluate->parse($msg); // Replace possible dynamic parts
// Throw user defineable error message
throw new UserFormException($msg, ERROR_REPORT_FAILED_ACTION);
}
}
//
///********************************************************
// * doAddNUpdate