type = $field->typefield; $this->field = $field; $this->form = $form; $this->input = Factory::getApplication()->getInput(); // make field names unique, allow use of one form more than once on one page $this->field->alias = $this->field->name; if (!empty($this->form->context)) { $this->field->name = $this->form->context . $this->field->name; } $this->isEditOrSaveEditTask = ($this->form->displayState === VisformsModelSite::$displayStateIsNewEditData || $this->form->displayState === VisformsModelSite::$displayStateIsRedisplayEditData) ? true : false; } public function getField() { $this->setField(); return $this->field; } public function setRecordId($cid) { $this->field->recordId = $cid; } protected function setQueryValue(): void { if ($this->form->displayState === VisformsModelSite::$displayStateIsNew) { $app = Factory::getApplication(); $task = $app->getInput()->getCmd('task', ''); if (($task !== 'editdata') && ($task !== 'saveedit')) { // using $this->input->get->get makes sure that the joomla! security functions are performed on the user inputs! // plugin form view sets get values as well $queryValue = $this->input->get->get($this->field->name, null, 'STRING'); if (!is_null($queryValue)) { $urlparams = $app->getUserState('com_visforms.urlparams.' . $this->form->context); if (empty($urlparams)) { $urlparams = array(); } $urlparams[$this->field->name] = (!empty($this->field->decodeqpvalue)) ? HTMLHelper::_('visforms.base64_url_decode', $queryValue) : $queryValue; $app->setUserState('com_visforms.urlparams.' . $this->form->context, $urlparams); } } } } protected function extractDefaultValueParams(): void { $this->field->defaultvalue = VisformsHelper::registryArrayFromString($this->field->defaultvalue); $helper = new FieldParamNameShortener($this->field); $this->field = $helper->makeShort(true); } protected function extractGridSizesParams(): void { $this->field->gridSizes = VisformsHelper::registryArrayFromString($this->field->gridSizes); foreach ($this->field->gridSizes as $key => $value) { $this->field->$key = $value; } unset($this->field->gridSizes); } protected function extractRestrictions(): void { $this->field->restrictions = VisformsHelper::registryArrayFromString($this->field->restrictions); } protected function mendBooleanAttribs(): void { $attribs = array('required' => true, 'readonly' => 'readonly', 'checked' => 'checked'); foreach ($attribs as $attrib => $value) { $attribname = 'attribute_' . $attrib; // Do not remove. Older fields may have set the attribute with empty walue! if (isset($this->field->$attribname) && ($this->field->$attribname == $attrib || $this->field->$attribname == '1' || $this->field->$attribname == true)) { $this->field->$attribname = $attrib; } else { unset($this->field->$attribname); } } } protected function prepareFieldForNoEditSqlProcess(): void { // new option which might not be set in older fields // Default is 'process' with a value of 1 // so only if option is set and has the value 0 no process of sql in edit view if ($this->isEditOrSaveEditTask && ((isset($this->field->sql_process_in_edit_view) && empty($this->field->sql_process_in_edit_view)))) { $this->field->noEditSqlProcess = true; } } protected function unsetDeselectedEditViewValidations(): void { // check for each validation option if it was deselected for edit view // new options which might not be set in older fields // Default is 'validate in edit view' with a value of 1 // so only if option is set and has the value 0 validation should not be performed in edit view if ($this->isEditOrSaveEditTask ) { foreach ($this->field as $name => $value) { if (!is_array($value)) { if ($value) { // field option starts with validate_ if (str_contains($name, 'validate')) { $ruleName = str_replace('validate_', "", strtolower($name)); $ruleNevvName = $ruleName . '_nevv'; if (!empty($this->field->$ruleNevvName)) { unset($this->field->$name); continue; } } // field option with a custom name if (in_array($name, Visforms::customValidationNames)) { $ruleNevvName = $name . '_nevv'; if (!empty($this->field->$ruleNevvName)) { unset($this->field->$name); continue; } } // field option starts with attribute if (str_contains($name, 'attribute_')) { $ruleName = str_replace('attribute_', "", $name); $ruleNevvName = $ruleName . '_nevv'; if (in_array($ruleName, Visforms::htmlValidationAttribs)) { if (!empty($this->field->$ruleNevvName)) { unset($this->field->$name); } } } } } } } } protected function setCustomPhpErrorMsg(): void { if (empty($this->field->custom_php_error)) { $this->field->custom_php_error = ''; } } protected function setIsConditional(): void { if (isset($this->field->showWhen) && is_array($this->field->showWhen) && count($this->field->showWhen) > 0) { foreach ($this->field->showWhen as $value) { // if we have at least on restict with a field there is a condition set if (preg_match('/^field/', $value) === 1) { $this->field->isConditional = true; return; } } } $this->field->isConditional = false; } protected function setIsReloadable(): void { // a field has to be reloaded if // it is a select sql field with the option 'reload' set to yes // it is a text-like field with a field value from sql statement // used in edit view to set the proper field value // used in form view in select sql fields and text-like inputs to set value from sql statement // by triggering one reload of the field value after the field values are set from the user-input object in initVisfields if (!empty($this->field->toggle_reload) || !empty($this->field->toggle_value_from_sql)) { $this->field->isReloadable = true; return; } $this->field->isReloadable = false; } protected function setIsReloadTrigger() { if (isset($this->field->restrictions) && (is_array($this->field->restrictions))) { // loop through restrictions and check that there is at least one usedAsReloadTrigger restriction if (array_key_exists('usedAsReloadTrigger', $this->field->restrictions)) { $this->field->isReloadTrigger = true; return; } } $this->field->isReloadTrigger = false; } protected function setIsDisplayChanger(): void { if (isset($this->field->restrictions) && (is_array($this->field->restrictions))) { // loop through restrictions and check that there is at least one usedAsShowWhen restriction if (array_key_exists('usedAsShowWhen', $this->field->restrictions)) { $this->field->isDisplayChanger = true; } } } protected function setIsCalculationTrigger() { if (isset($this->field->restrictions) && (is_array($this->field->restrictions))) { // loop through restrictions and check that there is at least one usedAsReloadTrigger restriction if (array_key_exists('usedInCal', $this->field->restrictions)) { $this->field->isCalculationTrigger = true; return; } } $this->field->isCalculationTrigger = false; } // override a default value set in attribute_value if fillwith is not set to '0' protected function fillWith(): void { $field = $this->field; // no custom default value selection. // don't change 'attribute_value' if ((!isset($field->fillwith) || $field->fillwith === "0")) { return; } // process fillwith sql first if ($field->fillwith === 'sql') { try { $sqlHelper = new SqlHelper($field->defaultvalue_sql); $this->field->attribute_value = $sqlHelper->getItemsFromSQL('loadResult'); } catch (\Exception $e) { $this->field->attribute_value = ''; } return; } // this default value does not depend on the user being logged in if ($field->fillwith == "1") { $this->field->attribute_value = uniqid($this->field->attribute_value, true); return; } if ($field->fillwith == 'url') { $this->field->attribute_value = Uri::getInstance()->toString(); return; } // process fillwith user data // if we edit stored user inputs we want to use the user profile of the user who submitted the form as default fill with values if (($this->form->displayState === VisformsModelSite::$displayStateIsNewEditData) || ($this->form->displayState === VisformsModelSite::$displayStateIsRedisplayEditData)) { $data = $this->form->data; $userId = $data->created_by; if (!empty($userId)) { $user = new User($userId); } } // use user profile of logged-in user else { $user = Factory::getApplication()->getIdentity(); $userId = $user->id; } if ($userId != 0) { if ($field->fillwith == "2") { $this->field->attribute_value = $user->name; return; } if ($field->fillwith == "3") { $this->field->attribute_value = $user->username; return; } if ($field->fillwith == 'usermail') { $this->field->attribute_value = $user->email; return; } preg_match('/^CF(\d+)$/', $field->fillwith, $matches); if ($matches && !empty($matches[1])) { $customfieldid = $matches[1]; $value = HTMLHelper::_('visforms.getCustomUserFieldValue', $customfieldid, $user); // in error case, value === false // empty values in CF are not stored in the database // so value is never null or '' if ($value !== false) { $type = HTMLHelper::_('visforms.getCustomUserFieldType', $customfieldid); // remove potential time, format if ($type === 'calendar') { $value = HTMLHelper::_('date', $value, 'DATE_FORMAT_LC4'); } $this->field->attribute_value = $value ; return; } } $userProfile = UserHelper::getProfile($userId); if ((!(empty($userProfile->profile))) && (is_array($userProfile->profile)) && array_key_exists($field->fillwith, $userProfile->profile)) { $value = $userProfile->profile[$field->fillwith]; // if a user profile value is not set, the database value is '' if (!(empty($value))) { if ($field->fillwith === 'dob') { $value = HTMLHelper::_('date', $value, 'DATE_FORMAT_LC4'); } $this->field->attribute_value = $value; return; } } } // no value found, set attribute_value to '' $this->field->attribute_value = ''; } protected function setEditValue(): void { if ($this->isEditOrSaveEditTask) { $this->field->editValue = ""; $data = $this->form->data; $dataFieldName = $this->getParameterFieldNameForEditValue(); if (isset($data->$dataFieldName)) { $filter = InputFilter::getInstance(); $this->field->editValue = $filter->clean($data->$dataFieldName, 'STRING'); } } } protected function escapeCustomRegex(): void { if (!(isset($this->field->customvalidation))) { return; } $clean1 = str_replace("\/", "/", $this->field->customvalidation); $clean2 = str_replace("/", "\/", str_replace("\/", "/", $clean1)); $this->field->customvalidation = $clean2; } // create empty array as field parameter // can be used in business class of the field in order to set custom Javascript which is added in the 'View' Class (HTMLView/Vfformfiewmodel/VisformsHelper) // this is necessary in order to pass the information through session storage, if a form is redisplayed after php validation failed protected function setCustomJs(): void { $this->field->customJs = array(); $this->field->customJs['joomlaOptions'] = array(); $this->field->customJs['texts'] = array(); } protected function setFieldsetCounter(): void { $this->field->fieldsetCounter = $this->form->steps; } protected function mendInvalidUncheckedValue(): void { if (!empty(AefHelper::checkAEF())) { if (!isset($this->field->unchecked_value) || $this->field->unchecked_value === "") { $this->field->unchecked_value = 0; } $this->field->unchecked_value = trim(str_replace(",", ".", $this->field->unchecked_value)); } } protected function setEnterKeyAction(): void { if (!empty($this->form->preventsubmitonenter)) { $this->field->disableEnterKey = true; } } protected function setShowRequiredAsterix(): void { if (!empty($this->form->requiredasterix)) { $this->field->showRequiredAsterix = true; } } protected function replaceLabelWithCustomText(): void { if (!empty(AefHelper::checkAEF())) { if (!empty($this->field->customtext) && isset($this->field->customtextposition) && $this->field->customtextposition == "3") { // remove HTML block elements from custom text using Joomla input filter (list from https://www.w3schools.com/html/html_blocks.asp) $customBlocked = array('p', 'div', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'address', 'article', 'aside', 'blockquote', 'canvas', 'dd', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'header', 'hr', 'li', 'main', 'nav', 'noscript', 'ol', 'pre', 'section', 'table', 'tfoot', 'ul', 'video'); $defaultBlocked = InputFilter::getInstance()->blockedTags; // Joomla default block list $blockList = array_merge($customBlocked, $defaultBlocked); $label = InputFilter::getInstance()->emailToPunycode($this->field->customtext); $filter = InputFilter::getInstance( $blockList, // tag block list [], // attribute block list InputFilter::ONLY_BLOCK_DEFINED_TAGS, InputFilter::ONLY_BLOCK_DEFINED_ATTRIBUTES ); $label = trim($filter->clean($label, 'html')); // replace label, if we still have any text if (!empty($label)) { $this->field->label = $label; } } } } protected function setErrorMessageInForm($error): void { if ($error === '') { return; } if (!(isset($this->form->errors))) { $this->form->errors = array(); } if (is_array($this->form->errors)) { array_push($this->form->errors, $error); } } protected function addFormStep(): void { if ((isset($this->form->steps)) && (is_numeric($this->form->steps))) { $this->form->steps++; } else { $this->form->steps = 1; } if (empty($this->form->canHideSummaryOnMultiPageForms) && ($this->form->steps > 1)) { $this->form->displaysummarypage = true; } } protected function hasSearchableSelect(): void { if (!empty($this->field->is_searchable)) { if (isset($this->field->attribute_readonly)) { unset($this->field->is_searchable); } else { $this->form->hasSearchableSelect = true; } } } protected function setNoFocus(): void { $this->field->noFocus = true; } protected function getParameterFieldNameForEditValue(): string { return "F" . $this->field->id; } protected function getCustomAllowedCharacterMessage(): void { foreach ($this->validation_includes as $include) { if (!empty($this->field->$include)) { $chars = array(); foreach ($this->field->$include as $char) { // $char is a upper case name for the character. // We expect that there is a language tag with a specific prefix 'COM_VISFORMS_ALLOWED_CUSTOM_CHAR_' and the character name $chars[] = Text::_('COM_VISFORMS_ALLOWED_CUSTOM_CHAR_'. $char); } // create additional text for error messages $this->field->allowedCharMessage = Text::sprintf('COM_VISFORMS_ALLOWED_CUSTOM_CHARACTERS_MESSAGE_PHP', implode(', ', $chars)); } } } abstract protected function setField(): void; abstract protected function setConfigurationDefault(): void; abstract protected function setEditOnlyFieldDbValue(): void; // Set the default value of the field which is displayed in the form according field definition, query params, user inputs abstract protected function setFieldDefaultValue(): void; // Method to convert post values into a string that can be stored in db and attach it as property to the field object abstract protected function setDbValue(): void; abstract protected function setRedirectParam(): void; }