getDocument()->getWebAssetManager(); $filter = new InputFilter(); $visforms = $displayData['visforms']; $vfObjForJs = new stdClass(); $vfObjForJs->fid = $visforms->id; $textareaRequired = $displayData['textareaRequired']; $hasHTMLEditor = $displayData['hasHTMLEditor']; $parentFormId = $displayData['parentFormId']; $vfObjForJs->parentFormId = $displayData['parentFormId']; $steps = $displayData['steps']; $nbFields = count($visforms->fields); $vfObjForJs->useSession = !empty($visforms->usesession); $vfObjForJs->editView = in_array($visforms->displayState, array(3,4)); $vfObjForJs->hideEmptyFieldsets = !empty($visforms->hideemptyfieldsets); // $vfObjForJs->overrideBrowserHistory = $visforms->overrideBrowserHistory; $fieldsForJsa = array(); $userinputsa = array(); $restrictData = array(); $reloadTriggerFields = array(); $calculationVars = array(); // list of all calculation fields ( which must be calculated) and all fields which trigger recalculation $calculationTriggerFields = array(); $calculationTree = array(); $calculationEquations = array(); for ($i = 0; $i < $nbFields; $i++) { $field = $visforms->fields[$i]; if (isset($field->userInput)) { $userinputsa[] = array( 'type' => $field->typefield, 'label' =>'field'. $field->id, 'value' => $field->userInput, 'isDisabled' => ((!empty($field->isDisabled)) ? true : false), 'isForbidden' => ((!empty($field->isForbidden)) ? true : false)); } if (isset($field->showWhenForForm) && (is_array($field->showWhenForForm))) { $restrictData['field' . $field->id] = implode(', ', $field->showWhenForForm); } if (isset($field->reloadTriggerFieldsForForm) && (is_array($field->reloadTriggerFieldsForForm))) { $reloadTriggerFields['field' . $field->id] = implode(', ', $field->reloadTriggerFieldsForForm); } // create a flat list, which includes any field that is use in a calculation and therefore triggers a recalculation if it's value changes // the field is used in a calculation, add it to the list if (!empty($field->isCalculationTrigger) || $field->typefield === 'calculation') { $calculationTriggerFields['field' . $field->id] = array(); } // the field is a calculation field if (isset($field->calculationTriggerFields) && (is_array($field->calculationTriggerFields))) { $calculationVars['field' . $field->id] = implode(', ', $field->calculationTriggerFields); } if (!empty($field->JsEquation)) { $calculationEquations['field' . $field->id] = $field->JsEquation; } // label might contain html tags, if the option 'replace label with custom text' is used, // use inputFilter to clean the label to a string $summaryLabel = (empty($field->customlabelforsummarypage)) ? $filter->clean($field->label, 'STRING') : $field->customlabelforsummarypage; $fieldsForJsa[] = array('id' => (int) $field->id, 'type' => $field->typefield ,'label'=> $summaryLabel); } // create a list with an element for each calculation trigger field; // this may include fields which are no calculation fields themselves // parents is empty array foreach ($calculationTriggerFields as $key => &$parents) { foreach ($visforms->fields as $field) { if (isset($field->calculationTriggerFields) && (is_array($field->calculationTriggerFields))) { foreach ($field->calculationTriggerFields as $calculationTriggerField) { if ($calculationTriggerField === $key && !array_key_exists('field' . $field->id, $parents)) { $parents['field' . $field->id] = 'field' . $field->id; } } } } } // set start level in calculation tree foreach ($calculationTriggerFields as $key => $parent) { $calculationTree[$key] = 0; } $maxLoopCount = count($calculationTriggerFields); while ($maxLoopCount > 0) { $parentsDone = array(); $entriesToDelete = array(); // outer loop: process each calculationTriggerFields1 entry foreach ($calculationTriggerFields as $pKey => $pParents) { // pParents Array is a list of all fields which must be recalculated, if pKey value is changed // empty pParents: there are no fields which must be recalculated, i pKey value is changed if (empty($pParents)) { // find each field that triggers a recalculation of pKey // inner loop foreach ($calculationTriggerFields as $sKey => $sParents) { if ($pKey === $sKey) { continue; } // sKey triggers a recalculation of pKey if (array_key_exists($pKey, $sParents)) { // if we have not yet processed sKey as trigger field if (!array_key_exists($sKey, $parentsDone)) { // get level of pKey and set level of sKey one higher $calculationTree[$sKey] = $calculationTree[$pKey] + 1; // in every other loop only update the level once $parentsDone[$sKey] = $sKey; } // remove parent key from the trigger list (sParent) of the currently processed inner loop field // at some point this results in sParent being empty // after that, it will be processed by the outer loop unset($calculationTriggerFields[$sKey][$pKey]); } } // pKey is processed: remove it from $calculationTriggerFields unset ($calculationTriggerFields[$pKey]); } } $maxLoopCount--; } if (!empty($visforms->usesession)) { $app->setUserState('com_visforms.userinputs.' . $visforms->context, json_encode($userinputsa)); } $vfObjForJs->fields = $fieldsForJsa; if ($textareaRequired == true || $hasHTMLEditor == true) { // we need an editor and create a simple tinyMCE editor EditorHelper::initEditor(); } // ToDo: We could now add a validatorOptions parameter to the form object // ToDo: and write the field validator options (rules and messages) into this object, directly in the field classes instead of creating validateArray and customErrorMsgArray // ToDo: and looping here through these lists $validatorOptions = array(); $validatorOptions['showProcessFormMsg'] = !empty($visforms->showmessageformprocessing); $validatorOptions['accordionErrorHandling'] = isset($visforms->mpdisplaytype) && (int) $visforms->mpdisplaytype === 1 && !empty($visforms->accordionCounter); $validatorOptions['rules'] = array(); for ($i = 0; $i < $nbFields; $i++) { $field = $visforms->fields[$i]; if (isset($field->validateArray) && !empty($field->validateArray)) { if (isset($field->typefield) && ($field->typefield == "select" || $field->typefield == "selectsql" || $field->typefield == "multicheckbox") || $field->typefield == "multicheckboxsql" || $field->typefield == 'location') { $ruleName = $field->name . '[]'; } else { $ruleName = $field->name; } $validatorOptions['rules'][$ruleName] = array(); foreach ($field->validateArray as $n => $v) { if ($n == 'geolocation') { $validatorOptions['rules'][$ruleName]['ispair'] = 'field' . $field->id; } else if ($n == 'mailExists') { continue; } else { $validatorOptions['rules'][$ruleName][$n] = $v; } unset($n); unset($v); } // this does not work! Joomla options container is only for passing values // the JS functions are only strings afterward // moved into visforms.js, function initValidator; /* if ( $field->typefield == 'email' && array_key_exists('mailExists', $field->validateArray)) { $ruleName = $field->name . '_code'; $validatorOptions['rules'][$ruleName] = array(); $validatorOptions['rules'][$ruleName]['remote'] = array( 'url' => Uri::root(true) .'/index.php?option=com_visforms&task=visforms.checkVerificationCode', 'type' => 'post', 'data' => array( 'verificationAddr' => "function () {return document.getElementById('field" . $field->id."').value;}", 'code' => "function () {return document.getElementById('field" . $field->id."_code').value;}", 'fid' => $visforms->id, Session::getFormToken() => 1, 'dataFilter' => "function (data) {if (data === '1') {return true;} else {return false}}}" ) ); }*/ } } if (isset($visforms->captcha)) { if ($visforms->captcha == 3) { $ruleName = 'h-captcha-response'; $validatorOptions['rules'][$ruleName] = array( 'required' => true); } if ($visforms->captcha == 4 ) { $ruleName = 'g-recaptcha-response'; $validatorOptions['rules'][$ruleName] = array( 'required' => true); } } $validatorOptions['messages'] = array(); for ($i = 0; $i < $nbFields; $i++) { $field = $visforms->fields[$i]; $messageName = $field->name; if (isset($field->typefield) && $field->typefield == "date" && !(isset($field->customErrorMsgArray))) { if (isset($field->dateFormatJs) || (isset($field->validateArray) && array_key_exists('minage', $field->validateArray))) { $validatorOptions['messages'][$messageName] = array(); if (isset($field->dateFormatJs)) { switch ($field->dateFormatJs) { case "%d.%m.%Y": $validatorOptions['messages'][$messageName]['dateDMY'] = Text::sprintf('COM_VISFORMS_ENTER_VALID_DATE_FORMAT', 'dd.mm.YYYY'); break; case "%m/%d/%Y": $validatorOptions['messages'][$messageName][ 'dateMDY'] = Text::sprintf('COM_VISFORMS_ENTER_VALID_DATE_FORMAT', 'mm/dd/YYYY'); break; case "%Y-%m-%d": $validatorOptions['messages'][$messageName]['dateYMD'] = Text::sprintf('COM_VISFORMS_ENTER_VALID_DATE_FORMAT', 'YYYY-mm-dd'); break; } } if (isset($field->validateArray) && array_key_exists('minage', $field->validateArray)) { $validatorOptions['messages'][$messageName]['minage'] = Text::sprintf('COM_VISFORMS_MINAGE_VALIDATION_FAILED_JS', $field->minage); } } } else if (isset($field->typefield) && $field->typefield == "tel" && !(isset($field->customErrorMsgArray)) && (isset($field->validateArray) && array_key_exists('phonevalidation', $field->validateArray))) { $validatorOptions['messages'][$messageName]['phonevalidation'] = Text::sprintf('COM_VISFORMS_PHONENUMBER_FORMAT_VALIDATION_FAILED_JS', $field->phonevalidation, Text::_("COM_VISFORMS_PHONE_NUMBER_FORMAT_".$field->phonevalidation)) . (!empty($field->allowedCharMessage) ? $field->allowedCharMessage : ""); } else if (isset($field->typefield) && $field->typefield == "file" && !(isset($field->customErrorMsgArray))) { $validatorOptions['messages'][$messageName] = array(); $validatorOptions['messages'][$messageName]['filesize'] = Text::sprintf('COM_VISFORMS_JS_ERROR_WARNFILETOOLARGE', ($field->maxfilesize)); $validatorOptions['messages'][$messageName]['fileextension'] = Text::sprintf('COM_VISFORMS_JS_ERROR_WARNFILETYPE', ($field->allowedextensions)); } else if (isset($field->typefield) && $field->typefield == "email" && isset($field->validateArray) && array_key_exists('mailExists', $field->validateArray) && !(isset($field->customErrorMsgArray))) { $messageName = $field->name . '_code'; $validatorOptions['messages'][$messageName] = array(); $validatorOptions['messages'][$messageName]['remote'] = Text::_('COM_VISFORMS_VALIDATION_CODE_INVALID'); $validatorOptions['messages'][$messageName]['required'] = Text::_('COM_VISFORMS_ENTER_VALIDATION_CODE'); } if (isset($field->customErrorMsgArray)) { if (isset($field->typefield) && ($field->typefield == "select" || $field->typefield == "selectsql" || $field->typefield == "multicheckbox" || $field->typefield == "multicheckboxsql")) { $messageName = $field->name . '[]'; } else { // array key for 'normal' fields $messageName = $field->name; } $validatorOptions['messages'][$messageName] = array(); foreach ($field->customErrorMsgArray as $n => $v) { if ($n === "date" && (isset($field->dateFormatJs))) { switch ($field->dateFormatJs) { case "%d.%m.%Y": $validatorOptions['messages'][$messageName]['dateDMY'] = $v; break; case "%m/%d/%Y": $validatorOptions['messages'][$messageName]['dateMDY'] = $v; break; case "%Y-%m-%d": $validatorOptions['messages'][$messageName]['dateYMD'] = $v; break; } } else { $validatorOptions['messages'][$messageName][$n] = $v; } } } else { // Adapt Error message for multi checkbox minlength, maxlength if we use the default message texts if (isset($field->typefield) && (($field->typefield == "multicheckbox") || ($field->typefield == "multicheckboxsql"))) { $messageName = $field->name . '[]'; $validatorOptions['messages'][$messageName] = array(); $validatorOptions['messages'][$messageName]['minlength'] = 'jQuery.validator.format("' . addslashes(Text::_('COM_VISFORMS_ENTER_VAILD_MINLENGTH_MULTICHECKBOX')) . '")'; $validatorOptions['messages'][$messageName]['maxlength'] = 'jQuery.validator.format("' . addslashes(Text::_('COM_VISFORMS_ENTER_VAILD_MAXLENGTH_MULTICHECKBOX')) . '")'; } } // Custom Captcha Error Message (ToDo escape potential @) if (isset($visforms->captchacustomerror) && $visforms->captchacustomerror != "") { $messageName = $visforms->context . 'viscaptcha_response'; $validatorOptions['messages'][$messageName] = array(); $validatorOptions['messages'][$messageName]['required'] = $visforms->captchacustomerror; $validatorOptions['messages']['h-captcha-response'] = $visforms->captchacustomerror; $validatorOptions['messages']['g-recaptcha-response'] = $visforms->captchacustomerror; } } endif; endif; $doc = Factory::getApplication()->getDocument(); // Todo: vfObjForJs contains the fields (fieldsForJsa). It seems that the fields provided separately by the 'fields' key, are not used in the visforms.js // either remove the fields key or the fields in the form object $doc->addScriptOptions('visforms.'.$parentFormId, ['visform' => $vfObjForJs, 'restrictData' => $restrictData, 'fields' => $fieldsForJsa, 'reloadTriggerFields' => $reloadTriggerFields, 'calculationVars' => $calculationVars, 'calculationEquations' => $calculationEquations, 'calculationTree' => $calculationTree, 'validator' => $validatorOptions]); if (empty($visforms->usesession)) { $doc->addScriptOptions('visforms.'.$parentFormId, ['userInputs' => $userinputsa]); } Text::script('COM_VISFORMS_STEP');