PluginProbe
Repeater Fields for Gravity Forms / 3.2.1
Repeater Fields for Gravity Forms v3.2.1
3.2.2 3.2.1 3.2.0 3.1.1 3.1.0 3.0.4 3.0.3 3.0.2 3.0.1 3.0.0 2.5.1 2.5.0 2.4.6 trunk 2.0.5 2.0.9 2.1.0 2.3.2 2.3.7 2.4.1 2.4.3 2.4.4 2.4.5
← All changes | fields/repeater_field.php +386 -123 2.5.0 → 3.2.1 View file →
@@ -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();
@@ -179,8 +277,9 @@
179 277 if (!isset($field->repeater_validate)) {
180 278 $field->repeater_validate = array("isRequired" => $field->isRequired);
181 279 }
182 280 $field->isRequired = false;
281 + $field->validateState = false;
183 282 }
184 283 }
185 284 return $form;
186 285 }
@@ -256,17 +355,27 @@
256 355 } else {
257 356 $failedValidation = true;
258 357 }
259 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;
260 369 default:
261 370 if (is_array($getInputData)) {
262 371 foreach ($getInputData as $vl) {
263 - if (empty($vl)) {
372 + if (rgblank($vl)) {
264 373 $failedValidation = true;
265 374 }
266 375 }
267 376 } else {
268 - if (empty($getInputData)) {
377 + if (rgblank($getInputData)) {
269 378 $failedValidation = true;
270 379 }
271 380 }
272 381 break;
@@ -371,17 +480,25 @@
371 480 public function get_value_save_entry($value, $form, $input_name, $lead_id, $lead)
372 481 {
373 482 $this->lead_id = $lead_id;
374 483 $datas = json_decode($value, true);
375 - //var_dump($value);
484 + if (!is_array($datas) || !isset($datas["id"]) || !is_array($datas["id"])) {
485 + return maybe_serialize(array());
486 + }
487 +
376 488 $values = array();
377 489 $form_id = $this->formId;
378 490 $get_form = GFFormsModel::get_form_meta_by_id($form_id);
379 491 $form = $get_form[0];
380 492 $fields = array();
381 - foreach ($datas["fields"] as $f) {
382 - $datas_f = explode(".", $f);
383 - $fields[] = $datas_f[0];
493 + if (isset($datas["fields"]) && is_array($datas["fields"])) {
494 + foreach ($datas["fields"] as $f) {
495 + if (!is_string($f) || empty($f)) {
496 + continue;
497 + }
498 + $datas_f = explode(".", $f);
499 + $fields[] = $datas_f[0];
500 + }
384 501 }
385 502 $fields = array_unique($fields);
386 503 foreach ($datas["id"] as $id_rand) {
387 504 $datas_step = array();
@@ -392,9 +509,17 @@
392 509 $getInputData = array();
393 510 foreach ($inputs as $child_input) {
394 511 $getInputName = "input_" . $child_input["id"] . "__" . $id_rand;
395 512 $vl = rgpost(str_replace('.', '_', strval($getInputName)));
396 - if ($vl != "") {
513 + if ($vl !== "" && $vl !== false && $vl !== null) {
514 + $child_field_type = $this->get_type($form, "input_" . $child_input["id"], $form_id);
515 + if (is_string($vl)) {
516 + if ($child_field_type === 'textarea') {
517 + $vl = sanitize_textarea_field($vl);
518 + } else {
519 + $vl = sanitize_text_field($vl);
520 + }
521 + }
397 522 $getInputData[$child_input["id"]] = $vl;
398 523 }
399 524 }
400 525 $datas_step[$getInputName] = $getInputData;
@@ -399,16 +524,89 @@
399 524 }
400 525 $datas_step[$getInputName] = $getInputData;
401 526 } else {
402 527 $getInputName = $field . "__" . $id_rand;
403 - if (isset($_FILES[$getInputName])) {
404 - $datas_step[$getInputName] = apply_filters("yeeaddons_gf_repeater_file", "Upgrade to pro version", $form_id, $_FILES[$getInputName]);
405 - } else if (isset($_POST[$getInputName])) {
406 - $datas_step[$getInputName] = rgpost(str_replace('.', '_', strval($getInputName)));
407 - } else {
408 - $getInputData = rgpost(str_replace('.', '_', strval($getInputName)));
409 - $datas_step[$getInputName] = $getInputData;
528 + $saved_url = '';
529 +
530 + // 1. Check transient saved across multi-step pages by gform_unique_id or form_id
531 + $unique_id = rgpost('gform_unique_id');
532 + $transient_keys = array();
533 + if (!empty($unique_id)) {
534 + $transient_keys[] = 'gf_repeater_files_' . $unique_id;
410 535 }
536 + $transient_keys[] = 'gf_repeater_files_' . $form_id;
537 + $transient_keys[] = 'gf_repeater_files_1';
538 +
539 + foreach ($transient_keys as $t_key) {
540 + $transient_files = get_transient($t_key);
541 + if (is_array($transient_files)) {
542 + if (!empty($transient_files[$getInputName])) {
543 + $saved_url = $transient_files[$getInputName];
544 + break;
545 + }
546 + // Also check alternative key name format
547 + foreach ($transient_files as $tk => $tv) {
548 + if (strpos($tk, '__' . $id_rand) !== false && !empty($tv)) {
549 + $clean_f = str_replace('gform_multifile_upload_' . $form_id . '_', '', $field);
550 + $clean_f = str_replace('input_', '', $clean_f);
551 + if (strpos($tk, '_' . $clean_f . '__') !== false || strpos($tk, 'input_' . $clean_f . '__') !== false) {
552 + $saved_url = $tv;
553 + break 2;
554 + }
555 + }
556 + }
557 + }
558 + }
559 +
560 +
561 + // 2. Check if $_POST contains a direct URL
562 + if (empty($saved_url)) {
563 + $post_val = rgpost(str_replace('.', '_', strval($getInputName)));
564 + if (!empty($post_val) && is_string($post_val) && strpos($post_val, 'http') === 0) {
565 + $saved_url = $post_val;
566 + }
567 + }
568 +
569 + // 3. Check gform_uploaded_files (GF native temp file store)
570 + if (empty($saved_url)) {
571 + $uploaded_files_json = rgpost('gform_uploaded_files');
572 + if (!empty($uploaded_files_json)) {
573 + $uploaded_files = json_decode(stripslashes($uploaded_files_json), true);
574 + if (is_array($uploaded_files) && isset($uploaded_files[$getInputName])) {
575 + $file_info = $uploaded_files[$getInputName];
576 + if (is_string($file_info) && strpos($file_info, 'http') === 0) {
577 + $saved_url = $file_info;
578 + }
579 + }
580 + }
581 + }
582 +
583 + // 4. Check $_FILES if uploaded on the current submit step
584 + if (empty($saved_url) && isset($_FILES[$getInputName]) && !empty($_FILES[$getInputName]['name']) && (is_array($_FILES[$getInputName]['name']) ? !empty(array_filter($_FILES[$getInputName]['name'])) : ($_FILES[$getInputName]['error'] === UPLOAD_ERR_OK))) {
585 + $res = apply_filters("yeeaddons_gf_repeater_file", "", $form_id, $_FILES[$getInputName]);
586 + if ($res && $res !== "Upgrade to pro version") {
587 + $saved_url = $res;
588 + }
589 + }
590 +
591 + // 5. Fallback to $_POST value if available
592 + if (empty($saved_url)) {
593 + $saved_url = rgpost(str_replace('.', '_', strval($getInputName)));
594 + }
595 +
596 + // Sanitize theo kiểu trường trước khi lưu vào DB
597 + $field_type = $this->get_type($form, $field, $form_id);
598 + if (is_string($saved_url)) {
599 + if ($field_type === 'textarea') {
600 + $saved_url = sanitize_textarea_field($saved_url);
601 + } elseif ($field_type === 'fileupload' || filter_var($saved_url, FILTER_VALIDATE_URL) !== false) {
602 + $saved_url = esc_url_raw($saved_url);
603 + } else {
604 + $saved_url = sanitize_text_field($saved_url);
605 + }
606 + }
607 +
608 + $datas_step[$getInputName] = $saved_url;
411 609 }
412 610 }
413 611 $values[$id_rand] = $datas_step;
414 612 }
@@ -452,14 +650,20 @@
452 650 $dataArray = GFFormsModel::unserialize($value);
453 651 $get_form = GFFormsModel::get_form_meta_by_id($form_id);
454 652 $form = $get_form[0];
455 653 if (isset($_GET['lid'])) {
456 - $result = GFAPI::get_entry($_GET['lid']);
654 + $result = GFAPI::get_entry(absint($_GET['lid']));
457 655 } else {
458 656 $table = $wpdb->prefix . "gf_entry";
459 657 $mylink = $wpdb->get_row("SELECT id FROM $table ORDER BY id DESC");
460 - $result = GFAPI::get_entry($mylink->id);
658 + $result = ($mylink && isset($mylink->id)) ? GFAPI::get_entry($mylink->id) : array();
461 659 }
660 + if (!is_array($result) || is_wp_error($result)) {
661 + $result = array();
662 + }
663 + if (!is_array($dataArray) || empty($dataArray)) {
664 + return '';
665 + }
462 666 if ($format === 'html') {
463 667 $html = '<ol>';
464 668 foreach ($dataArray as $step_datas) {
465 669 $html .= '<li><ul>';
@@ -464,85 +668,132 @@
464 668 foreach ($dataArray as $step_datas) {
465 669 $html .= '<li><ul>';
466 670 foreach ($step_datas as $name => $vl) {
467 671 $type = $this->get_type($form, $name, $form_id);
468 - $lb = $this->get_field_label($form, $name, $type, false, $form_id);
672 + $lb = $this->get_custom_field_label($form, $name, $type, false, $form_id);
469 673 if (is_array($vl)) {
470 674 switch ($type) {
471 675 case "address":
472 676 $vl_data = "";
473 677 foreach ($vl as $k => $v) {
474 - $child_lb = $this->get_field_label($form, "input_" . $k, $type, true);
475 - $vl_data .= $child_lb . ": " . $v . "<br>";
678 + $child_lb = $this->get_custom_field_label($form, "input_" . $k, $type, true);
679 + $vl_data .= esc_html($child_lb) . ": " . esc_html($v) . "<br>";
476 680 }
477 - $html .= '<li>' . $lb . ": <br>" . $vl_data . "</li>";
681 + $html .= '<li>' . esc_html($lb) . ": <br>" . $vl_data . "</li>";
478 682 break;
479 683 default:
480 - $vl_data = implode(", ", $vl);
481 - $html .= '<li>' . $lb . ": " . $vl_data . "</li>";
684 + $vl_data = implode(", ", array_map('esc_html', $vl));
685 + $html .= '<li>' . esc_html($lb) . ": " . $vl_data . "</li>";
482 686 break;
483 687 }
484 688 } else {
485 689 $vl_data = $vl;
690 +
691 + // Helper functions kiểm tra và render file/hình ảnh
692 + $encode_url = function ($url) {
693 + return preg_replace_callback('/[^\x20-\x7E]/u', function ($match) {
694 + return rawurlencode($match[0]);
695 + }, trim($url));
696 + };
697 +
698 + $is_valid_url = function ($url) use ($encode_url) {
699 + if (empty($url))
700 + return false;
701 + $encoded = $encode_url($url);
702 + return filter_var($encoded, FILTER_VALIDATE_URL) !== false;
703 + };
704 +
705 + $is_image_url = function ($url) {
706 + if (!is_string($url) || empty($url))
707 + return false;
708 + $clean_path = parse_url($url, PHP_URL_PATH);
709 + if (!$clean_path) {
710 + $clean_path = $url;
711 + }
712 + $ext = strtolower(pathinfo($clean_path, PATHINFO_EXTENSION));
713 + return in_array($ext, array('jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico', 'avif', 'heic'), true);
714 + };
715 +
716 + $render_file_or_image = function ($file_url, $display_name = '') use ($is_image_url) {
717 + $file_url = trim($file_url);
718 + if (empty($file_url))
719 + return '';
720 + $filename = !empty($display_name) ? $display_name : basename($file_url);
721 +
722 + if ($is_image_url($file_url)) {
723 + return '<a href="' . esc_url($file_url) . '" target="_blank" class="repeater-image-preview" style="display:inline-block; margin: 4px 6px 4px 0;">'
724 + . '<img src="' . esc_url($file_url) . '" alt="' . esc_attr($filename) . '" style="max-width: 150px; max-height: 150px; object-fit: contain; border-radius: 4px; border: 1px solid #e2e8f0; display: inline-block; vertical-align: middle;" />'
725 + . '</a>';
726 + } else {
727 + return '<a href="' . esc_url($file_url) . '" download>' . esc_html($filename) . '</a>';
728 + }
729 + };
730 +
486 731 switch ($type) {
487 732 case "fileupload":
488 - if ($vl_data == "Upgrade to pro version") {
489 - $html .= '<li>' . $lb . ": " . $vl_data . "</li>";
490 - } else {
491 - if (filter_var($vl_data, FILTER_VALIDATE_URL) === FALSE) {
492 - $content = array();
493 - $parts = array_map('trim', explode(",", $vl_data));
494 - $is_urls = true;
495 - foreach ($parts as $part) {
496 - if (empty($part) || filter_var($part, FILTER_VALIDATE_URL) === FALSE) {
497 - $is_urls = false;
733 + if ($vl_data === "Upgrade to pro version") {
734 + $html .= '<li>' . esc_html($lb) . ": " . esc_html($vl_data) . "</li>";
735 + break;
736 + }
737 +
738 + // Tách chuỗi theo dấu phẩy phòng trường hợp có nhiều file
739 + $parts = array_filter(array_map('trim', explode(",", $vl_data)));
740 + $content = array();
741 +
742 + // TRƯỜNG HỢP 1: Tất cả các phần tử đều là URL hợp lệ
743 + $all_are_urls = !empty($parts);
744 + foreach ($parts as $part) {
745 + if (!$is_valid_url($part)) {
746 + $all_are_urls = false;
747 + break;
748 + }
749 + }
750 +
751 + if ($all_are_urls) {
752 + foreach ($parts as $part) {
753 + $filename = basename($part);
754 + $content[] = $render_file_or_image($part, $filename);
755 + }
756 + $html .= '<li>' . esc_html($lb) . ': ' . implode(" ", $content) . "</li>";
757 + break;
758 + }
759 +
760 + // TRƯỜNG HỢP 2: Chuỗi chứa tên file hoặc URL không hợp lệ -> Tìm trong $result
761 + $main_name = explode("__", $name);
762 + $main_name = explode("_", $main_name[0]);
763 + $main_name_id = isset($main_name[4]) ? $main_name[4] : (isset($main_name[1]) ? $main_name[1] : null);
764 +
765 + if ($main_name_id && isset($result[$main_name_id])) {
766 + $raw_uploads = $result[$main_name_id];
767 + $data_uploads = is_array($raw_uploads) ? $raw_uploads : json_decode($raw_uploads, true);
768 +
769 + if (!is_array($data_uploads)) {
770 + $data_uploads = array_filter(array_map('trim', explode(",", (string) $raw_uploads)));
771 + }
772 +
773 + foreach ($parts as $n) {
774 + $clean_n = sanitize_file_name($n);
775 + $name_s = preg_quote(pathinfo($clean_n, PATHINFO_FILENAME), '/');
776 +
777 + foreach ($data_uploads as $upload_file) {
778 + // Regex khớp chính xác tên file gốc hoặc tên file có đánh số thứ tự
779 + if (preg_match('/' . $name_s . '(\d+)?\./i', $upload_file)) {
780 + $content[] = $render_file_or_image($upload_file, $clean_n);
498 781 break;
499 782 }
500 783 }
501 - if ($is_urls) {
502 - foreach ($parts as $part) {
503 - $filename = basename($part);
504 - $content[] = '<a href="' . esc_url($part) . '" download>' . esc_html($filename) . '</a>';
505 - }
506 - $html .= '<li>' . $lb . ': ' . implode(" | ", $content) . "</li>";
507 - } else {
508 - $main_name = explode("__", $name);
509 - $main_name = explode("_", $main_name[0]);
510 - if (isset($main_name[4])) {
511 - $main_name_id = $main_name[4];
512 - } else {
513 - $main_name_id = $main_name[1];
514 - }
515 - if (isset($result[$main_name_id])) {
516 - $data_uploads = json_decode($result[$main_name_id], true);
517 - if (!is_array($data_uploads)) {
518 - $data_uploads = explode(",", $data_uploads);
519 - }
520 - if (!is_array($data_uploads)) {
521 - $data_uploads = array();
522 - }
523 - foreach ($parts as $n) {
524 - $n = sanitize_file_name($n);
525 - foreach ($data_uploads as $name) {
526 - $name_s = explode(".", $n);
527 - $name_s = $name_s[0];
528 - $re = "/" . $name_s . "\.|" . $name_s . "[\d]\./";
529 - if (preg_match($re, $name)) {
530 - $content[] = '<a href="' . $name . '" download>' . $n . "</a> ";
531 - break;
532 - }
533 - }
534 - }
535 - }
536 - $html .= '<li>' . $lb . ': ' . implode(" | ", $content) . "</li>";
537 - }
538 - } else {
539 - $html .= '<li>' . $lb . ': <a href="' . $vl_data . '" download>' . $vl_data . "</a></li>";
540 784 }
541 785 }
786 +
787 + $html .= '<li>' . esc_html($lb) . ': ' . (!empty($content) ? implode(" ", $content) : esc_html($vl_data)) . "</li>";
542 788 break;
789 +
543 790 default:
544 - $html .= '<li>' . $lb . ": " . $vl_data . "</li>";
791 + if (is_string($vl_data) && $is_valid_url($vl_data) && $is_image_url($vl_data)) {
792 + $html .= '<li>' . esc_html($lb) . ': ' . $render_file_or_image($vl_data) . "</li>";
793 + } else {
794 + $html .= '<li>' . esc_html($lb) . ": " . esc_html($vl_data) . "</li>";
795 + }
545 796 break;
546 797 }
547 798 }
548 799 }
@@ -547,30 +798,35 @@
547 798 }
548 799 }
549 800 $html .= '</ul></li>';
550 801 }
551 - $html .= '<ol>';
802 + $html .= '</ol>';
552 803 $html = apply_filters("yeeadons_gravity_forms_repeater_html", $html, $dataArray, $form);
553 804 return $html;
554 805 } else {
555 - $html = '';
806 + $text = '';
556 807 foreach ($dataArray as $step_datas) {
808 + if (!is_array($step_datas)) {
809 + continue;
810 + }
557 811 foreach ($step_datas as $name => $vl) {
558 812 $type = $this->get_type($form, $name, $form_id);
559 - $lb = $this->get_field_label($form, $name, $type, false, $form_id);
813 + $lb = $this->get_custom_field_label($form, $name, $type, false, $form_id);
814 + $lb = esc_html($lb);
815 +
560 816 if (is_array($vl)) {
561 817 switch ($type) {
562 818 case "address":
563 819 $vl_data = "";
564 820 foreach ($vl as $k => $v) {
565 - $child_lb = $this->get_field_label($form, "input_" . $k, $type, true);
566 - $vl_data .= $child_lb . ": " . $v . "\n";
821 + $child_lb = $this->get_custom_field_label($form, "input_" . $k, $type, true);
822 + $vl_data .= esc_html($child_lb) . ": " . esc_html($v) . "\n";
567 823 }
568 - $html .= $lb . " : " . $vl_data . "\n";
824 + $text .= $lb . " : \n" . $vl_data;
569 825 break;
570 826 default:
571 - $vl_data = implode(", ", $vl);
572 - $html .= $lb . ": " . $vl_data . "\n";
827 + $vl_escaped = array_map('esc_html', $vl);
828 + $text .= $lb . ": " . implode(", ", $vl_escaped) . "\n";
573 829 break;
574 830 }
575 831 } else {
576 832 $vl_data = $vl;
@@ -575,59 +831,66 @@
575 831 } else {
576 832 $vl_data = $vl;
577 833 switch ($type) {
578 834 case "fileupload":
579 - if (filter_var($vl_data, FILTER_VALIDATE_URL) === FALSE) {
580 - $content = array();
581 - $parts = array_map('trim', explode(",", $vl_data));
582 - $is_urls = true;
835 + if ($vl_data === "Upgrade to pro version") {
836 + $text .= $lb . ": " . esc_html($vl_data) . "\n";
837 + break;
838 + }
839 + $parts = array_filter(array_map('trim', explode(",", $vl_data)));
840 + $content = array();
841 +
842 + $all_are_urls = !empty($parts);
843 + foreach ($parts as $part) {
844 + if (filter_var($part, FILTER_VALIDATE_URL) === false) {
845 + $all_are_urls = false;
846 + break;
847 + }
848 + }
849 +
850 + if ($all_are_urls) {
583 851 foreach ($parts as $part) {
584 - if (empty($part) || filter_var($part, FILTER_VALIDATE_URL) === FALSE) {
585 - $is_urls = false;
586 - break;
587 - }
852 + $filename = basename($part);
853 + $content[] = esc_html($filename) . ' (' . esc_url($part) . ')';
588 854 }
589 - if ($is_urls) {
590 - foreach ($parts as $part) {
591 - $filename = basename($part);
592 - $content[] = '<a href="' . esc_url($part) . '" download>' . esc_html($filename) . '</a>';
855 + $text .= $lb . ': ' . implode(", ", $content) . "\n";
856 + } else {
857 + $main_name = explode("__", $name);
858 + $main_name = explode("_", $main_name[0]);
859 + $main_name_id = isset($main_name[4]) ? $main_name[4] : (isset($main_name[1]) ? $main_name[1] : null);
860 +
861 + if ($main_name_id && isset($result[$main_name_id])) {
862 + $raw_uploads = $result[$main_name_id];
863 + $data_uploads = is_array($raw_uploads) ? $raw_uploads : json_decode($raw_uploads, true);
864 + if (!is_array($data_uploads)) {
865 + $data_uploads = array_filter(array_map('trim', explode(",", (string)$raw_uploads)));
593 866 }
594 - $html .= $lb . ': ' . implode(" | ", $content) . "\n";
595 - } else {
596 - $main_name = explode("__", $name);
597 - $main_name = explode("_", $main_name[0]);
598 - $main_name_id = $main_name[4];
599 - if (isset($result[$main_name_id])) {
600 - $data_uploads = json_decode($result[$main_name_id], true);
601 - foreach ($parts as $n) {
602 - $n = sanitize_file_name($n);
603 - foreach ($data_uploads as $name) {
604 - $name_s = explode(".", $n);
605 - $name_s = $name_s[0];
606 - $re = "/" . $name_s . "\.|" . $name_s . "[\d]\./";
607 - if (preg_match($re, $name)) {
608 - $content[] = '<a href="' . $name . '" download>' . $n . "</a> ";
609 - break;
610 - }
867 +
868 + foreach ($parts as $n) {
869 + $clean_n = sanitize_file_name($n);
870 + $name_s = preg_quote(pathinfo($clean_n, PATHINFO_FILENAME), '/');
871 + foreach ($data_uploads as $upload_file) {
872 + if (preg_match('/' . $name_s . '(\d+)?\./i', $upload_file)) {
873 + $content[] = esc_html($clean_n) . ' (' . esc_url($upload_file) . ')';
874 + break;
611 875 }
612 876 }
613 877 }
614 - $html .= $lb . ': ' . implode(" | ", $content) . "\n";
615 878 }
616 - } else {
617 - $html .= $lb . ':' . $vl_data . "\n";
879 + $text .= $lb . ': ' . (!empty($content) ? implode(", ", $content) : esc_html($vl_data)) . "\n";
618 880 }
619 881 break;
882 +
620 883 default:
621 - $html .= $lb . ": " . $vl_data . "\n";
884 + $text .= $lb . ": " . esc_html($vl_data) . "\n";
622 885 break;
623 886 }
624 887 }
625 888 }
626 - $html .= "\n";
889 + $text .= "\n";
627 890 }
628 - $html = apply_filters("yeeadons_gravity_forms_repeater_text", $html, $dataArray, $form);
629 - return $html;
891 + $text = apply_filters("yeeadons_gravity_forms_repeater_text", $text, $dataArray, $form);
892 + return $text;
630 893 }
631 894 }
632 895 public function get_value_export($entry, $input_id = '', $use_text = false, $is_csv = false)
633 896 {
@@ -655,9 +918,9 @@
655 918 $return = $this->get_datas_field($format, $value, $form_id);
656 919 return $return;
657 920 }
658 921 }
659 - function get_field_label($form, $name = '', $type = '', $child = false, $form_id = '')
922 + function get_custom_field_label($form, $name = '', $type = '', $child = false, $form_id = '')
660 923 {
661 924 if (is_array($form)) {
662 925 if (!array_key_exists('fields', $form)) {
663 926 return false;
@@ -667,9 +930,9 @@
667 930 }
668 931 $name = str_replace("gform_multifile_upload_" . $form_id, "input", $name);
669 932 $names = explode("__", $name);
670 933 $names = explode("_", $names[0]);
671 - $name = $names[1];
934 + $name = isset($names[1]) ? $names[1] : $names[0];
672 935 foreach ($form['fields'] as $field_key => $field_value) {
673 936 if (is_array($field_value->inputs)) {
674 937 foreach ($field_value->inputs as $children_id) {
675 938 if ($children_id["id"] == $name) {
@@ -698,9 +961,9 @@
698 961 return false;
699 962 }
700 963 $names = explode("__", $name);
701 964 $names = explode("_", $names[0]);
702 - $name = $names[1];
965 + $name = isset($names[1]) ? $names[1] : $names[0];
703 966 foreach ($form['fields'] as $field_key => $field_value) {
704 967 if ($field_value->id == $name) {
705 968 if ($field_value->type == "date") {
706 969 return $name;
@@ -723,9 +986,9 @@
723 986 }
724 987 $name = str_replace("gform_multifile_upload_" . $form_id, "input", $name);
725 988 $names = explode("__", $name);
726 989 $names = explode("_", $names[0]);
727 - $name = $names[1];
990 + $name = isset($names[1]) ? $names[1] : $names[0];
728 991 foreach ($form['fields'] as $field_key => $field_value) {
729 992 if (is_array($field_value->inputs)) {
730 993 foreach ($field_value->inputs as $children_id) {
731 994 if ($children_id["id"] == $name) {