OwlCyberSecurity - MANAGER
Edit File: GravityFormsMigrator.php
<?php namespace FluentForm\App\Services\Migrator\Classes; use FluentForm\App\Modules\Form\Form; use FluentForm\Framework\Helpers\ArrayHelper; class GravityFormsMigrator extends BaseMigrator { public function __construct() { $this->key = 'gravityform'; $this->title = 'Gravity Forms'; $this->shortcode = 'gravity_form'; $this->hasStep = false; } public function exist() { return class_exists('GFForms'); } /** * @param $form * @return array */ public function getFields($form) { $fluentFields = []; $fields = $form['fields']; foreach ($fields as $name => $field) { $field = (array)$field; list($type, $args) = $this->formatFieldData($field); if ($value = $this->getFluentClassicField($type, $args)) { $fluentFields[$field['id']] = $value; } else { $this->unSupportFields[] = ArrayHelper::get($field, 'label'); } } $submitBtn = $this->getSubmitBttn([ 'uniqElKey' => time(), 'class' => '', 'label' => ArrayHelper::get($form, 'button.text', 'Submit'), 'type' => ArrayHelper::get($form, 'button.type') == 'text' ? 'default' : 'image', 'img_url' => ArrayHelper::get($form, 'button.imageUrl'), ]); $returnData = [ 'fields' => $this->getContainer($fields, $fluentFields), 'submitButton' => $submitBtn ]; if ($this->hasStep && defined('FLUENTFORMPRO')) { $returnData['stepsWrapper'] = $this->getStepWrapper(); } return $returnData; } private function formatFieldData(array $field) { $args = [ 'uniqElKey' => $field['id'], 'index' => $field['id'], 'required' => $field['isRequired'], 'label' => $field['label'], 'label_placement' => $this->getLabelPlacement($field), 'admin_field_label' => ArrayHelper::get($field, 'adminLabel'), 'name' => $this->getInputName($field), 'placeholder' => ArrayHelper::get($field, 'placeholder'), 'class' => $field['cssClass'], 'value' => ArrayHelper::get($field, 'defaultValue'), 'help_message' => ArrayHelper::get($field, 'description'), ]; $type = ArrayHelper::get($this->fieldTypes(), $field['type'], ''); switch ($type) { case 'input_name': $args['input_name_args'] = $field['inputs']; $args['input_name_args']['first_name']['name'] = $this->getInputName($field['inputs'][1]); $args['input_name_args']['middle_name']['name'] = $this->getInputName($field['inputs'][2]); $args['input_name_args']['last_name']['name'] = $this->getInputName($field['inputs'][3]); $args['input_name_args']['first_name']['label'] = ArrayHelper::get($field['inputs'][1], 'label'); $args['input_name_args']['middle_name']['label'] = ArrayHelper::get($field['inputs'][2], 'label'); $args['input_name_args']['last_name']['label'] = ArrayHelper::get($field['inputs'][3], 'label'); $args['input_name_args']['first_name']['visible'] = ArrayHelper::get($field, 'inputs.1.isHidden', true); $args['input_name_args']['middle_name']['visible'] = ArrayHelper::get($field, 'inputs.2.isHidden', true); $args['input_name_args']['last_name']['visible'] = ArrayHelper::get($field, 'inputs.3.isHidden', true); break; case 'input_textarea': $args['maxlength'] = $field['maxLength']; break; case 'input_text': $args['maxlength'] = $field['maxLength']; $args['is_unique'] = ArrayHelper::isTrue($field, 'noDuplicates'); if (ArrayHelper::isTrue($field, 'inputMask')) { $type = 'input_mask'; $args['temp_mask'] = 'custom'; $args['mask'] = $field['inputMaskValue']; } if (ArrayHelper::isTrue($field, 'enablePasswordInput')) { $type = 'input_password'; } break; case 'address': $args['address_args'] = $this->getAddressArgs($field); break; case 'select': case 'input_radio': $optionData = $this->getOptions(ArrayHelper::get($field, 'choices')); $args['options'] = ArrayHelper::get($optionData, 'options'); $args['value'] = ArrayHelper::get($optionData, 'selectedOption.0'); case 'multi_select': case 'input_checkbox': $optionData = $this->getOptions(ArrayHelper::get($field, 'choices')); $args['options'] = ArrayHelper::get($optionData, 'options'); $args['value'] = ArrayHelper::get($optionData, 'selectedOption'); break; case 'input_date': if ($field['type'] == 'time') { $args['format'] = 'H:i'; $args['is_time_enabled'] = true; } break; case 'input_number': $args['min'] = $field['rangeMin']; $args['max'] = $field['rangeMax']; break; case 'repeater_field': $repeaterFields = ArrayHelper::get($field, 'choices', []); $args['fields'] = $this->getRepeaterFields($repeaterFields, $field['label']);; case 'input_file': $args['allowed_file_types'] = $this->getFileTypes($field, 'allowedExtensions'); $args['max_size_unit'] = 'MB'; $args['max_file_size'] = $this->getFileSize($field);; $args['max_file_count'] = ArrayHelper::isTrue($field, 'multipleFiles') ? $field['maxFiles'] : 1; $args['upload_btn_text'] = 'File Upload'; break; case 'custom_html': $args['html_codes'] = $field['content']; break; case 'section_break': $args['section_break_desc'] = $field['description']; break; case 'terms_and_condition': $args['tnc_html'] = $field['description']; break; case 'form_step': $this->hasStep = true; $args['next_btn'] = $field['nextButton']; $args['next_btn']['type'] = $field['nextButton']['type'] == 'text' ? 'default' : 'img'; $args['next_btn']['img_url'] = $field['nextButton']['imageUrl']; $args['prev_btn'] = $field['previousButton']; $args['prev_btn']['type'] = $field['previousButton']['type'] == 'text' ? 'default' : 'img'; $args['prev_btn']['img_url'] = $field['previousButton']['imageUrl']; break; } return array($type, $args); } private function getInputName($field) { return str_replace('-', '_', sanitize_title($field['label'] . '-' . $field['id'])); } private function getLabelPlacement($field) { if ($field['labelPlacement'] == 'hidden_label') { return 'hide_label'; } return 'top'; } /** * @param $field * @return filesize in MB */ private function getFileSize($field) { $fileSizeByte = ArrayHelper::get($field, 'maxFileSize', 10); if (empty($fileSizeByte)) { $fileSizeByte = 1; } $fileSizeMB = ceil($fileSizeByte * 1048576); // 1MB = 1048576 Bytes return $fileSizeMB; } /** * @return array */ public function fieldTypes() { $fieldTypes = [ 'email' => 'email', 'text' => 'input_text', 'name' => 'input_name', 'hidden' => 'input_hidden', 'textarea' => 'input_textarea', 'website' => 'input_url', 'phone' => 'phone', 'select' => 'select', 'list' => 'repeater_field', 'multiselect' => 'multi_select', 'checkbox' => 'input_checkbox', 'radio' => 'input_radio', 'date' => 'input_date', 'time' => 'input_date', 'number' => 'input_number', 'fileupload' => 'input_file', 'consent' => 'terms_and_condition', 'captcha' => 'reCaptcha', 'html' => 'custom_html', 'section' => 'section_break', 'page' => 'form_step', 'address' => 'address', ]; //todo pro fields remove return $fieldTypes; } /** * @param array $field * @return array[] */ private function getAddressArgs(array $field) { $required = ArrayHelper::isTrue($field, 'isRequired'); return [ 'address_line_1' => [ 'name' => $this->getInputName($field['inputs'][0]), 'label' => $field['inputs'][0]['label'], 'visible' => ArrayHelper::get($field, 'inputs.0.isHidden', true), 'required' => $required, ], 'address_line_2' => [ 'name' => $this->getInputName($field['inputs'][1]), 'label' => $field['inputs'][1]['label'], 'visible' => ArrayHelper::get($field, 'inputs.1.isHidden', true), 'required' => $required, ], 'city' => [ 'name' => $this->getInputName($field['inputs'][2]), 'label' => $field['inputs'][2]['label'], 'visible' => ArrayHelper::get($field, 'inputs.2.isHidden', true), 'required' => $required, ], 'state' => [ 'name' => $this->getInputName($field['inputs'][3]), 'label' => $field['inputs'][3]['label'], 'visible' => ArrayHelper::get($field, 'inputs.3.isHidden', true), 'required' => $required, ], 'zip' => [ 'name' => $this->getInputName($field['inputs'][4]), 'label' => $field['inputs'][4]['label'], 'visible' => ArrayHelper::get($field, 'inputs.4.isHidden', true), 'required' => $required, ], 'country' => [ 'name' => $this->getInputName($field['inputs'][5]), 'label' => $field['inputs'][5]['label'], 'visible' => ArrayHelper::get($field, 'inputs.5.isHidden', true), 'required' => $required, ], ]; } /** * @param $options * @return array */ public function getOptions($options = []) { $formattedOptions = []; $selectedOption = []; foreach ($options as $key => $option) { $arr = [ 'label' => ArrayHelper::get($option, 'text', 'Item -' . $key), 'value' => ArrayHelper::get($option, 'value'), 'id' => ArrayHelper::get($option, $key) ]; if (ArrayHelper::isTrue($option, 'isSelected')) { $selectedOption[] = ArrayHelper::get($option, 'value', ''); } $formattedOptions[] = $arr; } return ['options' => $formattedOptions, 'selectedOption' => $selectedOption]; } /** * @param $repeaterFields * @param $label * @return array */ protected function getRepeaterFields($repeaterFields, $label) { $arr = []; if (empty($repeaterFields)) { $arr[] = [ 'element' => 'input_text', 'attributes' => array( 'type' => 'text', 'value' => '', 'placeholder' => '', ), 'settings' => array( 'label' => $label, 'help_message' => '', 'validation_rules' => array( 'required' => array( 'value' => false, 'message' => __('This field is required', 'fluentform'), ), ) ) ]; } else { foreach ($repeaterFields as $serial => $repeaterField) { $arr[] = [ 'element' => 'input_text', 'attributes' => array( 'type' => 'text', 'value' => '', 'placeholder' => '', ), 'settings' => array( 'label' => ArrayHelper::get($repeaterField, 'label', ''), 'help_message' => '', 'validation_rules' => array( 'required' => array( 'value' => false, 'message' => __('This field is required', 'fluentform'), ), ) ) ]; } } return $arr; } private function getContainer($fields, $fluentFields) { $layoutGroupIds = array_column($fields, 'layoutGroupId'); $cols = array_count_values($layoutGroupIds); // if inputs has more then one duplicate layoutGroupIds then it has container if (intval($cols) < 2) { return $fluentFields; } $final = []; //get fields array for inserting into containers $containers = self::getLayout($fields); //set fields array map for inserting into containers foreach ($containers as $index => $fields) { $final[$index][] = array_map(function ($id) use ($fluentFields) { if (isset($fluentFields[$id])) { return $fluentFields[$id]; } }, $fields); } $final = self::arrayFlat($final); $withContainer = []; foreach ($final as $row => $columns) { $colsCount = count($columns); $containerConfig = []; //with container if ($colsCount != 1) { $fields = []; foreach ($columns as $col) { $fields[]['fields'] = [$col]; } $containerConfig[] = [ 'index' => $row, 'element' => 'container', "attributes" => [], 'settings' => [ 'container_class', 'conditional_logics' ], 'editor_options' => [ 'title' => $colsCount . ' Column Container', 'icon_class' => 'ff-edit-column-' . $colsCount ], 'columns' => $fields, 'uniqElKey' => 'col' . '_' . md5(uniqid(mt_rand(), true)) ]; } else { //without container $containerConfig = $columns; } $withContainer[] = $containerConfig; } return (array_filter(self::arrayFlat($withContainer))); } protected static function getLayout($fields, $id = '') { $layoutGroupIds = array_column($fields, 'layoutGroupId'); $rows = array_count_values($layoutGroupIds); $layout = []; foreach ($rows as $key => $value) { $layout[] = self::getInputIdsFromLayoutGrp($key, $fields); } return $layout; } public static function getInputIdsFromLayoutGrp($id, $array) { $keys = []; foreach ($array as $key => $val) { if ($val['layoutGroupId'] === $id) { $keys[] = $val['id']; } } return $keys; } /** * @param null $array * @param int $depth * @return array */ public static function arrayFlat($array = null, $depth = 1) { $result = []; if (!is_array($array)) { $array = func_get_args(); } foreach ($array as $key => $value) { if (is_array($value) && $depth) { $result = array_merge($result, self::arrayFlat($value, $depth - 1)); } else { $result = array_merge($result, [$key => $value]); } } return $result; } /** * @return array */ private function getStepWrapper() { return [ 'stepStart' => [ 'element' => 'step_start', 'attributes' => [ 'id' => '', 'class' => '', ], 'settings' => [ 'progress_indicator' => 'progress-bar', 'step_titles' => [], 'disable_auto_focus' => 'no', 'enable_auto_slider' => 'no', 'enable_step_data_persistency' => 'no', 'enable_step_page_resume' => 'no', ], 'editor_options' => [ 'title' => 'Start Paging' ], ], 'stepEnd' => [ 'element' => 'step_end', 'attributes' => [ 'id' => '', 'class' => '', ], 'settings' => [ 'prev_btn' => [ 'type' => 'default', 'text' => 'Previous', 'img_url' => '' ] ], 'editor_options' => [ 'title' => 'End Paging' ], ] ]; } /** * @param $form * @return array default parsed form metas * @throws \Exception */ public function getFormMetas($form) { $formObject = new Form(wpFluentForm()); $defaults = $formObject->getFormsDefaultSettings(); $array = array_reverse($form['confirmations']); $firstConfirmation = array_pop($array); $confirmation = wp_parse_args( [ 'messageToShow' => $firstConfirmation['message'], 'samePageFormBehavior' => 'hide_form', ], $defaults['confirmation'] ); $defaults['restrictions']['requireLogin']['enabled'] = ArrayHelper::isTrue($form, 'requireLogin'); $defaults['restrictions']['requireLogin']['requireLoginMsg'] = ArrayHelper::isTrue($form, 'requireLoginMessage'); $defaults['restrictions']['limitNumberOfEntries']['enabled'] = ArrayHelper::isTrue($form, 'limitEntries'); $defaults['restrictions']['limitNumberOfEntries']['numberOfEntries'] = ArrayHelper::isTrue($form, 'limitEntriesCount'); $defaults['restrictions']['limitNumberOfEntries']['period'] = ArrayHelper::isTrue($form, 'limitEntriesPeriod'); $defaults['restrictions']['limitNumberOfEntries']['limitReachedMsg'] = ArrayHelper::isTrue($form, 'limitEntriesMessage'); $defaults['restrictions']['scheduleForm']['enabled'] = ArrayHelper::isTrue($form, 'scheduleForm'); $defaults['restrictions']['scheduleForm']['start'] = ArrayHelper::isTrue($form, 'scheduleStart'); $defaults['restrictions']['scheduleForm']['end'] = ArrayHelper::isTrue($form, 'scheduleEnd'); $defaults['restrictions']['scheduleForm']['pendingMsg'] = ArrayHelper::isTrue($form, 'schedulePendingMessage'); $defaults['restrictions']['scheduleForm']['expiredMsg'] = ArrayHelper::isTrue($form, 'scheduleMessage'); $advancedValidation = [ 'status' => false, 'type' => 'all', 'conditions' => [ [ 'field' => '', 'operator' => '=', 'value' => '' ] ], 'error_message' => '', 'validation_type' => 'fail_on_condition_met' ]; $notifications = []; foreach ($form['notifications'] as $notification) { $notifications[] = [ 'sendTo' => [ 'type' => 'email', 'email' => str_replace('{admin_email}', '{wp.admin_email}', $notification['to']), 'field' => '', 'routing' => [], ], 'enabled' => ArrayHelper::isTrue($notification, 'isActive'), 'name' => $notification['name'], 'subject' => $notification['subject'], 'to' => str_replace('{admin_email}', '{wp.admin_email}', $notification['to']), 'replyTo' => ArrayHelper::get($notification, 'replyTo'), 'message' => str_replace('{all_fields}', '{all_data}', $notification['message']), 'fromName' => ArrayHelper::get($notification, 'fromName'), 'fromAddress' => ArrayHelper::get($notification, 'from'), 'bcc' => ArrayHelper::get($notification, 'bcc'), 'cc' => ArrayHelper::get($notification, 'cc'), ]; } return [ 'formSettings' => [ 'confirmation' => $confirmation, 'restrictions' => $defaults['restrictions'], 'layout' => $defaults['layout'], ], 'advancedValidationSettings' => $advancedValidation, 'delete_entry_on_submission' => 'no', 'notifications' => $notifications ]; } public function getFormsFormatted() { $forms = []; $items = $this->getForms(); foreach ($items as $item) { $forms[] = [ 'name' => $this->getFormName($item), 'id' => $this->getFormId($item), 'imported_ff_id' => $this->isAlreadyImported($item), ]; } return $forms; } protected function getForms() { $forms = \GFAPI::get_forms(); return $forms; } protected function getForm($id) { if ($form = \GFAPI::get_form($id)) { return $form; } return false; } protected function getFormName($form) { return $form['title']; } public function getEntries($formId) { $form = $this->getForm($formId); if (empty($form)) { return false; } /** * Note - more-then 5000/6000 (based on sever) entries process make timout response / set default limit 1000 * @todo need silently async processing for support all entries migrate at a time, and improve frontend entry-migrate with more settings options */ $totalEntries = \GFAPI::count_entries($formId); $perPage = apply_filters('fluentform/entry_migration_max_limit', static::DEFAULT_ENTRY_MIGRATION_MAX_LIMIT, $this->key , $totalEntries, $formId); $offset = 0; $paging = [ 'offset' => $offset, 'page_size' => $perPage ]; $shorting = [ 'key' => 'id', 'direction' => 'ASC', ]; $submissions = \GFAPI::get_entries($formId, [], $shorting, $paging); $entries = []; if (!is_array($submissions)) { return $entries; } $fieldsMap = $this->getFields($form); foreach ($submissions as $submission) { $entry = []; foreach ($fieldsMap['fields'] as $id => $field) { $name = ArrayHelper::get($field, 'attributes.name'); if (!$name) { continue; } $type = ArrayHelper::get($field, 'element'); $fieldModel = \GFFormsModel::get_field($form, $id); // format entry value by field name $finalValue = null; if ("input_file" == $type && $value = $this->getSubmissionValue($id, $submission)) { $finalValue = $this->migrateFilesAndGetUrls($value); } elseif ("repeater_field" == $type && $value = $this->getSubmissionValue($id, $submission)) { if ($repeatData = (array)maybe_unserialize($value)) { $finalValue = []; foreach ($repeatData as $data) { $finalValue[] = array_values($data); } } } elseif ( "select" == $type && ArrayHelper::isTrue($field, 'attributes.multiple') && $value = $this->getSubmissionValue($id, $submission) ) { $finalValue = \json_decode($value); } elseif ( in_array($type, ["input_checkbox", "address", "input_name", "terms_and_condition"]) && isset($fieldModel['inputs']) ) { $finalValue = $this->getSubmissionArrayValue($type, $field, $fieldModel['inputs'], $submission); if ("input_checkbox" == $type) { $finalValue = array_values($finalValue); } elseif ("terms_and_condition" == $type) { $finalValue = $finalValue ? 'on' : 'off'; } } if (!$finalValue) { $finalValue = is_object($fieldModel) ? $fieldModel->get_value_export($submission, $id) : ''; } $entry[$name] = $finalValue; } if ($created_at = ArrayHelper::get($submission, 'date_created')) { $entry['created_at'] = $created_at; } if ($updated_at = ArrayHelper::get($submission, 'date_updated')) { $entry['updated_at'] = $updated_at; } $entries[] = $entry; } return $entries; } /** * @param $form * @return mixed */ protected function getFormId($form) { if (isset($form['id'])) { return $form['id']; } return false; } protected function getSubmissionArrayValue($type, $field, $inputs, $submission) { $arrayValue = []; foreach ($inputs as $input) { if (!isset($submission[$input['id']])) { continue; } if ("input_name" == $type && $subFields = ArrayHelper::get($field, 'fields')) { foreach ($subFields as $subField) { if ( $input['label'] == ArrayHelper::get($subField, 'settings.label') && $subName = ArrayHelper::get($subField, 'attributes.name', '') ) { $arrayValue[$subName] = $submission[$input['id']]; } } } else { $arrayValue[] = $submission[$input['id']]; } } if ('address' == $type) { $arrayValue = array_combine([ "address_line_1", "address_line_2", "city", "state", "zip", "country" ], $arrayValue); } return array_filter($arrayValue); } protected function getSubmissionValue($id, $submission) { return isset($submission[$id]) ? $submission[$id] : ""; } }