fields = $fields; $this->with = $with; $this->inputTypes = $inputTypes; } /** * The extractor initializer for getting the extracted data. * * @return array */ public function extract() { $this->looper($this->fields); return $this->result; } /** * The recursive looper method to loop each * of the fields and extract it's data. * * @param array $fields */ protected function looper($fields = []) { foreach ($fields as $field) { // If the field is a Container (collection of other fields) // then we will recursively call this function to resolve. if (Arr::get($field, 'element') === 'container') { $columns = Arr::get($field, 'columns', []); foreach ($columns as $item) { $itemFields = Arr::get($item, 'fields', []); $this->looper($itemFields); } } // Now the field is supposed to be a flat field. // We can extract the desired keys as we want. else { $element = Arr::get($field, 'element'); if ($element && in_array($element, $this->inputTypes)) { $this->extractField($field); } } } } /** * The extractor initializer for getting the extracted data. * * @return array */ public function extractEssentials($formData) { $this->looperEssential($formData, $this->fields); return $this->result; } /** * The recursive looper method to loop each * of the fields and extract it's data. * * @param array $fields */ protected function looperEssential($formData, $fields = []) { foreach ($fields as $field) { $field['conditionals'] = Arr::get($field, 'settings.conditional_logics', []); $matched = ConditionAssesor::evaluate($field, $formData); if (!$matched) { continue; } // If the field is a Container (collection of other fields) // then we will recursively call this function to resolve. if (Arr::get($field, 'element') === 'container') { $columns = Arr::get($field, 'columns', []); foreach ($columns as $item) { $itemFields = Arr::get($item, 'fields', []); $this->looperEssential($formData, $itemFields); } } // Now the field is supposed to be a flat field. // We can extract the desired keys as we want. else { $element = Arr::get($field, 'element'); if ($element && in_array($element, $this->inputTypes)) { $this->extractField($field); } } } } /** * Extract the form field. * * @param array $field * @return $this */ protected function extractField($field) { // Before starting the extraction we'll set the current // field and it's attribute name at first. And then we // will proceed to extract the field settings that // the developer demanded using $with initially. $this->prepareIteration($field, Arr::get($field, 'attributes.name')) ->setElement() ->setAdminLabel() ->setLabel() ->setOptions() ->setAdvancedOptions() ->setSettings() ->setRaw() ->setAttributes() ->setValidations() ->handleCustomField(); return $this; } /** * Set the field and attribute of the current iteration when * we loop through the form fields using the looper method. * * @param array $field * @param string $attribute * @return $this */ protected function prepareIteration($field, $attribute) { $this->field = $field; $this->attribute = $attribute; return $this; } /** * Set the element of the form field. * * @param array $field * @param string $attributeName * @return $this */ protected function setElement() { $this->result[$this->attribute]['element'] = Arr::get($this->field, 'element', ''); return $this; } /** * Set the label of the form field. * * @return $this */ protected function setLabel() { if (in_array('label', $this->with)) { $this->result[$this->attribute]['label'] = Arr::get($this->field, 'settings.label', ''); } return $this; } /** * Set the admin label of the form field. * * @return $this */ protected function setAdminLabel() { if (in_array('admin_label', $this->with)) { $adminLabel = Arr::get($this->field, 'settings.admin_field_label') ?: Arr::get($this->field, 'settings.label') ?: Arr::get($this->field, 'element'); $this->result[$this->attribute]['admin_label'] = $adminLabel; } return $this; } /** * Set the options of the form field. * * @return $this */ protected function setOptions() { if (in_array('options', $this->with)) { $options = Arr::get($this->field, 'options', []); if(!$options) { $newOptions = \FluentForm\App\Helpers\Helper::flattenAdvancedOptions( Arr::get($this->field, 'settings.advanced_options', []) ); if( !$newOptions && Arr::get($this->field,'element') == 'multi_payment_component' && Arr::get($this->field,'attributes.type') != 'single' ) { $pricingOptions = Arr::get($this->field, 'settings.pricing_options', []); foreach ($pricingOptions as $pricingOption) { $newOptions[] = [ 'value' => $pricingOption['label'], 'label' => $pricingOption['label'] ]; } } $options = []; if($newOptions) { foreach ($newOptions as $option) { $value = sanitize_text_field($option['value']); $options[$value] = sanitize_text_field($option['label']); } } } $this->result[$this->attribute]['options'] = $options; } return $this; } /** * Set the advanced options of the form field. * * @return $this */ protected function setAdvancedOptions() { if (in_array('advanced_options', $this->with)) { $this->result[$this->attribute]['advanced_options'] = Arr::get($this->field, 'settings.advanced_options', []); } return $this; } protected function setSettings() { if (in_array('settings', $this->with)) { $this->result[$this->attribute]['settings'] = Arr::get($this->field, 'settings', []); } return $this; } /** * Set the attributes of the form field. * * @return $this */ protected function setAttributes() { if (in_array('attributes', $this->with)) { $this->result[$this->attribute]['attributes'] = Arr::get($this->field, 'attributes'); } return $this; } /** * Set the validation rules and conditions of the form field. * * @return $this */ protected function setValidations() { if (in_array('rules', $this->with)) { $this->result[$this->attribute]['rules'] = Arr::get( $this->field, 'settings.validation_rules' ); $this->handleMaxLengthValidation(); $this->result[$this->attribute]['conditionals'] = Arr::get( $this->field, 'settings.conditional_logics' ); } return $this; } protected function handleMaxLengthValidation() { $maxLength = Arr::get($this->field, 'attributes.maxlength'); $fieldHasMaxValidation = Arr::get($this->field, 'settings.validation_rules.max'); $shouldSetMaxValidation = $maxLength && !$fieldHasMaxValidation; if ($shouldSetMaxValidation) { $message = Helper::getGlobalDefaultMessage('max'); if (!$message) { $message = __('Validation fails for maximum value', 'fluentform'); } $this->result[$this->attribute]['rules']['max'] = [ 'value' => $maxLength, 'message' => $message, ]; } return $this; } /** * Handle the child fields of complex form fields (address, name, repeater). * * This method processes fields that have sub-fields (like address field having * address_line_1, city, state, etc.) and prepares them for shortcode generation. * * @return $this */ protected function handleCustomField() { // If this field is a custom field we'll assume it has it's child fields // under the `fields` key. Then we are gonna modify those child fields' // attribute `name`, `label` & `conditional_logics` properties using // the parent field. The current implementation will modify those // properties in a way so that we can use dot notation to access. $customFields = Arr::get($this->field, 'fields'); if ($customFields) { $parentAttribute = Arr::get($this->field, 'attributes.name'); $parentConditionalLogics = Arr::get($this->field, 'settings.conditional_logics', []); $isAddressOrNameField = in_array(Arr::get($this->field, 'element'), ['address', 'input_name']); $isRepeatField = Arr::get($this->field, 'element') === 'input_repeat' || Arr::get($this->field, 'element') == 'repeater_field'; // Allow plugins to modify custom fields before processing $customFields = apply_filters('fluentform/extractor_parser_custom_fields', $customFields, $this->field); foreach ($customFields as $index => $customField) { // If the current field is in fact `address` || `name` field // then we have to only keep the enabled child fields // by the user from the form editor settings. if ($isAddressOrNameField) { $subFieldName = Arr::get($customField, 'attributes.name'); if (!Arr::get($customField, 'settings.visible', false) && !in_array($subFieldName, ['latitude', 'longitude'])) { unset($customFields[$index]); continue; } } // Depending on whether the parent field is a repeat field or not // the modified attribute name of the child field will vary. if ($isRepeatField) { $modifiedAttribute = $parentAttribute.'['.$index.'].*'; } else { $modifiedAttribute = $parentAttribute.'['.Arr::get($customField, 'attributes.name').']'; } $modifiedLabel = $parentAttribute.'['.Arr::get($customField, 'settings.label').']'; $customField['attributes']['name'] = $modifiedAttribute; $customField['settings']['label'] = $modifiedLabel; // Now, we'll replace the `conditional_logics` property $customField['settings']['conditional_logics'] = $parentConditionalLogics; // Now that this field's properties are handled we can pass // it to the extract field method to extract it's data. $this->extractField($customField); } } return $this; } /** * Set the raw field of the form field. * * @return $this */ protected function setRaw() { if (in_array('raw', $this->with)) { $this->result[$this->attribute]['raw'] = $this->field; } return $this; } }