| @@ -114,12 +114,46 @@ | ||
| 114 | 114 | { |
| 115 | 115 | if (is_array($value)) { |
| 116 | 116 | $value = ''; |
| 117 | 117 | } |
| 118 | + $id = intval($this->id); | |
| 119 | + | |
| 120 | + // If resuming draft submission via Save & Continue and $value doesn't have saved_values, | |
| 121 | + // attempt to restore from draft $entry if available | |
| 122 | + if (empty($value) || (is_string($value) && strpos($value, 'saved_values') === false)) { | |
| 123 | + if (!empty($entry) && is_array($entry) && !empty($entry[$id])) { | |
| 124 | + $entry_data = maybe_unserialize($entry[$id]); | |
| 125 | + if (is_array($entry_data) && !empty($entry_data)) { | |
| 126 | + $decoded_value = !empty($value) ? json_decode($value, true) : array(); | |
| 127 | + if (!is_array($decoded_value)) { | |
| 128 | + $decoded_value = array(); | |
| 129 | + } | |
| 130 | + $row_ids = array_keys($entry_data); | |
| 131 | + $decoded_value['count'] = count($row_ids); | |
| 132 | + $decoded_value['id'] = $row_ids; | |
| 133 | + $saved_rows = array(); | |
| 134 | + foreach ($entry_data as $row_id => $row_inputs) { | |
| 135 | + if (is_array($row_inputs)) { | |
| 136 | + foreach ($row_inputs as $in_name => $in_val) { | |
| 137 | + if (is_array($in_val)) { | |
| 138 | + foreach ($in_val as $sub_k => $sub_v) { | |
| 139 | + $saved_rows[$row_id]['input_' . str_replace('.', '_', $sub_k) . '__' . $row_id] = $sub_v; | |
| 140 | + } | |
| 141 | + } else { | |
| 142 | + $saved_rows[$row_id][$in_name] = $in_val; | |
| 143 | + } | |
| 144 | + } | |
| 145 | + } | |
| 146 | + } | |
| 147 | + $decoded_value['saved_values'] = $saved_rows; | |
| 148 | + $value = wp_json_encode($decoded_value); | |
| 149 | + } | |
| 150 | + } | |
| 151 | + } | |
| 152 | + | |
| 118 | 153 | $is_entry_detail = $this->is_entry_detail(); |
| 119 | 154 | $is_form_editor = $this->is_form_editor(); |
| 120 | 155 | $form_id = $form['id']; |
| 121 | - $id = intval($this->id); | |
| 122 | 156 | $field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id"; |
| 123 | 157 | $size = $this->size; |
| 124 | 158 | $disabled_text = $is_form_editor ? "disabled='disabled'" : ''; |
| 125 | 159 | $class_suffix = $is_entry_detail ? '_admin' : ''; |
| @@ -145,10 +179,10 @@ | ||
| 145 | 179 | $limit = 9999; |
| 146 | 180 | } |
| 147 | 181 | $limit = apply_filters("yeeaddons_gf_repeater_limit", 5, $limit); |
| 148 | 182 | $initial_rows = apply_filters("yeeaddons_gf_repeater_initial_rows", 1, $initial_rows); |
| 149 | - $input = "<input data-initial_rows_map_check='" . $this->repeater_initial_rows_map . "' data-initial_rows_map='input_{$form_id}_" . $this->repeater_initial_rows_map . "' data-map_id='field_" . $form_id . "_" . $id . "' name='input_{$id}' id='{$field_id}' type='{$html_input_type}' value='{$value}' class='{$class}' {$tabindex} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>"; | |
| 150 | - $html = '<div data-initial_rows_map_check="' . $this->repeater_initial_rows_map . '" class="repeater-field-warp-item-data" data-initial_rows="' . $initial_rows . '" data-limit="' . $limit . '" data-initial_rows_map="input_' . $form_id . '_' . $this->repeater_initial_rows_map . '" data-map_id="field_' . $form_id . '_' . $id . '"> | |
| 183 | + $input = "<input data-initial_rows_map_check='" . esc_attr($this->repeater_initial_rows_map) . "' data-initial_rows_map='input_{$form_id}_" . esc_attr($this->repeater_initial_rows_map) . "' data-map_id='field_" . $form_id . "_" . $id . "' name='input_{$id}' id='{$field_id}' type='{$html_input_type}' value='" . esc_attr($value) . "' class='{$class}' {$tabindex} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>"; | |
| 184 | + $html = '<div data-initial_rows_map_check="' . esc_attr($this->repeater_initial_rows_map) . '" class="repeater-field-warp-item-data" data-initial_rows="' . $initial_rows . '" data-limit="' . $limit . '" data-initial_rows_map="input_' . $form_id . '_' . esc_attr($this->repeater_initial_rows_map) . '" data-map_id="field_' . $form_id . '_' . $id . '"> | |
| 151 | 185 | <div class="repeater-field-warp-item"> |
| 152 | 186 | </div> |
| 153 | 187 | <div class="repeater-field-footer"><a href="#"" class="gf-repeater-field-button-add" >' . $repeater_add_button . '</a></div> |
| 154 | 188 | ' . $input . ' |
| @@ -160,8 +194,72 @@ | ||
| 160 | 194 | } else { |
| 161 | 195 | return sprintf("<div class='ginput_container'>%s</div>", $html); |
| 162 | 196 | } |
| 163 | 197 | } |
| 198 | + public static function save_draft_submission_values($submitted_values, $form) | |
| 199 | + { | |
| 200 | + if (empty($form['fields']) || !is_array($form['fields'])) { | |
| 201 | + return $submitted_values; | |
| 202 | + } | |
| 203 | + | |
| 204 | + foreach ($form['fields'] as $field) { | |
| 205 | + if ($field->type !== 'repeater_end') { | |
| 206 | + continue; | |
| 207 | + } | |
| 208 | + | |
| 209 | + $raw_value = rgar($submitted_values, $field->id); | |
| 210 | + if (empty($raw_value)) { | |
| 211 | + $raw_value = rgpost('input_' . $field->id); | |
| 212 | + } | |
| 213 | + | |
| 214 | + if (empty($raw_value)) { | |
| 215 | + continue; | |
| 216 | + } | |
| 217 | + | |
| 218 | + $repeater_data = is_array($raw_value) ? $raw_value : json_decode($raw_value, true); | |
| 219 | + if (!is_array($repeater_data) || empty($repeater_data['id']) || !is_array($repeater_data['id'])) { | |
| 220 | + continue; | |
| 221 | + } | |
| 222 | + | |
| 223 | + // Capture all $_POST values for each repeater row | |
| 224 | + $saved_rows = array(); | |
| 225 | + foreach ($repeater_data['id'] as $id_rand) { | |
| 226 | + $row_data = array(); | |
| 227 | + foreach ($_POST as $post_key => $post_val) { | |
| 228 | + if (strpos($post_key, '__' . $id_rand) !== false) { | |
| 229 | + $row_data[$post_key] = wp_unslash($post_val); | |
| 230 | + } | |
| 231 | + } | |
| 232 | + | |
| 233 | + // Also check if any file was uploaded in this row | |
| 234 | + $transient_keys = array(); | |
| 235 | + $unique_id = rgpost('gform_unique_id'); | |
| 236 | + if (!empty($unique_id)) { | |
| 237 | + $transient_keys[] = 'gf_repeater_files_' . $unique_id; | |
| 238 | + } | |
| 239 | + $transient_keys[] = 'gf_repeater_files_' . $form['id']; | |
| 240 | + $transient_keys[] = 'gf_repeater_files_1'; | |
| 241 | + | |
| 242 | + foreach ($transient_keys as $t_key) { | |
| 243 | + $transient_files = get_transient($t_key); | |
| 244 | + if (is_array($transient_files)) { | |
| 245 | + foreach ($transient_files as $tk => $tv) { | |
| 246 | + if (strpos($tk, '__' . $id_rand) !== false && !empty($tv)) { | |
| 247 | + $row_data[$tk] = $tv; | |
| 248 | + } | |
| 249 | + } | |
| 250 | + } | |
| 251 | + } | |
| 252 | + | |
| 253 | + $saved_rows[$id_rand] = $row_data; | |
| 254 | + } | |
| 255 | + | |
| 256 | + $repeater_data['saved_values'] = $saved_rows; | |
| 257 | + $submitted_values[$field->id] = wp_json_encode($repeater_data); | |
| 258 | + } | |
| 259 | + | |
| 260 | + return $submitted_values; | |
| 261 | + } | |
| 164 | 262 | public static function remove_validation($form) |
| 165 | 263 | { |
| 166 | 264 | $zo = false; |
| 167 | 265 | $zo_datas = array(); |
| @@ -257,17 +355,27 @@ | ||
| 257 | 355 | } else { |
| 258 | 356 | $failedValidation = true; |
| 259 | 357 | } |
| 260 | 358 | break; |
| 359 | + case 'radio': | |
| 360 | + if (rgblank($getInputData)) { | |
| 361 | + $failedValidation = true; | |
| 362 | + } elseif ($getInputData === 'gf_other_choice') { | |
| 363 | + $other_val = rgpost($field . "_other__" . $id); | |
| 364 | + if (rgblank($other_val)) { | |
| 365 | + $failedValidation = true; | |
| 366 | + } | |
| 367 | + } | |
| 368 | + break; | |
| 261 | 369 | default: |
| 262 | 370 | if (is_array($getInputData)) { |
| 263 | 371 | foreach ($getInputData as $vl) { |
| 264 | - if (empty($vl)) { | |
| 372 | + if (rgblank($vl)) { | |
| 265 | 373 | $failedValidation = true; |
| 266 | 374 | } |
| 267 | 375 | } |
| 268 | 376 | } else { |
| 269 | - if (empty($getInputData)) { | |
| 377 | + if (rgblank($getInputData)) { | |
| 270 | 378 | $failedValidation = true; |
| 271 | 379 | } |
| 272 | 380 | } |
| 273 | 381 | break; |