Commit 769e7cc9 authored by Carsten  Rose's avatar Carsten Rose
Browse files

FormAction.php: started to implement 'save templateGroups with foreign records'

OnArray.php: new function 'arrayValueReplace()'.
AbstractBuildForm.php: Load foreign values in templatGroups.
parent ded8be12
......@@ -406,8 +406,24 @@ abstract class AbstractBuildForm {
//In case the current element is a 'RETYPE' element: take the element name of the source FormElement. Needed in the next row to retrieve the default value.
$name = (isset($formElement[FE_RETYPE_SOURCE_NAME])) ? $formElement[FE_RETYPE_SOURCE_NAME] : $formElement[FE_NAME];
// If there is a value explicit defined: take it
$value = '';
Support::setIfNotSet($formElement, FE_VALUE);
// If is FormElement['value'] explicit defined: take it
// There are two options: a) single value, b) array of values (template Group)
// if (is_array($formElement[FE_VALUE])) {
// // For Templates Groups, the 'value' has to be defined as '{{!SELECT ...' wich returns all selected records in an array.
// $idx = isset($formElement[FE_TEMPLATE_GROUP_CURRENT_IDX]) ? $formElement[FE_TEMPLATE_GROUP_CURRENT_IDX] - 1 : 0;
// if (isset($formElement[FE_VALUE][$idx]) && is_array($formElement[FE_VALUE][$idx])) {
// $value = current($formElement[FE_VALUE][$idx]);
// if ($value === false) {
// $value = '';
// }
// }
// } else {
$value = $formElement[FE_VALUE];
// }
if ($value === '') {
// Only take the default, if the FE is a real tablecolumn. See #2064
if ($this->store->getVar($formElement[FE_NAME], STORE_TABLE_COLUMN_TYPES) !== false) {
......@@ -2961,29 +2977,38 @@ EOT;
}
$default = $this->store->getStore(STORE_TABLE_DEFAULT); // current defaults
// evaluate FE_VALUE on all templateGroup FormElements.
$maxForeignRecords = $this->templateGroupDoValue();
$lastFilled = 0; // Marker if there is at least one element per copy who is filled.
$feSpecNativeCopy = array();
for ($ii = 1; $ii < $max; $ii++) {
for ($ii = 1; $ii <= $max; $ii++) {
// Per copy, iterate over all templateGroup FormElements
// Per copy, iterate over all templateGroup FormElements.
foreach ($this->feSpecNative as $fe) {
$columnName = str_replace(FE_TEMPLATE_GROUP_NAME_PATTERN, $ii, $fe[FE_NAME]);
$fe[FE_LABEL] = str_replace(FE_TEMPLATE_GROUP_NAME_PATTERN, $ii, $fe[FE_LABEL]);
$fe[FE_NOTE] = str_replace(FE_TEMPLATE_GROUP_NAME_PATTERN, $ii, $fe[FE_NOTE]);
// Column of primary table?
if (isset($record[$columnName])) {
if ($record[$columnName] != $default[$columnName]) {
$lastFilled = $ii;
$lastFilled = max($ii, $lastFilled);
}
$fe[FE_NAME] = $columnName;
} else {
throw new UserFormException("Not implemented: templateGroup FormElement-columns not found in primary table.", ERROR_NOT_IMPLEMENTED);
$lastFilled = max($maxForeignRecords, $lastFilled);
if (is_array($fe[FE_VALUE]) && isset($fe[FE_VALUE][$ii - 1])) {
$fe[FE_VALUE] = current($fe[FE_VALUE][$ii - 1]); // replace array with current value
}
// $fe[FE_TEMPLATE_GROUP_CURRENT_IDX] = $ii;
}
$fe[FE_NAME] = $columnName;
$feSpecNativeCopy[$ii - 1][] = $fe; // Build array with current copy of templateGroup.
}
// Append $htmlDelete on the last element of all copies,, but not the first.
// Append $htmlDelete on the last element of all copies, but not the first.
if ($ii > 1) {
// Count defined FormElements in the current templateGroup
$last = count($feSpecNativeCopy[$ii - 1]) - 1;
......@@ -2999,6 +3024,7 @@ EOT;
$feSpecNativeSave = $this->feSpecNative;
$lastFilled = min($lastFilled, $max); // It's possible (external records) that there are more fetched values than the maximum allows - skip those.
$html = '';
for ($ii = 0; $ii < $lastFilled; $ii++) {
$this->feSpecNative = $feSpecNativeCopy[$ii];
......@@ -3012,6 +3038,31 @@ EOT;
return $html;
}
/**
* Evaluate for all FormElements of the current templateGroup the field FE_VALUE.
* If the specific FormElement is not a real column of the primary table, than the value is probably a '{{!SELECT ...'
* Statement, that one will be fired. Additional the maximum count of all select rows will be determined and returned.
*
* @return int max number of records in FormElement[FE_VALUE] over all FormElements.
* @throws UserFormException
*/
private function templateGroupDoValue() {
// Fire 'value' statement
$tgMax = 0;
foreach ($this->feSpecNative as $key => $arr) {
$this->feSpecNative[$key][FE_VALUE] = $this->evaluate->parse($arr[FE_VALUE]);
if (is_array($this->feSpecNative[$key][FE_VALUE])) {
$cnt = count($this->feSpecNative[$key][FE_VALUE]);
$tgMax = max($cnt, $tgMax);
}
}
return $tgMax;
}
abstract public function buildRowNative(array $formElement, $htmlElement, $htmlFormElementName);
}
\ No newline at end of file
......@@ -50,6 +50,7 @@ const SQL_FORM_ELEMENT_SPECIFIC_CONTAINER = "SELECT *, ? AS 'nestedInFieldSet' F
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.label, fe.type, 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 = "SELECT * FROM FormElement AS fe WHERE fe.id = ? AND fe.deleted = 'no' AND fe.class = 'container' AND fe.type='templateGroup' AND fe.enabled='yes' ";
// SANITIZE Classifier
const SANITIZE_ALLOW_ALNUMX = "alnumx";
......@@ -635,6 +636,7 @@ const FE_TEMPLATE_GROUP_REMOVE_TEXT = 'tgRemoveText';
const FE_TEMPLATE_GROUP_CLASS = 'tgClass';
const FE_TEMPLATE_GROUP_DEFAULT_MAX_LENGTH = 5;
const FE_TEMPLATE_GROUP_NAME_PATTERN = '%d';
const FE_TEMPLATE_GROUP_CURRENT_IDX = 'tgCurentIndex';
const FE_BUTTON_CLASS = 'buttonClass';
const FE_LDAP_SERVER = F_LDAP_SERVER;
const FE_LDAP_BASE_DN = F_LDAP_BASE_DN;
......
......@@ -65,13 +65,16 @@ class FormAction {
* @throws DbException
* @throws UserFormException
*/
public function elements($recordId, array $feSpecAction, $feTypeList) {
public function elements($recordId, array $feSpecAction, $feTypeList, $templateGroupIndex = 0) {
$flagModified = false;
// Iterate over all Action FormElements
foreach ($feSpecAction as $fe) {
// Preparation for Log, Debug
$this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($fe), STORE_SYSTEM);
$fe = HelperFormElement::initActionFormElement($fe);
// Only process FE elements of types listed in $feTypeList. Skip all other
......@@ -79,8 +82,25 @@ class FormAction {
continue;
}
// Preparation for Log, Debug
$this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($fe), STORE_SYSTEM);
// Process templateGroup action elements
if (isset($fe[FE_ID_CONTAINER]) && $fe[FE_ID_CONTAINER] > 0) {
$feTemplateGroup = $this->db->sql(SQL_FORM_ELEMENT_TEMPLATE_GROUP, ROW_REGULAR, [$fe[FE_ID_CONTAINER]]);
if (count($feTemplateGroup) == 1) {
$fe[FE_ID_CONTAINER] = 0;
for ($ii = 1; $ii < $feTemplateGroup[0][FE_MAX_LENGTH]; $ii++) {
$feNew = OnArray::arrayValueReplace($fe, FE_TEMPLATE_GROUP_NAME_PATTERN, $ii);
if ($this->elements($recordId, [$feNew], $feTypeList, $ii)) {
$flagModified = true;
}
}
} else {
// At the moment 'action' elements have to point to a templateGroup - nothing else is defined. Break if there is somethin else
throw new UserFormException("Expect a 'templateGroup' record in FormElement.id=", $fe[FE_ID_CONTAINER], ERROR_RECORD_NOT_FOUND);
}
continue; // skip to next FormElement
}
switch ($fe[FE_TYPE]) {
case FE_TYPE_BEFORE_LOAD:
......@@ -117,7 +137,7 @@ class FormAction {
$this->validate($fe);
$this->doSlave($fe, $recordId);
$this->doSlave($fe, $recordId, $templateGroupIndex);
$flagModified = true;
}
......@@ -241,14 +261,27 @@ class FormAction {
* Create the slave record. First try to evaluate a slaveId. Depending if the slaveId > 0 choose `sqlUpdate` or `sqlInsert`
*
* @param array $fe
* @param int $recordId
* @param int $templateGroupIndex
* @return int
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
private function doSlave(array $fe, $recordId) {
private function doSlave(array $fe, $recordId, $templateGroupIndex) {
// Get the slaveId
$slaveId = $this->evaluate->parse($fe[FE_SLAVE_ID]);
if ($templateGroupIndex > 0) {
if (is_array($slaveId)) {
// Select the n'th id of the array
$slaveId = isset($slaveId[$templateGroupIndex]) ? $slaveId[$templateGroupIndex] : 0;
} else {
throw new UserFormException("Result not an arry. SQL Statement for 'slaveId' in TemplateGroup should return an array with all 'slaveId's.", ERROR_EXPECTED_ARRAY);
}
} elseif (is_array($slaveId)) {
throw new UserFormException("Result not a single value. SQL Statement for 'slaveId' in should a single value.", ERROR_UNEXPECTED_TYPE);
}
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
......
......@@ -228,4 +228,21 @@ class OnArray {
return $new;
}
/**
* Iterates over an array and replaces all occurences of $search with $replace. Returns the new array.
*
* @param array $src
* @param $search
* @param $replace
* @return array
*/
public static function arrayValueReplace(array $src, $search, $replace ) {
$new = array();
foreach($src AS $key => $element) {
$new[$key] = str_replace($search, $replace, $element);
}
return $new;
}
}
\ No newline at end of file
......@@ -120,4 +120,19 @@ class OnArrayTest extends \PHPUnit_Framework_TestCase {
$this->assertEquals(['a' => 'hello'], OnArray::getArrayItems(['a' => 'hello', 'b' => 'world'], ['a', 'c'], false));
$this->assertEquals(['a' => 'hello', 'c' => ''], OnArray::getArrayItems(['a' => 'hello', 'b' => 'world'], ['a', 'c'], true));
}
public function testArrayValueReplace() {
$this->assertEquals(array(), OnArray::arrayValueReplace(array(), '', ''));
$this->assertEquals(array(), OnArray::arrayValueReplace(array(), 'a', ''));
$this->assertEquals(array(), OnArray::arrayValueReplace(array(), '', 'b'));
$this->assertEquals(array(), OnArray::arrayValueReplace(array(), 'a', 'b'));
$src = ['fruit1' => 'apple', 'fruit2' => 'cherry', 'fruit3' => 'banana'];
$this->assertEquals($src, OnArray::arrayValueReplace($src, '', ''));
$this->assertEquals($src, OnArray::arrayValueReplace($src, 'Z', ''));
$this->assertEquals($src, OnArray::arrayValueReplace($src, 'Z', 'Y'));
$expected = ['fruit1' => 'Apple', 'fruit2' => 'cherry', 'fruit3' => 'bAnAnA'];
$this->assertEquals($expected, OnArray::arrayValueReplace($src, 'a', 'A'));
}
}
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