PluginProbe
WP Directory Kit / 1.5.9
WP Directory Kit v1.5.9
1.5.9 1.5.7 1.5.6 1.5.5 1.5.4 1.5.3 trunk 1.1.0 1.1.6 1.1.8 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.8 All 37 releases
← All changes | application/helpers/Basic.php +1606 -186 1.2.8 → 1.5.9 View file →
@@ -3,9 +3,9 @@
3 3 if ( ! defined( 'ABSPATH' ) ) {
4 4 exit; // Exit if accessed directly.
5 5 }
6 6
7 -function wdk_generate_fields($fields, $db_data)
7 +function wdk_generate_fields($fields, $db_data, $form = NULL)
8 8 {
9 9 if(is_array($fields))
10 10 foreach($fields as $field)
11 11 {
@@ -20,9 +20,9 @@
20 20 include $field_view_path;
21 21 }
22 22 else
23 23 {
24 - echo __('Missing VIEW file:', 'wpdirectorykit').' '.esc_html($field_type).'.php';
24 + echo esc_html__('Missing VIEW file:', 'wpdirectorykit').' '.esc_html($field_type).'.php';
25 25 }
26 26 }
27 27 }
28 28
@@ -150,9 +150,10 @@
150 150 "field_label" =>wmvc_show_data('field_label', $field_data),
151 151 "prefix" => wmvc_show_data('prefix', $field_data),
152 152 "suffix" => wmvc_show_data('suffix', $field_data),
153 153 "values_list" => wmvc_show_data('values_list', $field_data),
154 - "placeholder" => wmvc_show_data('placeholder', $field_data)
154 + "placeholder" => wmvc_show_data('placeholder', $field_data),
155 + "is_select_2_ajax_field_db_suggestion" => wmvc_show_data('is_select_2_ajax_field_db_suggestion', $used_field),
155 156 );
156 157 }
157 158 }
158 159 }
@@ -189,8 +190,9 @@
189 190
190 191 }
191 192
192 193 if($print){
194 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
193 195 echo $output;
194 196 return FALSE;
195 197 }
196 198
@@ -320,8 +322,12 @@
320 322 if(wmvc_show_data('field_placeholder', $el_field_data, false)) {
321 323 $field['placeholder'] = wmvc_show_data('field_placeholder', $el_field_data, false);
322 324 }
323 325
326 + if(wmvc_show_data('search_type_tree_hide', $el_field_data, false)) {
327 + $field['search_type_tree_hide'] = wmvc_show_data('search_type_tree_hide', $el_field_data, false);
328 + }
329 +
324 330 /* if field not detected or remove from fields list, skip field in search */
325 331 if(empty($field)) continue;
326 332
327 333 /* add from user fields data */
@@ -354,8 +360,9 @@
354 360 }
355 361 }
356 362
357 363 if($print){
364 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
358 365 echo $output;
359 366 return FALSE;
360 367 }
361 368
@@ -386,9 +393,10 @@
386 393 $wdk_bookings_joinded = false;
387 394 static $available_fields_listings = NULL;
388 395 static $available_fields_static = array();
389 396 static $list_fields_static = NULL;
390 -
397 + $fields_type = array();
398 +
391 399 /* add if missing columns */
392 400 if(!in_array('post_id', $columns)) {
393 401 $columns[] = $Winter_MVC_WDK->db->prefix.'wdk_listings.post_id';
394 402 }
@@ -404,10 +412,10 @@
404 412
405 413 if(isset($custom_parameters['order_by'])) {
406 414
407 415 if(isset($_GET_clone['order_by']) && !empty($_GET_clone['order_by'])) {
408 - $_GET_clone['order_by'] = $custom_parameters['order_by'].', '.$_GET_clone['order_by'];
409 - } else {
416 + $_GET_clone['order_by'] = ((!empty($custom_parameters['order_by'])) ? $custom_parameters['order_by'].', ':'').sanitize_text_field($_GET_clone['order_by']);
417 + } elseif(!empty( $custom_parameters['order_by'])) {
410 418 $_GET_clone['order_by'] = $custom_parameters['order_by'];
411 419 }
412 420
413 421 unset($custom_parameters['order_by']);
@@ -422,12 +430,12 @@
422 430 $WMVC->model('listingfield_m');
423 431
424 432 $smart_search = '';
425 433 if(isset($_GET_clone['search']))
426 - $smart_search = sanitize_text_field($_GET_clone['search']);
434 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['search']));
427 435
428 436 if(isset($_GET_clone['field_search']))
429 - $smart_search = sanitize_text_field($_GET_clone['field_search']);
437 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['field_search']));
430 438
431 439 if(!isset($available_fields_static[$model_name]))
432 440 {
433 441 $available_fields = $WMVC->$model_name->get_available_fields();
@@ -460,8 +468,10 @@
460 468 foreach($list_fields as $field_data) {
461 469
462 470 $field_id = wmvc_show_data('idfield',$field_data);
463 471 $field_type = wmvc_show_data('field_type',$field_data);
472 +
473 + $fields_type[$field_id] = $field_type;
464 474 $column_name ='field_'.$field_id.'_'.$field_type;
465 475 if(!isset($available_fields_listings[$column_name])) continue;
466 476
467 477 if(isset($_GET_clone['field_'.$field_id])) {
@@ -479,9 +489,9 @@
479 489 if(isset($_GET_clone['field_'.$field_id.'_min'])) {
480 490 $_GET_clone['field_'.$field_id.'_'.$field_type.'_min'] = apply_filters( 'wdk-currency-conversion/convert/default_value',sanitize_text_field($_GET_clone['field_'.$field_id.'_min']), $field_id);
481 491 }
482 492 if(isset($_GET_clone['field_'.$field_id.'_exactly'])) {
483 - $_GET_clone['field_'.$field_id.'_'.$field_type.'_exactly'] = sanitize_text_field($_GET_clone['field_'.$field_id.'_exactly']);
493 + $_GET_clone['field_'.$field_id.'_'.$field_type.'_exactly'] = wdk_clean_mixed($_GET_clone['field_'.$field_id.'_exactly']);
484 494 }
485 495
486 496 $columns[] = $column_name;
487 497 $columns[] = $column_name.'_max';
@@ -536,13 +546,34 @@
536 546 }
537 547
538 548 if(isset($_GET_clone['field_post_id'])) {
539 549 $column_name ='ID_exactly';
540 - $_GET_clone[$column_name] = intval($_GET_clone['field_post_id']);
550 + $_GET_clone[$column_name] = sanitize_text_field($_GET_clone['field_post_id']);
541 551 $columns[] = $column_name;
542 552 $external_columns[] = $column_name;
543 553 }
544 554
555 + if(isset($_GET_clone['field_post_date'])) {
556 + $column_name ='post_DATE';
557 + $_GET_clone[$column_name] = ($_GET_clone['field_post_date']);
558 + $columns[] = $column_name;
559 + $external_columns[] = $column_name;
560 + }
561 +
562 + if(isset($_GET_clone['field_post_date_min'])) {
563 + $column_name ='post_DATE_min';
564 + $_GET_clone[$column_name] = ($_GET_clone['field_post_date_min']);
565 + $columns[] = $column_name;
566 + $external_columns[] = $column_name;
567 + }
568 +
569 + if(isset($_GET_clone['field_post_date_max'])) {
570 + $column_name ='post_DATE_max';
571 + $_GET_clone[$column_name] = ($_GET_clone['field_post_date_max']);
572 + $columns[] = $column_name;
573 + $external_columns[] = $column_name;
574 + }
575 +
545 576 if (function_exists('run_wdk_bookings') && isset($_GET_clone['field_booking_date_from'])) {
546 577 $column_name ='field_booking_date_from';
547 578 $_GET_clone[$column_name] = $_GET_clone['field_booking_date_from'];
548 579 $columns[] = $column_name;
@@ -562,8 +593,29 @@
562 593 $columns[] = $column_name;
563 594 $external_columns[] = $column_name;
564 595 }
565 596
597 + if (isset($_GET_clone['search_rank'])) {
598 + $column_name ='`rank`';
599 + $_GET_clone[$column_name] = $_GET_clone['search_rank'];
600 + $columns[] = $column_name;
601 + $external_columns[] = $column_name;
602 + }
603 +
604 + if (isset($_GET_clone['search_rank_min'])) {
605 + $column_name ='`rank`_min';
606 + $_GET_clone[$column_name] = $_GET_clone['search_rank_min'];
607 + $columns[] = $column_name;
608 + $external_columns[] = $column_name;
609 + }
610 +
611 + if (isset($_GET_clone['search_rank_max'])) {
612 + $column_name ='`rank`_max';
613 + $_GET_clone[$column_name] = $_GET_clone['search_rank_max'];
614 + $columns[] = $column_name;
615 + $external_columns[] = $column_name;
616 + }
617 +
566 618 //$table_name = substr($model_name, 0, -2);
567 619 $columns_original = array();
568 620 foreach($columns as $key=>$val)
569 621 {
@@ -591,8 +643,10 @@
591 643 {
592 644 unset($_GET_clone['search']);
593 645 unset($_GET_clone['field_search']);
594 646
647 + $WMVC->db->join($WMVC->listing_m->_table_name.' ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'posts'.'.ID', NULL, 'LEFT');
648 +
595 649 // For quick/smart search
596 650 if(wmvc_count($columns) > 0 && !empty($smart_search))
597 651 {
598 652 $gen_q = '';
@@ -650,8 +704,13 @@
650 704 /* location / categories */
651 705 if(!is_intval($smart_search)) {
652 706 $gen_q.="location_title LIKE '%$smart_search%' OR ";
653 707 $gen_q.="category_title LIKE '%$smart_search%' OR ";
708 +
709 +
710 + $gen_q.="`category_table`.`titles_for_search` LIKE '%$smart_search%' OR ";
711 + $gen_q.="`location_table`.`titles_for_search` LIKE '%$smart_search%' OR ";
712 +
654 713 }
655 714 /* get address and gps */
656 715 if(strlen($smart_search) > 5) {
657 716 $coordinates_center = wdk_get_gps($smart_search);
@@ -707,9 +766,9 @@
707 766
708 767 if(!empty($gen_q))
709 768 $WMVC->db->where("($gen_q)");
710 769 }
711 -
770 +
712 771 // For column search
713 772 if(isset($_GET_clone))
714 773 {
715 774 $gen_q = '';
@@ -717,9 +776,9 @@
717 776 {
718 777 if(!empty($val) && in_array($key, $columns))
719 778 {
720 779 $col_name = $key;
721 -
780 +
722 781 $val = esc_sql($val);
723 782 //if(isset($key))
724 783 // $col_name = $key;
725 784
@@ -724,43 +783,31 @@
724 783 // $col_name = $key;
725 784
726 785 if(strpos($key, 'skip') !== FALSE) continue;
727 786
728 - if(defined( 'WP_DEBUG' ) && WP_DEBUG)
729 - if(function_exists('pll_current_language'))
730 - {
731 - $lang_term_id = pll_current_language('term_id');
732 -
733 - if(is_numeric($lang_term_id))
734 - {
735 - $WMVC->db->join($WMVC->db->prefix.'term_relationships ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'term_relationships.object_id', NULL, NULL);
736 - $WMVC->db->where("({$WMVC->db->prefix}term_relationships.term_taxonomy_id = $lang_term_id)");
737 - }
738 - }
739 -
740 787 if($key == 'field_booking_guest')
741 788 {
742 789 if(!$wdk_bookings_joinded){
743 - $WMVC->db->join($WMVC->db->prefix.'wdk_booking_price ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_booking_price.post_id', NULL, 'LEFT');
744 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
745 - $WMVC->db->join($WMVC->db->prefix.'wdk_booking_reservation ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_booking_price.post_id', NULL, 'LEFT');
790 + $WMVC->db->join($WMVC->db->prefix.'wdk_booking_price ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_booking_price.post_id', NULL, 'LEFT');
791 + $WMVC->db->distinct($WMVC->db->prefix.'posts.ID');
792 + $WMVC->db->join($WMVC->db->prefix.'wdk_booking_reservation ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_booking_reservation.post_id', NULL, 'LEFT');
746 793 $wdk_bookings_joinded = true;
747 794 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
748 - $WMVC->db->join($WMVC->db->prefix.'wdk_booking_calendar ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_booking_calendar.post_id', NULL, 'LEFT');
795 + $WMVC->db->join($WMVC->db->prefix.'wdk_booking_calendar ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_booking_calendar.post_id', NULL, 'LEFT');
749 796 }
750 797
751 - $gen_q.= $WMVC->db->prefix."wdk_booking_calendar.guests <='".intval($val)."' AND ";
798 + $gen_q.= $WMVC->db->prefix."wdk_booking_calendar.guests >='".intval($val)."' AND ";
752 799
753 800 }
754 801 elseif($key == 'field_booking_date_from')
755 802 {
756 803 if(!$wdk_bookings_joinded){
757 - $WMVC->db->join($WMVC->db->prefix.'wdk_booking_price ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_booking_price.post_id', NULL, 'LEFT');
758 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
759 - $WMVC->db->join($WMVC->db->prefix.'wdk_booking_reservation ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_booking_price.post_id', NULL, 'LEFT');
804 + $WMVC->db->join($WMVC->db->prefix.'wdk_booking_price ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_booking_price.post_id', NULL, 'LEFT');
805 + $WMVC->db->distinct($WMVC->db->prefix.'posts.ID');
806 + $WMVC->db->join($WMVC->db->prefix.'wdk_booking_reservation ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_booking_reservation.post_id', NULL, 'LEFT');
760 807 $wdk_bookings_joinded = true;
761 808 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
762 - $WMVC->db->join($WMVC->db->prefix.'wdk_booking_calendar ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_booking_calendar.post_id', NULL, 'LEFT');
809 + $WMVC->db->join($WMVC->db->prefix.'wdk_booking_calendar ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_booking_calendar.post_id', NULL, 'LEFT');
763 810 }
764 811
765 812 if(wdk_is_date($val))
766 813 {
@@ -778,9 +825,9 @@
778 825 if(!get_option('wdk_bookings_is_hours_enabled')) {
779 826 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from'], 'Y-m-d H:i:s', 'Y-m-d');
780 827 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to'], 'Y-m-d H:i:s', 'Y-m-d');
781 828
782 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
829 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
783 830 SELECT post_id
784 831 FROM ".$WMVC->db->prefix."wdk_booking_reservation
785 832 WHERE
786 833 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -793,9 +840,9 @@
793 840 } else {
794 841 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from']);
795 842 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to']);
796 843
797 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
844 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
798 845 SELECT post_id
799 846 FROM ".$WMVC->db->prefix."wdk_booking_reservation
800 847 WHERE
801 848 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -810,13 +857,13 @@
810 857 }
811 858 elseif($key == 'field_booking_date_to')
812 859 {
813 860 if(!$wdk_bookings_joinded){
814 - $WMVC->db->join($WMVC->db->prefix.'wdk_booking_price ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_booking_price.post_id',NULL, 'LEFT');
815 - $WMVC->db->join($WMVC->db->prefix.'wdk_booking_reservation ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_booking_price.post_id',NULL, 'LEFT');
861 + $WMVC->db->join($WMVC->db->prefix.'wdk_booking_price ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_booking_price.post_id',NULL, 'LEFT');
862 + $WMVC->db->join($WMVC->db->prefix.'wdk_booking_reservation ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_booking_reservation.post_id',NULL, 'LEFT');
816 863 $wdk_bookings_joinded = true;
817 864 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
818 - $WMVC->db->join($WMVC->db->prefix.'wdk_booking_calendar ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_booking_calendar.post_id', NULL, 'LEFT');
865 + $WMVC->db->join($WMVC->db->prefix.'wdk_booking_calendar ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_booking_calendar.post_id', NULL, 'LEFT');
819 866 }
820 867
821 868 if(wdk_is_date($val))
822 869 {
@@ -832,9 +879,33 @@
832 879 }
833 880 elseif(substr($key, -8) == '_exactly')
834 881 {
835 882 $col_name = substr($key, 0, -8);
836 - $gen_q.=$col_name." = '".$val."' AND ";
883 +
884 + if(is_string($val) && strpos($val, ',') !== FALSE){
885 + $val =explode(',', $val);
886 + } elseif(is_string($val)){
887 + $val =array($val);
888 + }
889 +
890 + if(is_array($val))
891 + {
892 + $sql_search = '';
893 + foreach ($val as $v) {
894 + if(empty($v)) continue;
895 +
896 + if(!empty($sql_search))
897 + $sql_search .= " OR ";
898 +
899 + $sql_search .= " ".$col_name." = '".$v."' ";
900 + }
901 +
902 + if(!empty($sql_search))
903 + $gen_q.=" ( ".$sql_search." ) AND ";
904 + } else {
905 +
906 + $gen_q.=$col_name." = '".$val."' AND ";
907 + }
837 908 }
838 909 elseif(substr($key, -4) == '_max')
839 910 {
840 911 $col_name = substr($key, 0, -4);
@@ -853,9 +924,9 @@
853 924 }
854 925 else if(substr($key, -4) == '_min')
855 926 {
856 927 $col_name = substr($key, 0, -4);
857 -
928 +
858 929 if(strpos($key, 'NUMBER') !== FALSE) {
859 930 $gen_q.=$col_name." >= ".intval($val)." AND ";
860 931 } else if(strpos($key, 'DATE') !== FALSE) {
861 932 if(wdk_is_date($val))
@@ -924,9 +995,9 @@
924 995 }
925 996
926 997 if(is_array($val)) {
927 998
928 - $WMVC->db->join($WMVC->db->prefix.'wdk_listings_users ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_listings_users.post_id', NULL, 'LEFT');
999 + $WMVC->db->join($WMVC->db->prefix.'wdk_listings_users ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'wdk_listings_users.post_id', NULL, 'LEFT');
929 1000 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
930 1001 $sql_search = '';
931 1002 foreach ($val as $v) {
932 1003 if(empty($v)) continue;
@@ -941,9 +1012,9 @@
941 1012 if(!empty($sql_search))
942 1013 $gen_q.=" ( ".$sql_search." ) AND ";
943 1014
944 1015 } elseif(is_string($val) && !empty($val)) {
945 - $WMVC->db->join($WMVC->db->prefix.'wdk_listings_users ON '.$WMVC->listing_m->_table_name.'.post_id = '.$WMVC->db->prefix.'wdk_listings_users.post_id', NULL, 'LEFT');
1016 + $WMVC->db->join($WMVC->db->prefix.'wdk_listings_users ON '.$WMVC->db->prefix.'posts.post_id = '.$WMVC->db->prefix.'wdk_listings_users.post_id', NULL, 'LEFT');
946 1017 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
947 1018 $sql_search =" ".$WMVC->listing_m->_table_name.".`user_id_editor` = ".intval($val)." OR `".$WMVC->db->prefix."wdk_listings_users`.`user_id` = ".intval($val)." ";
948 1019 $gen_q.=" ( ".$sql_search." ) AND ";
949 1020 }
@@ -1100,10 +1171,15 @@
1100 1171
1101 1172 if(!empty($sql_search))
1102 1173 $gen_q.=" ( ".$sql_search." ) AND ";
1103 1174 }
1175 + } elseif ($val == 0) {
1176 + $col_name = $key;
1177 + $val = esc_sql($val);
1178 + if(in_array($col_name, ['`rank`'])) {
1179 + $gen_q.=" ( ".$col_name." = 0 OR ".$col_name." IS NULL ) AND ";
1180 + }
1104 1181 }
1105 -
1106 1182 }
1107 1183
1108 1184 $gen_q = substr($gen_q, 0, -5);
1109 1185
@@ -1109,14 +1185,120 @@
1109 1185
1110 1186 if(!empty($gen_q))
1111 1187 $WMVC->db->where("($gen_q)");
1112 1188 }
1189 +
1190 + //if(defined( 'WP_DEBUG' ) && WP_DEBUG)
1191 + if(function_exists('pll_current_language'))
1192 + {
1193 + $lang_term_id = pll_current_language('term_id');
1194 +
1195 + if(is_numeric($lang_term_id))
1196 + {
1197 + $WMVC->db->join($WMVC->db->prefix.'term_relationships ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'term_relationships.object_id', NULL, NULL);
1198 + $WMVC->db->where("({$WMVC->db->prefix}term_relationships.term_taxonomy_id = $lang_term_id)");
1199 + }
1200 + }
1201 +
1202 + // [RECTANGLE SEARCH]
1203 + if(isset($_GET_clone['rectangle_ne']) && isset($_GET_clone['rectangle_sw']))
1204 + {
1205 + if(wdk_is_gps($_GET_clone['rectangle_ne']) && wdk_is_gps($_GET_clone['rectangle_sw'])) {
1206 +
1207 + $gps_ne = explode(',', $_GET_clone['rectangle_ne']);
1208 + $gps_sw = explode(',', $_GET_clone['rectangle_sw']);
1209 +
1210 + $WMVC->db->where("(".$WMVC->db->prefix."wdk_listings.lat < '$gps_ne[0]' AND ".$WMVC->db->prefix."wdk_listings.lat > '$gps_sw[0]' AND
1211 + ".$WMVC->db->prefix."wdk_listings.lng > '$gps_ne[1]' AND ".$WMVC->db->prefix."wdk_listings.lng < '$gps_sw[1]')");
1212 + }
1213 + }
1214 + // [/RECTANGLE SEARCH]
1113 1215
1114 1216 // order
1115 - if(isset($_GET_clone['order_by']))
1116 - {
1117 - $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_listings.post_id', $_GET_clone['order_by']);
1118 - $WMVC->db->order_by($_GET_clone['order_by']);
1217 + if (isset($_GET_clone['order_by'])) {
1218 + // Merge available fields + system columns
1219 + $order_columns = [
1220 + 'post_id' => $WMVC->db->prefix . 'wdk_listings.post_id',
1221 + 'counter_views' => $WMVC->db->prefix . 'wdk_listings.counter_views',
1222 + 'date_modified' => $WMVC->db->prefix . 'wdk_listings.date_modified',
1223 + 'post_title' => $WMVC->db->prefix . 'posts.post_title',
1224 + 'address' => $WMVC->db->prefix . 'wdk_listings.address',
1225 + 'category_id' => $WMVC->db->prefix . 'wdk_listings.category_id',
1226 + 'location_id' => $WMVC->db->prefix . 'wdk_listings.location_id',
1227 + 'rank' => $WMVC->db->prefix . 'wdk_listings.rank'
1228 + ];
1229 +
1230 + $order_columns = apply_filters('wdk/listings/order_columns', $order_columns);
1231 +
1232 + $_GET_clone['order_by'] = str_replace(
1233 + 'post_id',
1234 + $WMVC->db->prefix . 'wdk_listings.post_id',
1235 + sanitize_text_field($_GET_clone['order_by'])
1236 + );
1237 +
1238 + // Fix common typos: ask → asc, desk → desc
1239 + $_GET_clone['order_by'] = str_ireplace([' ask', ' desk'], [' asc', ' desc'], $_GET_clone['order_by']);
1240 +
1241 + /* we no need field type in get link now */
1242 + $_GET_clone['order_by'] = str_ireplace(['_NUMBER', '_SECTION', '_TEXTAREA', '_DATE', '_DROPDOWN', '_DROPDOWNMULTIPLE', '_CHECKBOX'], '', $_GET_clone['order_by']);
1243 +
1244 + // Parse order_by string into parts
1245 + $order_by_array = explode(',', $_GET_clone['order_by']);
1246 + $final_order_by = [];
1247 +
1248 + foreach ($order_by_array as $order_part) {
1249 + $order_part = trim($order_part);
1250 +
1251 + // detect direction asc/desc
1252 + $direction = 'DESC';
1253 + if (stripos($order_part, ' asc') !== false) {
1254 + $direction = 'ASC';
1255 + } elseif (stripos($order_part, ' desc') !== false) {
1256 + $direction = 'DESC';
1257 + }
1258 +
1259 + $order_part = str_ireplace(['desc', 'asc'], '', $order_part);
1260 + $order_part = esc_sql(sanitize_textarea_field(str_replace(' ', '', $order_part)));
1261 +
1262 + // Try to detect field_(id)
1263 + if (preg_match('/field_(\d+)\b/', $order_part, $matches)) {
1264 +
1265 + $search_field_id = $matches[1];
1266 + if (!empty($fields_type[$search_field_id])) {
1267 + $field_name = "field_{$search_field_id}_{$fields_type[$search_field_id]}";
1268 +
1269 + // Check if field exists in order_columns
1270 + if (isset($available_fields_listings[$field_name])) {
1271 + $final_order_by[] = $field_name . ' ' . $direction;
1272 + }
1273 + }
1274 +
1275 + // else → skip invalid field automatically
1276 +
1277 + } else {
1278 + // Extract only the part after the last '.' if exists, else use entire string
1279 + $col_field = $order_part;
1280 + if (strpos($col_field, '.') !== false) {
1281 + $parts = explode('.', $col_field);
1282 + $col_field = end($parts);
1283 + }
1284 +
1285 + // Check if field exists in order_columns
1286 + if (isset($order_columns[$col_field])) {
1287 + $safe_column = $order_columns[$col_field];
1288 + $final_order_by[] = "$safe_column $direction";
1289 + }
1290 + }
1291 + }
1292 +
1293 + // Apply final order if any valid fields left
1294 + if (!empty($final_order_by)) {
1295 + $_GET_clone['order_by'] = implode(', ', $final_order_by);
1296 + $WMVC->db->order_by($_GET_clone['order_by']);
1297 + } else {
1298 + $WMVC->db->order_by('');
1299 + }
1300 +
1119 1301 }
1120 1302
1121 1303 }
1122 1304 }
@@ -1133,9 +1315,9 @@
1133 1315
1134 1316 if(isset($custom_parameters['order_by'])) {
1135 1317
1136 1318 if(isset($_GET_clone['order_by']) && !empty($_GET_clone['order_by'])) {
1137 - $_GET_clone['order_by'] = $custom_parameters['order_by'].', '.$_GET_clone['order_by'];
1319 + $_GET_clone['order_by'] = $custom_parameters['order_by'].', '.sanitize_text_field($_GET_clone['order_by']);
1138 1320 } else {
1139 1321 $_GET_clone['order_by'] = $custom_parameters['order_by'];
1140 1322 }
1141 1323
@@ -1149,9 +1331,9 @@
1149 1331 $WMVC->model($model_name);
1150 1332
1151 1333 $smart_search = '';
1152 1334 if(isset($_GET_clone['profile_search']))
1153 - $smart_search = sanitize_text_field($_GET_clone['profile_search']);
1335 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['profile_search']));
1154 1336
1155 1337 $available_fields = array('user_login','user_nicename','user_email','user_url','display_name');
1156 1338
1157 1339 if(isset($_GET_clone['is_activated'])){
@@ -1318,9 +1500,9 @@
1318 1500 // order
1319 1501 if(isset($_GET_clone['order_by']))
1320 1502 {
1321 1503 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_favorite.post_id', $_GET_clone['order_by']);
1322 - $WMVC->db->order_by($_GET_clone['order_by']);
1504 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by'])));
1323 1505 }
1324 1506
1325 1507 }
1326 1508 }
@@ -1336,9 +1518,9 @@
1336 1518 //$WMVC->model('listing_m');
1337 1519
1338 1520 $smart_search = '';
1339 1521 if(isset($_GET_clone['search']))
1340 - $smart_search = sanitize_text_field($_GET_clone['search']);
1522 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['search']));
1341 1523
1342 1524 $available_fields = $WMVC->$model_name->get_available_fields();
1343 1525
1344 1526 /* Пet column names from wdk_package and add to allow search +
@@ -1449,9 +1631,9 @@
1449 1631 $detect_date = strtotime($gen_search);
1450 1632
1451 1633 if(wdk_payments_is_date($val) && $detect_date > 1000)
1452 1634 {
1453 - $gen_search = date('Y-m-d H:i:s', $detect_date);
1635 + $gen_search = gmdate('Y-m-d H:i:s', $detect_date);
1454 1636 $gen_q.=$col_name." > '".$gen_search."' AND ";
1455 1637 }
1456 1638 else
1457 1639 {
@@ -1489,9 +1671,9 @@
1489 1671 // order
1490 1672 if(isset($_GET_clone['order_by']))
1491 1673 {
1492 1674 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_messages.post_id', $_GET_clone['order_by']);
1493 - $WMVC->db->order_by($_GET_clone['order_by']);
1675 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by']), true));
1494 1676 }
1495 1677
1496 1678 }
1497 1679 }
@@ -1498,9 +1680,9 @@
1498 1680
1499 1681 function wdk_date() {
1500 1682 $date_format = get_option('date_format');
1501 1683 $time_format = get_option('time_format');
1502 - $date = date("{$date_format} {$time_format}", current_time('timestamp'));
1684 + $date = gmdate("{$date_format} {$time_format}", current_time('timestamp'));
1503 1685 return $date;
1504 1686 }
1505 1687
1506 1688 if(!function_exists('wdk_placeholder_image_src')) {
@@ -1524,18 +1706,20 @@
1524 1706
1525 1707 if(isset($_GET[$page_var]))
1526 1708 $current_page = intval(wmvc_xss_clean($_GET[$page_var]));
1527 1709
1528 - if(!isset($texts['previous_page']))$texts['previous_page'] = 'Previous page';
1529 - if(!isset($texts['next_page']))$texts['next_page'] = 'Next page';
1710 + if(!isset($texts['previous_page']))$texts['previous_page'] = esc_html__('Previous page', 'wpdirectorykit');
1711 + if(!isset($texts['next_page']))$texts['next_page'] = esc_html__('Next page', 'wpdirectorykit');
1530 1712 if(!isset($texts['first_page']))$texts['first_page'] = '';
1531 1713 if(!isset($texts['last_page']))$texts['last_page'] = '';
1532 - if(!isset($texts['items']))$texts['items'] = 'items';
1714 + if(!isset($texts['items']))$texts['items'] = esc_html__('items', 'wpdirectorykit');
1533 1715
1534 1716 if(empty($current_page))$current_page = 1;
1535 1717
1536 1718 // get url
1537 - $url = strtok($_SERVER["REQUEST_URI"], '?');
1719 + $url = strtok(wdk_server_current_url(), '?');
1720 +
1721 +
1538 1722 $qs_parameters = wmvc_xss_clean( $_GET );
1539 1723 unset($qs_parameters[$page_var]);
1540 1724 $qs_part = http_build_query($qs_parameters);
1541 1725 $url = wdk_url_suffix($url, $qs_part);
@@ -1558,16 +1742,16 @@
1558 1742
1559 1743 $output .= '<div class="nav-links">';
1560 1744
1561 1745 if($enable_latest_first && $current_page-1 > 0)
1562 - $output.= '<a class="next page-numbers" href="'.esc_url($url).'#results"><span class="screen-reader-text">'.esc_html($texts['first_page']).'</span><span aria-hidden="true">«</span></a>';
1746 + $output.= '<a class="next page-numbers scroll-ignore" href="'.esc_url($url).'#results"><span class="screen-reader-text">'.esc_html($texts['first_page']).'</span><span aria-hidden="true">«</span></a>';
1563 1747
1564 1748 if ($current_page-1 > 0) {
1565 1749
1566 - $output.= '<a class="next page-numbers" href="'.esc_url(wdk_url_suffix($url,esc_attr($page_var).'='.esc_attr($current_page-1))).'#results"><span class="screen-reader-text">'.esc_html($texts['previous_page']).'</span><span aria-hidden="true">‹</span></a>';
1750 + $output.= '<a class="next page-numbers scroll-ignore" href="'.esc_url(wdk_url_suffix($url,esc_attr($page_var).'='.esc_attr($current_page-1))).'#results"><span class="screen-reader-text">'.esc_html($texts['previous_page']).'</span><span aria-hidden="true">‹</span></a>';
1567 1751 } elseif($enable_compact)
1568 1752 {
1569 - $output.= '<span class="next page-numbers disabled" href=""><span class="screen-reader-text">'.esc_html($texts['previous_page']).'</span><span aria-hidden="true">‹</span></span>';
1753 + $output.= '<span class="next page-numbers disabled " href=""><span class="screen-reader-text">'.esc_html($texts['previous_page']).'</span><span aria-hidden="true">‹</span></span>';
1570 1754 }
1571 1755
1572 1756 if (!$enable_compact) {
1573 1757 for ($i = 1 ; $i <= $total_pages; $i++) {
@@ -1575,9 +1759,9 @@
1575 1759 if(($current_page-$limit_items) <= $i && ($current_page+$limit_items) >= $i) {
1576 1760 if (($current_page == $i)) {
1577 1761 $output.= '<span aria-current="page" class="page-numbers current">'.$i.'</span>';
1578 1762 } else {
1579 - $output.= '<a class="page-numbers" href="'.esc_url(wdk_url_suffix($url, esc_attr($page_var).'='.esc_attr($i))).'#results">'.esc_attr($i).'</a>';
1763 + $output.= '<a class="page-numbers scroll-ignore" href="'.esc_url(wdk_url_suffix($url, esc_attr($page_var).'='.esc_attr($i))).'#results">'.esc_attr($i).'</a>';
1580 1764 }
1581 1765 }
1582 1766 }
1583 1767 } else {
@@ -1585,17 +1769,17 @@
1585 1769 }
1586 1770
1587 1771 if($current_page+1 <= $total_pages)
1588 1772 {
1589 - $output.= '<a class="next page-numbers" href="'.esc_url(wdk_url_suffix($url, esc_attr($page_var).'='.esc_attr($current_page+1))).'#results"><span class="screen-reader-text">'.esc_html($texts['next_page']).'</span><span aria-hidden="true">›</span></a>';
1773 + $output.= '<a class="next page-numbers scroll-ignore" href="'.esc_url(wdk_url_suffix($url, esc_attr($page_var).'='.esc_attr($current_page+1))).'#results"><span class="screen-reader-text">'.esc_html($texts['next_page']).'</span><span aria-hidden="true">›</span></a>';
1590 1774 }
1591 1775 elseif($enable_compact)
1592 1776 {
1593 - $output.= '<a class="next page-numbers disabled" href=""><span class="screen-reader-text">'.esc_html($texts['next_page']).'</span><span aria-hidden="true">›</span></a>';
1777 + $output.= '<a class="next page-numbers disabled scroll-ignore" href=""><span class="screen-reader-text">'.esc_html($texts['next_page']).'</span><span aria-hidden="true">›</span></a>';
1594 1778 }
1595 1779
1596 1780 if($enable_latest_first && $current_page+1 <= $total_pages)
1597 - $output.= '<a class="next page-numbers" href="'.esc_url(wdk_url_suffix($url, esc_attr($page_var).'='.esc_attr($total_pages))).'#results"><span class="screen-reader-text">'.esc_html($texts['last_page']).'</span><span aria-hidden="true">»</span></a>';
1781 + $output.= '<a class="next page-numbers scroll-ignore" href="'.esc_url(wdk_url_suffix($url, esc_attr($page_var).'='.esc_attr($total_pages))).'#results"><span class="screen-reader-text">'.esc_html($texts['last_page']).'</span><span aria-hidden="true">»</span></a>';
1598 1782
1599 1783
1600 1784 $output.= '</div>';
1601 1785 $output.= '</nav>';
@@ -1650,22 +1834,27 @@
1650 1834 }
1651 1835
1652 1836 ?>
1653 1837 <div class="wdk-col wdk-col-btns">
1654 - <div class="wdk-field wdk-field-btn">
1838 + <div class="wdk-field wdk-field-btn">
1655 1839 <div class="wdk-field-group wdk-field-group-additional">
1656 1840 <button id="wdk-search-additional" type="button" class="wdk-search-additional-btn"><?php echo esc_html($wdk_text_more_button); ?><i class="wdk-toggle-icon"></i></button>
1657 - <input type='checkbox' style="display: none !important" value='1' name='wdk_search_additional_opened' />
1841 + <input type='checkbox' style="display: none !important" value='1' <?php if(isset($_GET['wdk_search_additional_opened']) && wmvc_xss_clean($_GET['wdk_search_additional_opened']) == 1):?> checked <?php endif;?> name='wdk_search_additional_opened' />
1658 1842 </div>
1659 1843 <div class="wdk-field-group wdk-field-group-reset">
1660 - <button id="wdk-reset-primary" type="reset" class="wdk-search-start wdk-search-reset wdk-click-load-animation"><?php echo esc_html($wdk_text_reset_button);?></button>
1844 + <button title="<?php echo esc_attr__('Reset','wpdirectorykit');?>" id="wdk-reset-primary" type="reset" class="wdk-search-start wdk-search-reset wdk-click-load-animation"><?php echo esc_html($wdk_text_reset_button);?></button>
1661 1845 </div>
1846 + <?php if (function_exists('fpai_register_settings')):?>
1847 + <div class="wdk-field-group wdk-field-group-ai-search">
1848 + <button title="<?php echo esc_attr__('Ai Search','wpdirectorykit');?>" type="button" class="wdk-ai-search"><?php echo esc_html__('Ai Search','wpdirectorykit');?></button>
1849 + </div>
1850 + <?php endif;?>
1662 1851 <div class="wdk-field-group wdk-field-group-search">
1663 - <button id="wdk-start-primary" type="submit" class="wdk-search-start wdk-click-load-animation">&nbsp;&nbsp;<?php echo esc_html($wdk_text_search_button);?>&nbsp;<i class="fa fa-spinner fa-spin fa-ajax-indicator" style="display: none;"></i>&nbsp;</button>
1852 + <button title="<?php echo esc_attr__('Search','wpdirectorykit');?>" id="wdk-start-primary" type="submit" class="wdk-search-start wdk-click-load-animation">&nbsp;&nbsp;<?php echo esc_html($wdk_text_search_button);?>&nbsp;<i class="fa fa-spinner fa-spin fa-ajax-indicator" style="display: none;"></i>&nbsp;</button>
1664 1853
1665 1854 <?php if(function_exists('run_wdk_save_search') && get_option('wdk_save_search_show_on_searchform')):?>
1666 1855 <div class="section-widget-control right">
1667 - <a class="wdk-c-btn wdk-c-edit wdk-save-search-button" href="#" data-url="<?php echo esc_url(admin_url('admin-ajax.php')); ?>" title="<?php echo esc_attr_e('Save Search', 'selio'); ?>" target="_blank">
1856 + <a class="wdk-c-btn wdk-c-edit wdk-save-search-button" href="#" data-url="<?php echo esc_url(admin_url('admin-ajax.php')); ?>" title="<?php echo esc_attr__('Save Search', 'wpdirectorykit'); ?>" target="_blank">
1668 1857 <i class="fas fa-save" aria-hidden="true"></i>
1669 1858 <i class="fa fa-spinner fa-spin fa-ajax-indicator"></i>
1670 1859 </a>
1671 1860 </div>
@@ -1670,8 +1859,9 @@
1670 1859 </a>
1671 1860 </div>
1672 1861 <?php endif;?>
1673 1862 </div>
1863 +
1674 1864 </div>
1675 1865 </div>
1676 1866 <div id='wdk-form-additional' class="wdk-col" style="<?php echo esc_attr($form_closed) ;?>">
1677 1867 <div class="wdk-row">
@@ -1687,9 +1877,9 @@
1687 1877 */
1688 1878 if ( ! function_exists('wdk_treefield_option'))
1689 1879 {
1690 1880 function wdk_treefield_option($name = '', $table=NULL, $selected = NULL,
1691 - $column = 'category_title', $language_id=NULL, $empty_value='', $filter_ids = '', $user_check = FALSE, $sql_where='')
1881 + $column = 'category_title', $language_id=NULL, $empty_value='', $filter_ids = '', $user_check = FALSE, $sql_where='', $hide_fields = '')
1692 1882 {
1693 1883 $WMVC = &wdk_get_instance();
1694 1884
1695 1885 if(is_array($filter_ids)) $filter_ids = implode(',', $filter_ids);
@@ -1714,9 +1904,9 @@
1714 1904
1715 1905 if(empty($selected))
1716 1906 $selected='';
1717 1907
1718 - $form = '<input name="'.$name.'" value="'.$selected.'" class="wdk-hidden" type="text" id="wdktreeelem'.$counter.'" readonly/>';
1908 + $form = '<input name="'.esc_attr($name).'" value="'.esc_attr($selected).'" class="wdk-hidden" type="text" id="wdktreeelem'.esc_attr($counter).'" readonly/>';
1719 1909
1720 1910 $skip_id = '';
1721 1911 //load javascript library
1722 1912 if($counter==0)
@@ -1723,38 +1913,39 @@
1723 1913 {
1724 1914 wp_enqueue_script('wdk-treefield');
1725 1915 wp_enqueue_style('wdk-treefield');
1726 1916 }
1727 - ?>
1728 - <script>
1729 - jQuery(document).ready(function($) {
1730 - $('#wdktreeelem<?php echo esc_js($counter);?>:not(.init)').wdkTreefield({
1731 - ajax_url: '<?php echo admin_url('admin-ajax.php'); ?>',
1917 + wp_add_inline_script(
1918 + 'wdk-treefield',
1919 + "jQuery(document).ready(function($) {
1920 + $('#wdktreeelem" . esc_js($counter) . ":not(.init)').wdkTreefield({
1921 + ajax_url: '" . esc_js(admin_url('admin-ajax.php')) . "',
1732 1922 ajax_param: {
1733 - "page": 'wdk_frontendajax',
1734 - "function": 'treefieldid',
1735 - "action": 'wdk_public_action',
1736 - "table": '<?php echo esc_js($table); ?>',
1737 - "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1738 - "start_id": '<?php if(!empty($filter_ids)) esc_js($selected); else echo ""; ?>',
1739 - "empty_value": '<?php echo esc_js($empty_value); ?>',
1740 - "user_check": '<?php echo esc_js($user_check); ?>',
1741 - "sql_where": '<?php echo esc_js($sql_where); ?>'
1742 - },
1743 - attribute_id: '<?php echo esc_js($attribute_id); ?>',
1744 - language_id: '<?php echo esc_js($language_id); ?>',
1745 - attribute_value: '<?php echo esc_js($column); ?>',
1746 - skip_id: '<?php echo esc_js($skip_id); ?>',
1923 + page: 'wdk_frontendajax',
1924 + function: 'treefieldid',
1925 + action: 'wdk_public_action',
1926 + wdk_secure: '" . esc_js(wp_create_nonce('wdk_secure_treefieldid')) . "',
1927 + table: '" . esc_js($table) . "',
1928 + filter_ids: '" . esc_js($filter_ids) . "',
1929 + start_id: '" . (!empty($filter_ids) ? esc_js($selected) : "") . "',
1930 + empty_value: '" . esc_js($empty_value) . "',
1931 + user_check: '" . esc_js($user_check) . "',
1932 + sql_where: '" . esc_js($sql_where) . "',
1933 + hide_fields: '" . esc_js($hide_fields) . "'
1934 + },
1935 + attribute_id: '" . esc_js($attribute_id) . "',
1936 + language_id: '" . esc_js($language_id) . "',
1937 + attribute_value: '" . esc_js($column) . "',
1938 + skip_id: '',
1747 1939 empty_value: ' - ',
1748 - text_search: '<?php esc_html_e('Search term', 'wpdirectorykit');?>',
1749 - text_no_results: '<?php esc_html_e('No results found', 'wpdirectorykit');?>',
1940 + text_search: '" . esc_html__('Search term', 'wpdirectorykit') . "',
1941 + text_no_results: '" . esc_html__('No results found', 'wpdirectorykit') . "',
1750 1942 callback_selected: function(key) {
1751 - $('#wdktreeelem<?php echo esc_js($counter);?>').trigger("change");
1943 + $('#wdktreeelem" . esc_js($counter) . "').trigger('change');
1752 1944 }
1753 1945 }).addClass('init');
1754 - });
1755 - </script>
1756 - <?php
1946 + });"
1947 + );
1757 1948 $counter++;
1758 1949 return $form;
1759 1950 }
1760 1951 }
@@ -1765,9 +1956,9 @@
1765 1956 */
1766 1957 if ( ! function_exists('wdk_treefield_option_checkboxes'))
1767 1958 {
1768 1959 function wdk_treefield_option_checkboxes($name = '', $table=NULL, $selected = NULL,
1769 - $column = 'category_title', $language_id=NULL, $empty_value='', $filter_ids = '', $user_check = FALSE)
1960 + $column = 'category_title', $language_id=NULL, $empty_value='', $filter_ids = '', $user_check = FALSE, $sql_where='', $hide_fields = '')
1770 1961 {
1771 1962 $WMVC = &wdk_get_instance();
1772 1963
1773 1964 if(is_array($filter_ids)) $filter_ids = implode(',', $filter_ids);
@@ -1786,12 +1977,11 @@
1786 1977
1787 1978 $values = '';
1788 1979 if(!empty($selected)){
1789 1980 $ids = array();
1790 -
1791 1981 if(is_string($selected) && strpos($selected, ',') !== FALSE){
1792 1982 $val_selected = explode(',', $selected);
1793 - } elseif(is_string($selected)){
1983 + } elseif($selected){
1794 1984 $val_selected = array($selected);
1795 1985 }
1796 1986
1797 1987 foreach($val_selected as $selected_item) {
@@ -1823,9 +2013,9 @@
1823 2013 if(empty($values)) {
1824 2014 $values = $empty_value;
1825 2015 }
1826 2016
1827 - $form = '<input name="'.$name.'" value="'.esc_html($selected).'" data-placehoder="'.esc_html($values).'" class="wdk-hidden" type="text" id="wdktreeelem_checkbox'.$counter.'" readonly/>';
2017 + $form = '<input name="'.esc_attr($name).'" value="'.esc_html($selected).'" data-placehoder="'.esc_html($values).'" class="wdk-hidden" type="text" id="wdktreeelem_checkbox'.esc_attr($counter).'" readonly/>';
1828 2018
1829 2019 $skip_id = '';
1830 2020 //load javascript library
1831 2021 if($counter==0)
@@ -1836,17 +2026,19 @@
1836 2026 ?>
1837 2027 <script>
1838 2028 jQuery(document).ready(function($) {
1839 2029 $('#wdktreeelem_checkbox<?php echo esc_js($counter);?>:not(.init)').wdkTreefieldCheckboxes({
1840 - ajax_url: '<?php echo admin_url('admin-ajax.php'); ?>',
2030 + ajax_url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
1841 2031 ajax_param: {
1842 2032 "page": 'wdk_frontendajax',
1843 2033 "function": 'treefieldid_checkboxes',
1844 2034 "action": 'wdk_public_action',
2035 + "wdk_secure": '<?php echo esc_js(wp_create_nonce( 'wdk_secure_treefieldid_checkboxes' ));?>',
1845 2036 "table": '<?php echo esc_js($table); ?>',
1846 2037 "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1847 2038 "empty_value": '<?php echo esc_js($empty_value); ?>',
1848 2039 "user_check": '<?php echo esc_js($user_check); ?>',
2040 + "hide_fields": '<?php echo esc_js($hide_fields); ?>',
1849 2041 },
1850 2042 selected: '<?php echo esc_js($selected); ?>',
1851 2043 attribute_id: '<?php echo esc_js($attribute_id); ?>',
1852 2044 language_id: '<?php echo esc_js($language_id); ?>',
@@ -1870,11 +2062,19 @@
1870 2062 if ( ! function_exists('wdk_filter_decimal'))
1871 2063 {
1872 2064 function wdk_filter_decimal($string = '')
1873 2065 {
1874 - if(substr($string, -3, 3) === ".00") {
1875 - return substr($string, 0, -3);
1876 - }
2066 + if(wdk_get_option('wdk_enable_filter_zero_decimal')) {
2067 + if(substr($string, -3, 3) === ",00") {
2068 + return substr($string, 0, -3);
2069 + }
2070 + if(substr($string, -3, 3) === ".00") {
2071 + return substr($string, 0, -3);
2072 + }
2073 + if(substr($string, -3, 1) === "." && substr($string, -1, 1) === "0") {
2074 + return substr($string, 0, -1);
2075 + }
2076 + }
1877 2077
1878 2078 return $string;
1879 2079 }
1880 2080 }
@@ -1952,12 +2152,8 @@
1952 2152 * @return string date in format Y-m-d H:i:s
1953 2153 */
1954 2154 function wdk_normalize_date_db($date, $format = 'Y-m-d H:i:s', $return_format = 'Y-m-d H:i:s')
1955 2155 {
1956 - /* check is date on strtotime */
1957 - if((bool)strtotime($date)){
1958 - return date($return_format, strtotime($date));
1959 - }
1960 2156
1961 2157 /* check is date from argument */
1962 2158 $d = \DateTime::createFromFormat($format, $date);
1963 2159 if($d) {
@@ -1988,24 +2184,29 @@
1988 2184 return $d->format($return_format);
1989 2185 }
1990 2186 }
1991 2187
1992 - /* issue with pm/am inside date, example bug format like "2023 01 19 pm8:06" => 'Y n j ag:i' */
1993 - $format = get_option('date_format').' '.get_option('time_format');
1994 - if(strpos($format, 'a') !== FALSE) {
1995 - $format = str_replace('a', '',$format).' a';
1996 - if(strpos($date, 'am') !== FALSE) {
1997 - $date = str_replace('am', '',$date).' am';
1998 - }
1999 - if(strpos($date, 'pm') !== FALSE) {
2000 - $date = str_replace('pm', '',$date).' pm';
2001 - }
2002 - $d = \DateTime::createFromFormat($format, $date);
2003 - if($d) {
2004 - return $d->format($return_format);
2005 - }
2006 - }
2188 + /* issue with pm/am inside date, example bug format like "2023 01 19 pm8:06" => 'Y n j ag:i' */
2189 + $format = get_option('date_format').' '.get_option('time_format');
2190 + if(strpos($format, 'a') !== FALSE) {
2191 + $format = str_replace('a', '',$format).' a';
2192 + if(strpos($date, 'am') !== FALSE) {
2193 + $date = str_replace('am', '',$date).' am';
2194 + }
2195 + if(strpos($date, 'pm') !== FALSE) {
2196 + $date = str_replace('pm', '',$date).' pm';
2197 + }
2198 + $d = \DateTime::createFromFormat($format, $date);
2199 + if($d) {
2200 + return $d->format($return_format);
2201 + }
2202 + }
2007 2203
2204 + /* check is date on strtotime */
2205 + if((bool)strtotime($date)){
2206 + return gmdate($return_format, strtotime($date));
2207 + }
2208 +
2008 2209 return false;
2009 2210 }
2010 2211 }
2011 2212
@@ -2023,9 +2224,100 @@
2023 2224 return $base_url.$extension_url;
2024 2225 }
2025 2226 }
2026 2227
2228 +
2027 2229 /**
2230 + * Insert an attachment from a remote URL.
2231 + *
2232 + * @param string $url Remote file URL.
2233 + * @param int|null $parent_post_id Post ID to attach the image to.
2234 + * @return int|false Attachment ID or false on failure.
2235 + */
2236 +function wdk_insert_attachment_from_cloud_url($url, $parent_post_id = null) {
2237 + // Request with headers (Google blocks requests without UA sometimes)
2238 + $response = wp_remote_get($url, array(
2239 + 'timeout' => 30,
2240 + 'redirection' => 5,
2241 + 'headers' => array(
2242 + 'User-Agent' => 'Mozilla/5.0 (WordPress)',
2243 + 'Referer' => home_url()
2244 + )
2245 + ));
2246 +
2247 + if (is_wp_error($response)) {
2248 + return false;
2249 + }
2250 +
2251 + $code = wp_remote_retrieve_response_code($response);
2252 + if ($code != 200) {
2253 + return false;
2254 + }
2255 +
2256 + $body = wp_remote_retrieve_body($response);
2257 + if (empty($body)) {
2258 + return false;
2259 + }
2260 +
2261 + // Try to get filename from URL or headers
2262 + $filename = basename(wp_parse_url($url, PHP_URL_PATH));
2263 +
2264 + // If filename empty (Google Drive case)
2265 + if (!$filename || strpos($filename, '.') === false) {
2266 + // Try content-disposition header
2267 + $headers = wp_remote_retrieve_headers($response);
2268 + if (!empty($headers['content-disposition']) &&
2269 + preg_match('/filename="?([^"]+)"?/i', $headers['content-disposition'], $matches)) {
2270 + $filename = sanitize_file_name($matches[1]);
2271 + }
2272 + }
2273 +
2274 + // If still no extension, detect from mime
2275 + $ext = pathinfo($filename, PATHINFO_EXTENSION);
2276 + if (empty($ext)) {
2277 + $data = getimagesizefromstring($body);
2278 + if (!$data || empty($data['mime'])) {
2279 + return false;
2280 + }
2281 + $ext = wdk_mime2ext($data['mime']);
2282 + $filename = time() . '-' . wp_generate_password(6, false) . '.' . $ext;
2283 + }
2284 +
2285 + // Save file to uploads dir
2286 + $upload = wp_upload_bits($filename, null, $body);
2287 + if (!empty($upload['error'])) {
2288 + return false;
2289 + }
2290 +
2291 + $file_path = $upload['file'];
2292 + $file_name = basename($file_path);
2293 + $file_type = wp_check_filetype($file_name, null);
2294 + $wp_upload_dir = wp_upload_dir();
2295 +
2296 + $post_info = array(
2297 + 'guid' => $wp_upload_dir['url'] . '/' . $file_name,
2298 + 'post_mime_type' => $file_type['type'],
2299 + 'post_title' => sanitize_file_name(pathinfo($file_name, PATHINFO_FILENAME)),
2300 + 'post_content' => '',
2301 + 'post_status' => 'inherit',
2302 + );
2303 +
2304 + // Insert attachment
2305 + $attach_id = wp_insert_attachment($post_info, $file_path, $parent_post_id);
2306 +
2307 + if (!$attach_id) {
2308 + return false;
2309 + }
2310 +
2311 + // Generate metadata
2312 + require_once ABSPATH . 'wp-admin/includes/image.php';
2313 + $attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
2314 + wp_update_attachment_metadata($attach_id, $attach_data);
2315 +
2316 + return $attach_id;
2317 +}
2318 +
2319 +/**
2028 2320 * Insert an attachment from an URL address.
2029 2321 *
2030 2322 * @param String $url
2031 2323 * @param Int $parent_post_id
@@ -2047,14 +2339,14 @@
2047 2339 $filename = substr($filename, 0, strpos($filename, '?'));
2048 2340 }
2049 2341
2050 2342 /* if unsoported extension */
2051 - if(in_array(wdk_file_extension($filename), array('php','asp'))){
2343 + if(in_array(wdk_file_extension($filename), array('php','asp')) || strlen(wdk_file_extension($filename)) > 5){
2052 2344 $data = getimagesizefromstring($response['body']);
2053 2345 if(!$data) return false;
2054 2346 if(empty($data['mime'])) return false;
2055 2347
2056 - $filename = time().rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2348 + $filename = time().wp_rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2057 2349 }
2058 2350 $upload = wp_upload_bits( $filename, null, $response['body'] );
2059 2351
2060 2352 if( !empty( $upload['error'] ) ) {
@@ -2146,17 +2438,12 @@
2146 2438 */
2147 2439
2148 2440 function wdk_generate_profile_permalink($profile = array())
2149 2441 {
2150 -
2151 2442 $profile_slug = '';
2152 - if(wmvc_show_data('user_login', $profile, false)){
2153 - $profile_slug = wmvc_show_data('user_login', $profile);
2154 - if(wmvc_show_data('wdk_slug', $profile))
2155 - $profile_slug = wmvc_show_data('wdk_slug', $profile);
2156 - } else if(is_intval($profile)){
2443 + if(is_intval($profile)){
2157 2444 $profile_data = get_userdata($profile);
2158 - if(wmvc_show_data('wdk_slug', $profile, false)){
2445 + if(wmvc_show_data('wdk_slug', $profile_data, false)){
2159 2446 $profile_slug = wmvc_show_data('wdk_slug', $profile);
2160 2447 }elseif(wmvc_show_data('user_login', $profile_data, false)){
2161 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2162 2449 } else {
@@ -2161,10 +2448,14 @@
2161 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2162 2449 } else {
2163 2450 $profile_slug = $profile;
2164 2451 }
2165 - }
2166 -
2452 + } else if(wmvc_show_data('user_login', $profile, false)){
2453 + $profile_slug = wmvc_show_data('user_login', $profile);
2454 + if(wmvc_show_data('wdk_slug', $profile))
2455 + $profile_slug = wmvc_show_data('wdk_slug', $profile);
2456 + }
2457 +
2167 2458 $user_profile_page = get_option('wdk_membership_profile_preview_page');
2168 2459 if(!$user_profile_page) {
2169 2460 return '#';
2170 2461 }
@@ -2258,12 +2549,18 @@
2258 2549 {
2259 2550 $url = wp_login_url($url_redirect);
2260 2551
2261 2552 if(get_option('wdk_membership_login_page')){
2262 - $url = wdk_url_suffix(get_permalink(get_option('wdk_membership_login_page')), 'redirect_to='. urlencode($url_redirect).'&custom_message='. urlencode($custom_message));
2553 + $url = wdk_url_suffix(get_permalink(get_option('wdk_membership_login_page')));
2554 + if(!empty($url_redirect)) {
2555 + $url = wdk_url_suffix(get_permalink(get_option('wdk_membership_login_page')), 'redirect_to='. urlencode($url_redirect));
2556 + }
2557 + if(!empty($custom_message)) {
2558 + $url = wdk_url_suffix(get_permalink(get_option('wdk_membership_login_page')), 'custom_message='. urlencode($custom_message));
2559 + }
2263 2560 }
2264 2561
2265 - return $url;
2562 + return trim($url, '?');
2266 2563 }
2267 2564 }
2268 2565
2269 2566 if(!function_exists('wdk_mail')) {
@@ -2282,10 +2579,10 @@
2282 2579 if(empty($subject))
2283 2580 $subject = __("New message", "wpdirectorykit");
2284 2581
2285 2582 $headers = array('Content-Type: text/html; charset=UTF-8');
2286 - $headers[] = 'From: '.$email_from;
2287 -
2583 + $headers[] = 'From: "'.get_bloginfo('name').'" <'.$email_from.'>';
2584 +
2288 2585 if(!empty($reply_to)) {
2289 2586 $headers[] = 'Reply-To: '.$reply_to;
2290 2587 } else {
2291 2588 $headers[] = 'Reply-To: '.$email_from;
@@ -2413,19 +2710,19 @@
2413 2710 <!-- Your add & remove file links -->
2414 2711 <p class="hide-if-no-js">
2415 2712 <a class="upload-custom-img <?php if ( $you_have_file ) { echo 'hidden'; } ?>"
2416 2713 href="<?php echo esc_url($upload_link) ?>">
2417 - <?php echo esc_html__('Select file','wmvc_win') ?>
2714 + <?php echo esc_html__('Select file','wpdirectorykit') ?>
2418 2715 </a>
2419 2716 <a class="delete-custom-img <?php if ( ! $you_have_file ) { echo 'hidden'; } ?>"
2420 2717 href="#">
2421 - <?php echo esc_html__('Remove file','wmvc_win') ?>
2718 + <?php echo esc_html__('Remove all files','wpdirectorykit') ?>
2422 2719 </a>
2423 2720 </p>
2424 2721 <?php //endif; ?>
2425 2722
2426 2723 <!-- A hidden input to set and post the chosen file id -->
2427 - <input class="logo_file_id" type="hidden" id="<?php echo esc_html($field_name); ?>" name="<?php echo esc_html($field_name); ?>" value="<?php echo esc_html($file_id); ?>" />
2724 + <input class="logo_file_id" type="hidden" id="<?php echo esc_attr($field_name); ?>" name="<?php echo esc_attr($field_name); ?>" value="<?php echo esc_attr($file_id); ?>" />
2428 2725 </div>
2429 2726
2430 2727 <?php
2431 2728 $custom_js ='';
@@ -2433,8 +2730,9 @@
2433 2730 if( typeof jQuery.fn.wpMediaElementFile == 'function')
2434 2731 $('#".esc_js($field_name)."meta-box-id.postbox-upload').wpMediaElementFile();
2435 2732 });";
2436 2733
2734 +// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2437 2735 echo "<script>".$custom_js."</script>";
2438 2736
2439 2737 ?>
2440 2738
@@ -2485,19 +2783,15 @@
2485 2783 function wdk_upload_multi_files($field_name, $image_ids='', $texts = array())
2486 2784 {
2487 2785 static $media_element_counter = 0;
2488 2786
2489 - if(!isset($texts['file_select']))$texts['file_select'] = esc_html__('Select file','wmvc_win');
2490 - if(!isset($texts['file_remove']))$texts['file_remove'] = esc_html__('Remove file','wmvc_win');
2787 + if(!isset($texts['file_select']))$texts['file_select'] = esc_html__('Select file','wpdirectorykit');
2788 + if(!isset($texts['file_remove']))$texts['file_remove'] = esc_html__('Remove all files','wpdirectorykit');
2491 2789
2492 2790 $media_element_counter++;
2493 2791
2494 2792 $img_field = $field_name.'_'.$media_element_counter;
2495 2793
2496 - wp_register_script( 'wpmediaelement_file', WPDIRECTORYKIT_URL . 'admin/js/jquery.wpmediaelement_file.js', array( 'jquery' ), false, false );
2497 - wp_enqueue_script( 'wpmediaelement_file' );
2498 - wp_enqueue_media();
2499 -
2500 2794 wp_enqueue_script( 'wpmediamultiple' );
2501 2795 wp_enqueue_script( 'jquery-ui-mouse' );
2502 2796 wp_enqueue_media();
2503 2797
@@ -2534,9 +2828,9 @@
2534 2828 <!-- Your image container, which can be manipulated with js -->
2535 2829 <div class="custom-img-container winter_mvc-media">
2536 2830 <?php if($you_have_img)foreach($your_img_src as $image_id => $img_src) : ?>
2537 2831 <div class="winter_mvc-media-card" data-media-id="<?php echo esc_attr($image_id);?>">
2538 - <img src="<?php echo esc_html($img_src); ?>" style="object-fit: contain;" alt="<?php echo esc_attr__('thumb', 'wmvc_win');?>" style="max-width:100%;" class="thumbnail"/>
2832 + <img src="<?php echo esc_attr($img_src); ?>" style="object-fit: contain;" alt="<?php echo esc_attr__('thumb', 'wpdirectorykit');?>" style="max-width:100%;" class="thumbnail"/>
2539 2833 <a href="#" class="remove"></a>
2540 2834 </div>
2541 2835 <?php endforeach; ?>
2542 2836 </div>
@@ -2556,9 +2850,9 @@
2556 2850 </p>
2557 2851 <?php //endif; ?>
2558 2852
2559 2853 <!-- A hidden input to set and post the chosen image id -->
2560 - <input class="logo_image_id" type="hidden" id="<?php echo esc_html(esc_html($field_name)); ?>" name="<?php echo esc_html($field_name); ?>" value="<?php echo esc_html($image_ids); ?>" />
2854 + <input class="logo_image_id" type="hidden" id="<?php echo esc_attr(esc_html($field_name)); ?>" name="<?php echo esc_attr($field_name); ?>" value="<?php echo esc_attr($image_ids); ?>" />
2561 2855 </div>
2562 2856 <?php
2563 2857 $custom_js ='';
2564 2858 $custom_js .=" jQuery(function($) {
@@ -2564,11 +2858,14 @@
2564 2858 $custom_js .=" jQuery(function($) {
2565 2859 if( typeof jQuery.fn.wpMediaMultiple == 'function')
2566 2860 $('#".esc_js($field_name)."meta-box-id.postbox-upload-multiple').wpMediaMultiple({
2567 2861 frame: {
2568 - title: '".esc_js(__('Select or Upload Media Of Your Chosen Persuasion','wpdirectorykit'))."',
2862 + title: '".esc_js(__('Upload and select your images here for use with your listing','wpdirectorykit'))."',
2569 2863 button: '".esc_js(__('Use this media','wpdirectorykit'))."',
2570 - }
2864 + },
2865 + library: {
2866 + type: ['application', 'image', 'video']
2867 + },
2571 2868 });
2572 2869 /* order */
2573 2870 var re_order = function(media_element){
2574 2871 var list_media = '';
@@ -2595,8 +2892,9 @@
2595 2892 })
2596 2893 });
2597 2894 ";
2598 2895
2896 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2599 2897 echo "<script>".$custom_js."</script>";
2600 2898
2601 2899 ?>
2602 2900
@@ -2677,8 +2975,59 @@
2677 2975
2678 2976 }
2679 2977 }
2680 2978
2979 +if ( ! function_exists('wdk_recaptcha_field_v3'))
2980 +{
2981 + function wdk_recaptcha_field_v3($wdk_recaptcha_site_key=null, $wdk_recaptcha_secret_key=null, $load_script=true)
2982 + {
2983 + static $counter = 0;
2984 +
2985 + if(empty($wdk_recaptcha_site_key) && empty($wdk_recaptcha_site_key)) {
2986 + $wdk_recaptcha_site_key = get_option('wdk_recaptcha_site_key_v3');
2987 + $wdk_recaptcha_secret_key = get_option('wdk_recaptcha_secret_key_v3');
2988 + }
2989 +
2990 + if($wdk_recaptcha_site_key && $wdk_recaptcha_secret_key)
2991 + {
2992 + if($load_script && $counter===0)
2993 + {
2994 + wp_enqueue_script(
2995 + 'google-recaptcha-v3',
2996 + 'https://www.google.com/recaptcha/api.js?render=' . esc_attr(trim($wdk_recaptcha_site_key)),
2997 + array(),
2998 + null,
2999 + true
3000 + );
3001 +
3002 + }
3003 + $counter++;
3004 + ?>
3005 + <input type="hidden" name="g-recaptcha-response" id="recaptcha_called_v3_count_<?php echo esc_html($counter);?>">
3006 + <script>
3007 + (function(){
3008 + const field_token = document.getElementById('recaptcha_called_v3_count_<?php echo esc_html($counter);?>');
3009 + grecaptcha.ready(function() {
3010 + grecaptcha.execute('<?php echo esc_attr(trim($wdk_recaptcha_site_key));?>', {action: 'submit'}).then(function(token) {
3011 + field_token.value = token;
3012 + });
3013 + });
3014 +
3015 + // Reload token after form submit
3016 + field_token.closest('form').addEventListener('submit', function(e) {
3017 + e.preventDefault();
3018 + grecaptcha.execute('<?php echo esc_attr(trim($wdk_recaptcha_site_key));?>', {action: 'submit'}).then(function(token) {
3019 + field_token.value = token;
3020 + });
3021 + });
3022 + })();
3023 + </script>
3024 + <?php
3025 + }
3026 + }
3027 +}
3028 +
3029 +
2681 3030 if ( ! function_exists('wdk_recaptcha_field'))
2682 3031 {
2683 3032 function wdk_recaptcha_field($is_compact=false, $style="", $load_script=true)
2684 3033 {
@@ -2688,9 +3037,16 @@
2688 3037 if(get_option('wdk_recaptcha_site_key') !== FALSE && get_option('wdk_recaptcha_secret_key') !== NULL)
2689 3038 {
2690 3039 if($load_script && $counter===0)
2691 3040 {
2692 - echo "<script src='https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&amp;render=explicit'></script>";
3041 + wp_enqueue_script(
3042 + 'google-recaptcha-v2',
3043 + 'https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit',
3044 + array(),
3045 + null,
3046 + true
3047 + );
3048 +
2693 3049 }
2694 3050 $counter++;
2695 3051
2696 3052 $compact_tag='';
@@ -2702,15 +3058,15 @@
2702 3058 }
2703 3059
2704 3060 $recaptcha_array[$counter] = array('size'=>$size_tag);
2705 3061
2706 - echo '<div id="recaptcha_called_'.$counter.'" class="g-recaptcha" style="'.$style.'" '.$compact_tag.' data-sitekey="'.get_option('wdk_recaptcha_site_key').'"></div>';
3062 + echo '<div id="recaptcha_called_'.esc_attr($counter).'" class="g-recaptcha" style="'.esc_attr($style).'" '.esc_attr($compact_tag).' data-sitekey="'.esc_attr(get_option('wdk_recaptcha_site_key')).'"></div>';
2707 3063 ?>
2708 3064
2709 3065 <script>
2710 3066 <?php if($counter===1)echo 'var ';?>CaptchaCallback = function(){
2711 3067 <?php for($j=1;$j<=$counter;$j++): ?>
2712 - grecaptcha.render(document.getElementById('recaptcha_called_<?php echo $j;?>'), {'size' : '<?php echo $recaptcha_array[$j]['size']; ?>', 'sitekey' : '<?php echo get_option('wdk_recaptcha_site_key'); ?>'});
3068 + grecaptcha.render(document.getElementById('recaptcha_called_<?php echo esc_attr($j);?>'), {'size' : '<?php echo esc_attr($recaptcha_array[$j]['size']); ?>', 'sitekey' : '<?php echo esc_attr(get_option('wdk_recaptcha_site_key')); ?>'});
2713 3069 <?php endfor; ?>
2714 3070 };
2715 3071 </script>
2716 3072
@@ -2812,9 +3168,9 @@
2812 3168 if(is_array($val))
2813 3169 {
2814 3170 return wdk_clean($_POST);
2815 3171 }
2816 - else
3172 + elseif(is_string($val))
2817 3173 {
2818 3174 if(strpos($val, '<iframe') === 0)
2819 3175 $val = str_replace("'",'"', $val);
2820 3176
@@ -2853,9 +3209,9 @@
2853 3209 if(is_array($val))
2854 3210 {
2855 3211 $arr_cleaned[sanitize_text_field($key)] = wdk_clean($val);
2856 3212 }
2857 - else
3213 + elseif(is_string($val))
2858 3214 {
2859 3215 $arr_cleaned[sanitize_text_field($key)] = wp_kses_post($val);
2860 3216 }
2861 3217
@@ -2865,8 +3221,34 @@
2865 3221
2866 3222 return $arr_cleaned;
2867 3223 }
2868 3224
3225 +function wdk_clean_mixed($item)
3226 +{
3227 + $arr_cleaned = array();
3228 +
3229 + if(is_array($item))
3230 + {
3231 + foreach($item as $key=>$val)
3232 + {
3233 + if(is_array($val))
3234 + {
3235 + $arr_cleaned[sanitize_text_field($key)] = wdk_clean_mixed($val);
3236 + }
3237 + else
3238 + {
3239 + $arr_cleaned[sanitize_text_field($key)] = wp_kses_post($val);
3240 + }
3241 + }
3242 + }
3243 + else
3244 + {
3245 + return wp_kses_post($item);
3246 + }
3247 +
3248 + return $arr_cleaned;
3249 +}
3250 +
2869 3251 /*
2870 3252 <select class="form-control" name="<?php echo 'control_operator_'.$i_fieldnum; ?>">
2871 3253 <option value="CONTAINS">CONTAINS</option>
2872 3254 <option value="NOT_CONTAINS">NOT_CONTAINS</option>
@@ -2907,9 +3289,9 @@
2907 3289
2908 3290 if(is_array($filter_ids)) $filter_ids = implode(',', $filter_ids);
2909 3291
2910 3292 static $counter = 0;
2911 - $form = '<select data-ajax="'.admin_url('admin-ajax.php').'" name="'.$name.'" data-table="'.$table.'" '.$attr.' data-placeholder="'.$empty_value.'" class="form-control select_ajax" id="wdk_select2_'.$counter.'" multiple="">';
3293 + $form = '<select data-ajax="'.admin_url('admin-ajax.php').'" name="'.esc_attr($name).'" data-table="'.esc_attr($table).'" '.esc_attr($attr).' data-placeholder="'.esc_attr($empty_value).'" class="form-control select_ajax" id="wdk_select2_'.esc_attr($counter).'" multiple="">';
2912 3294
2913 3295
2914 3296 if(false)
2915 3297 if( $column_key == 'idcategory') {
@@ -2923,9 +3305,9 @@
2923 3305
2924 3306 $ids = array();
2925 3307 foreach($selected as $selected_item) {
2926 3308 if(!empty($selected_item)) {
2927 - $ids [] = $selected_item;
3309 + $ids [] = (int) $selected_item;
2928 3310 }
2929 3311 }
2930 3312
2931 3313 /* where in */
@@ -2936,15 +3318,19 @@
2936 3318
2937 3319 $results = $WMVC->$table->get();
2938 3320 foreach ($results as $item) {
2939 3321 if($item)
2940 - $form .= '<option selected="selected" value="'.esc_attr(wmvc_show_data($column_key, $item, false, TRUE, TRUE)).'">'.esc_html(wmvc_show_data($column_print, $item, false, TRUE, TRUE)).'</option>';
3322 + // Dynamic field values are registered in the translation catalog separately.
3323 + // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText
3324 + $form .= '<option selected="selected" value="'.esc_attr(wmvc_show_data($column_key, $item, false, TRUE, TRUE)).'">'.esc_html__(wmvc_show_data($column_print, $item, false, TRUE, TRUE),'wpdirectorykit').'</option>';
2941 3325 }
2942 3326 }
2943 3327 } elseif(is_intval($selected)) {
2944 3328 $db_item = $WMVC->$table->get($selected, TRUE);
2945 3329 if($db_item)
2946 - $form .= '<option selected="selected" value="'.esc_attr(wmvc_show_data($column_key, $db_item, false, TRUE, TRUE)).'">'.esc_attr(wmvc_show_data($column_print, $db_item, false, TRUE, TRUE)).'</option>';
3330 + // Dynamic field values are registered in the translation catalog separately.
3331 + // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText
3332 + $form .= '<option selected="selected" value="'.esc_attr(wmvc_show_data($column_key, $db_item, false, TRUE, TRUE)).'">'.esc_html__(wmvc_show_data($column_print, $db_item, false, TRUE, TRUE),'wpdirectorykit').'</option>';
2947 3333 }
2948 3334 } else {
2949 3335 //$form .= '<option value="" selected="selected">'.esc_html__('Not selected', 'wpdirectorykit').'</option>';
2950 3336 }
@@ -2952,11 +3338,11 @@
2952 3338
2953 3339 //load javascript library
2954 3340 if($counter==0)
2955 3341 {
2956 - wp_enqueue_script('select2');
3342 + wp_enqueue_script('select2-select2');
2957 3343 wp_enqueue_script('wdk-select2');
2958 - wp_enqueue_style('select2');
3344 + wp_enqueue_style('select2-select2');
2959 3345 }
2960 3346 ?>
2961 3347 <?php
2962 3348 $counter++;
@@ -3000,11 +3386,11 @@
3000 3386
3001 3387 //load javascript library
3002 3388 if($counter==0)
3003 3389 {
3004 - wp_enqueue_script('select2');
3390 + wp_enqueue_script('select2-select2');
3005 3391 wp_enqueue_script('wdk-select2');
3006 - wp_enqueue_style('select2');
3392 + wp_enqueue_style('select2-select2');
3007 3393 }
3008 3394 ?>
3009 3395 <?php
3010 3396 $counter++;
@@ -3082,11 +3468,30 @@
3082 3468 'r'=>'llll',
3083 3469 'u'=>'x',
3084 3470 );
3085 3471
3086 - $replaced_from = array_keys($replaced);
3087 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3088 - return str_replace(array_reverse(array_keys($replaced_from)), array_reverse($replaced), $date_format);
3472 +
3473 + $result = '';
3474 + $escaped = false;
3475 + $length = strlen($date_format);
3476 +
3477 + for ($i = 0; $i < $length; $i++) {
3478 + $char = $date_format[$i];
3479 +
3480 + if ($char === '\\') {
3481 + $escaped = true;
3482 + continue;
3483 + }
3484 +
3485 + if ($escaped) {
3486 + $result .= "'".$char."'";
3487 + $escaped = false;
3488 + } else {
3489 + $result .= isset($replaced[$char]) ? $replaced[$char] : $char;
3490 + }
3491 + }
3492 +
3493 + return str_replace("''", '',$result);
3089 3494 }
3090 3495 }
3091 3496
3092 3497 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3127,11 +3532,29 @@
3127 3532 'u'=>'@',
3128 3533 ':'=>'',
3129 3534 );
3130 3535
3131 - $replaced_from = array_keys($replaced);
3132 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3133 - return str_replace(array_reverse(array_keys($replaced_from)), array_reverse($replaced), $date_format);
3536 + $result = '';
3537 + $escaped = false;
3538 + $length = strlen($date_format);
3539 +
3540 + for ($i = 0; $i < $length; $i++) {
3541 + $char = $date_format[$i];
3542 +
3543 + if ($char === '\\') {
3544 + $escaped = true;
3545 + continue;
3546 + }
3547 +
3548 + if ($escaped) {
3549 + $result .= "'".$char."'";
3550 + $escaped = false;
3551 + } else {
3552 + $result .= isset($replaced[$char]) ? $replaced[$char] : $char;
3553 + }
3554 + }
3555 +
3556 + return str_replace("''", '',$result);
3134 3557 }
3135 3558 }
3136 3559
3137 3560 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3172,11 +3595,31 @@
3172 3595 'u'=>'@',
3173 3596 ':'=>'',
3174 3597 );
3175 3598
3176 - $replaced_from = array_keys($replaced);
3177 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3178 - return str_replace(array_reverse(array_keys($replaced_from)), array_reverse($replaced), $date_format);
3599 +
3600 + $result = '';
3601 + $escaped = false;
3602 + $length = strlen($date_format);
3603 +
3604 + for ($i = 0; $i < $length; $i++) {
3605 + $char = $date_format[$i];
3606 +
3607 + if ($char === '\\') {
3608 + $escaped = true;
3609 + continue;
3610 + }
3611 +
3612 + if ($escaped) {
3613 + $result .= "'".$char."'";
3614 + $escaped = false;
3615 + } else {
3616 + $result .= isset($replaced[$char]) ? $replaced[$char] : $char;
3617 + }
3618 + }
3619 +
3620 + return str_replace("''", '',$result);
3621 +
3179 3622 }
3180 3623 }
3181 3624
3182 3625 if ( ! function_exists('wdk_get_gps'))
@@ -3204,9 +3647,17 @@
3204 3647
3205 3648 if(!isset($results[$address])) {
3206 3649 $results[$address] = NULL;
3207 3650 $url = 'https://nominatim.openstreetmap.org/search?format=json&q=' . $address;
3208 - $request = wp_remote_get( $url );
3651 +
3652 + // Add required User-Agent header
3653 + $args = [
3654 + 'timeout' => 10,
3655 + 'headers' => [
3656 + 'User-Agent' => get_bloginfo('name') . '/1.0 (' . get_bloginfo('admin_email') . ')',
3657 + ],
3658 + ];
3659 + $request = wp_remote_get( $url, $args);
3209 3660 $response = '';
3210 3661
3211 3662 // request failed
3212 3663 if ( is_wp_error( $request ) ) {
@@ -3362,8 +3813,32 @@
3362 3813 return false;
3363 3814 }
3364 3815 }
3365 3816
3817 +if ( ! function_exists('is_wdk_whatsapp'))
3818 +{
3819 + // Validation phone
3820 + /**
3821 + * @param string $value phone in string
3822 + * @return bool
3823 + */
3824 + function is_wdk_whatsapp($value = '') {
3825 + return true;
3826 + }
3827 +}
3828 +
3829 +if ( ! function_exists('is_wdk_viber'))
3830 +{
3831 + // Validation phone
3832 + /**
3833 + * @param string $value phone in string
3834 + * @return bool
3835 + */
3836 + function is_wdk_viber($value = '') {
3837 + return true;
3838 + }
3839 +}
3840 +
3366 3841 if ( ! function_exists('wdk_filter_phone'))
3367 3842 {
3368 3843 // Validation phone
3369 3844 /**
@@ -3499,9 +3974,22 @@
3499 3974
3500 3975 $value = filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
3501 3976 $value = (float)str_replace(array(","," ",'&nbsp;'), "", $value);
3502 3977
3503 - return number_format_i18n($value);
3978 + // Allow decimal precision to be filtered (default is 0)
3979 + $decimals = apply_filters('wdk_number_format_decimals', ((wdk_get_option('wdk_number_format_decimals')) ? wdk_get_option('wdk_number_format_decimals') : 0));
3980 +
3981 + if(!get_option('wdk_disable_custom_muber_format')) {
3982 + global $wp_locale;
3983 + return number_format(
3984 + $value,
3985 + $decimals,
3986 + $wp_locale->number_format['decimal_point'],
3987 + $wp_locale->number_format['thousands_sep']
3988 + );
3989 + }
3990 +
3991 + return number_format_i18n($value, $decimals);
3504 3992 }
3505 3993 }
3506 3994
3507 3995 if ( ! function_exists('wdk_currency_symbol'))
@@ -3631,11 +4119,23 @@
3631 4119 $user_data['wdk_viber'] = wmvc_show_data('cacheduser_wdk_viber', $row);
3632 4120 $user_data['wdk_iban'] = wmvc_show_data('cacheduser_wdk_iban', $row);
3633 4121 $user_data['wdk_telegram'] = wmvc_show_data('cacheduser_wdk_telegram', $row);
3634 4122 $user_data['wdk_position_title'] = wmvc_show_data('cacheduser_wdk_position_title', $row);
4123 + $user_data['agency_name'] = wmvc_show_data('cacheduser_agency_name', $row);
3635 4124 $user_data['description'] = wmvc_show_data('cacheduser_description', $row);
3636 4125 $user_data['user_url'] = wmvc_show_data('cacheduser_user_url', $row);
3637 - $user_data['roles'] = explode(',', wmvc_show_data('cacheduser_roles', $value));
4126 + $user_data['roles'] = explode(',', wmvc_show_data('cacheduser_roles', $row));
4127 + $user_data['wdk_slug'] = wmvc_show_data('cacheduser_wdk_slug', $row);
4128 + $user_data['user_login'] = wmvc_show_data('cacheduser_user_login', $row);
4129 + $user_data['user_id'] = wmvc_show_data('cacheduser_user_id', $row);
4130 +
4131 + if(function_exists('wdk_generate_profile_permalink') && $user_data['profile_url'] == '#') {
4132 + if($user_data['user_login']) {
4133 + $user_data['profile_url'] = wdk_generate_profile_permalink($user_data);
4134 + } else {
4135 + $user_data['profile_url'] = wdk_generate_profile_permalink(wmvc_show_data('user_id', $user_data));
4136 + }
4137 + }
3638 4138
3639 4139 return $user_data;
3640 4140 }
3641 4141 }
@@ -3879,11 +4379,11 @@
3879 4379 $page_title,
3880 4380 $post_type
3881 4381 );
3882 4382 }
3883 -
3884 - $page = $wpdb->get_var( $sql );
3885 -
4383 + $page = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
4384 +
4385 +
3886 4386 if ( $page ) {
3887 4387 return get_post( $page, $output );
3888 4388 }
3889 4389
@@ -3947,9 +4447,9 @@
3947 4447 $output .= '<tr>';
3948 4448 foreach($var as $k => $v) {
3949 4449 if(count($columns) > 0 && !in_array($k, $columns))continue;
3950 4450
3951 - $output .= '<td><strong>' . $k . '</strong></td>';
4451 + $output .= '<td><strong>' . esc_html($k) . '</strong></td>';
3952 4452 }
3953 4453 $output .= '</tr>';
3954 4454 }
3955 4455
@@ -3956,13 +4456,14 @@
3956 4456 $output .= '<tr>';
3957 4457 foreach($var as $k => $v) {
3958 4458 if(count($columns) > 0 && !in_array($k, $columns))continue;
3959 4459
3960 - $output .= '<td>' . $v . '</td>';
4460 + $output .= '<td>' . esc_html($v) . '</td>';
3961 4461 }
3962 4462 $output .= '</tr>';
3963 4463 }
3964 4464 $output .= '</table>';
4465 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
3965 4466 echo $output;
3966 4467 }
3967 4468 }
3968 4469
@@ -3968,9 +4469,9 @@
3968 4469
3969 4470 if ( ! function_exists('wdk_move_gps'))
3970 4471 {
3971 4472 function wdk_move_gps($value) {
3972 - return $value+0.001 * rand(1, 9);
4473 + return $value+0.001 * wp_rand(1, 9);
3973 4474 }
3974 4475 }
3975 4476
3976 4477 if ( ! function_exists('wdk_get_near_location'))
@@ -3978,10 +4479,10 @@
3978 4479 function wdk_get_near_location($latitude, $longitude, $radius = 10000) {
3979 4480 // Convert radius from meters to degrees
3980 4481 $radiusInDegrees = $radius / 111000;
3981 4482
3982 - $u = mt_rand() / mt_getrandmax();
3983 - $v = mt_rand() / mt_getrandmax();
4483 + $u = wp_rand() / mt_getrandmax();
4484 + $v = wp_rand() / mt_getrandmax();
3984 4485 $w = $radiusInDegrees * sqrt($u);
3985 4486 $t = 2 * M_PI * $v;
3986 4487 $x = $w * cos($t);
3987 4488 $y = $w * sin($t);
@@ -4028,5 +4529,924 @@
4028 4529 return FALSE;
4029 4530 }
4030 4531 }
4031 4532
4032 -?>
4533 +if ( ! function_exists('wdk_cached_field_get'))
4534 +{
4535 + function wdk_cached_field_get($udpate_cache = FALSE) {
4536 + static $fields = NULL;
4537 +
4538 + $WMVC = &wdk_get_instance();
4539 + $WMVC->model('field_m');
4540 +
4541 + if(is_null($fields) || $udpate_cache) {
4542 + $fields = $WMVC->field_m->get();
4543 + }
4544 +
4545 + return $fields;
4546 + }
4547 +}
4548 +
4549 +if (! function_exists('wdk_generate_slug'))
4550 +{
4551 + function wdk_generate_slug($str, $separator = 'dash', $lowercase = TRUE)
4552 + {
4553 + if ($separator == 'dash')
4554 + {
4555 + $search = '_';
4556 + $replace = '-';
4557 + }
4558 + else
4559 + {
4560 + $search = '-';
4561 + $replace = '_';
4562 + }
4563 +
4564 + $dot='';
4565 + if($separator == 'dot'){
4566 + $str = str_replace(' ', '.', $str);
4567 + $dot='.';
4568 + }
4569 +
4570 + $trans = array(
4571 + $search => $replace,
4572 + "\s+" => $replace,
4573 + "[^a-z0-9".$replace.$dot."]" => '',
4574 + $replace."+" => $replace,
4575 + $replace."$" => '',
4576 + "^".$replace => ''
4577 + );
4578 +
4579 + // For Croatia
4580 + $str = str_replace(array('č','ć','ž','š','đ', 'Č','Ć','Ž','Š','Đ'),
4581 + array('c','c','z','s','d', 'c','c','z','s','d'), $str);
4582 +
4583 + // For Turkish
4584 + $str = str_replace(array('ş','Ş','ı','İ','ğ','Ğ','Ü','ü','Ö','ö','ç','Ç'),
4585 + array('s','s','i','i','g','g','u','u','o','o','c','c'), $str);
4586 +
4587 + // Russian alphabet
4588 + $str = str_replace(array('А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я'),
4589 + array('a','b','v','g','d','e','e','zh','z','i','y','k','l','m','n','o','p','r','s','t','u','f','kh','c','ch','sh','sh','','y','','e','yu','ya'), $str);
4590 + $str = str_replace(array('а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п','р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я'),
4591 + array('a','b','v','g','d','e','e','zh','z','i','y','k','l','m','n','o','p','r','s','t','u','f','kh','c','ch','sh','sh','','y','','e','yu','ya'), $str);
4592 +
4593 + // Ukrainian alphabet
4594 + $str = str_replace(array('Ґ','Є','І','Ї'),
4595 + array('G','E','I','I'), $str);
4596 + $str = str_replace(array('ґ','є','і','ї'),
4597 + array('g','e','i','i'), $str);
4598 + // Symbols
4599 + $str = str_replace(array("  ","’","–",'«','»','№','„','”'),
4600 + array("","","-",'','','no','',''), $str);
4601 +
4602 + // Alphabets Czech Croatian Turkish and other
4603 + $str = str_replace(array('Á','Ä','Ď','É','Ě','Ë','Í','Ň','Ń','Ó','Ŕ','Ř','Ť','Ú','Ů','Ý','Ź','Č','Ć','Ž','Š','Đ','Ş','İ','Ğ','Ü','Ö','Ç'),
4604 + array('a','a','d','e','e','e','i','n','n','o','r','r','t','u','u','y','z','c','c','z','s','d','s','i','g','u','o','c'), $str);
4605 + $str = str_replace(array('á','ä','ď','é','ě','ë','í','ň','ń','ó','ŕ','ř','ť','ú','ů','ý','ź','č','ć','ž','š','đ','ş','ı','ğ','ü','ö','ç'),
4606 + array('a','a','d','e','e','e','i','n','n','o','r','r','t','u','u','y','z','c','c','z','s','d','s','i','g','u','o','c'), $str);
4607 +
4608 + // For french
4609 + $str = str_replace(array('â','é','è','û','ê', 'à','Â','ç','ï','î','ä','î'),
4610 + array('a','e','e','u','e', 'a','c','c','i','î','a','î'), $str);
4611 +
4612 + $str = wp_strip_all_tags(strtolower($str));
4613 +
4614 +
4615 + foreach ($trans as $key => $val)
4616 + {
4617 + $str = preg_replace("#".$key."#", $val, $str);
4618 + }
4619 +
4620 + return trim(stripslashes($str));
4621 + }
4622 +}
4623 +
4624 +
4625 +if (! function_exists('wdk_is_gps'))
4626 +{
4627 + function wdk_is_gps($gps = '')
4628 + {
4629 +
4630 + if(stripos($gps,',') === FALSE) {
4631 + return FALSE;
4632 + }
4633 +
4634 + $gps_coor = explode(',', $gps);
4635 +
4636 + if(count($gps_coor) != 2)
4637 + {
4638 + return FALSE;
4639 + }
4640 +
4641 + if(!is_numeric($gps_coor[0]) || !is_numeric($gps_coor[1]))
4642 + {
4643 + return FALSE;
4644 + }
4645 +
4646 + if($gps_coor[0] < -90 || $gps_coor[0] > 90 || $gps_coor[1] < -180 || $gps_coor[1] > 180)
4647 + {
4648 + return FALSE;
4649 + }
4650 +
4651 + return TRUE;
4652 + }
4653 +}
4654 +
4655 +if ( ! function_exists('is_wdk_is_useremail_exists'))
4656 +{
4657 + function is_wdk_is_useremail_exists($param)
4658 + {
4659 +
4660 + if(null == username_exists( $param ) && !email_exists($param)) {
4661 + return true;
4662 + }
4663 +
4664 + return false;
4665 + }
4666 +}
4667 +
4668 +
4669 +/*
4670 + Validation is natural integer
4671 +*/
4672 +if ( ! function_exists('is_wdk_is_natural'))
4673 +{
4674 + function is_wdk_is_natural($param)
4675 + {
4676 +
4677 + if (is_intval($param) && stripos($param, '.') === FALSE && stripos($param, ',') === FALSE) {
4678 + return true;
4679 + }
4680 +
4681 + return false;
4682 + }
4683 +}
4684 +
4685 +
4686 +/**
4687 + * Check is listing preview page exits
4688 + *
4689 + * @return bool
4690 +*/
4691 +if ( ! function_exists('wdk_is_listing_page_enabled'))
4692 +{
4693 + function wdk_is_listing_page_enabled ()
4694 + {
4695 +
4696 + if(get_option('wdk_listing_page') && get_post_status(get_option('wdk_listing_page')) =='publish') {
4697 + return true;
4698 + }
4699 +
4700 + return false;
4701 + }
4702 +}
4703 +
4704 +
4705 +/**
4706 + * Check is listing preview page exits
4707 + *
4708 + * @return bool
4709 +*/
4710 +if ( ! function_exists('replace_smart_data'))
4711 +{
4712 + function replace_smart_data($output = '', $replace_data = array()) {
4713 + // Match all occurrences of the pattern
4714 + if (preg_match_all('/\{([^}]+)\}/', $output, $matches)) {
4715 + foreach ($matches[1] as $key => $value) {
4716 + foreach ($replace_data as $replace_key => $replace_value) {
4717 + $output = str_replace('{'.$replace_key.'}', $replace_value, $output);
4718 + }
4719 + }
4720 + }
4721 + return $output;
4722 + }
4723 +}
4724 +
4725 +if ( ! function_exists('wdk_generate_missing_image_sizes'))
4726 +{
4727 + /**
4728 + * Wdk_generate_missing_image_sizes and update meta
4729 + * @param int $attachment_id of iamge
4730 + * @param string $size_name size of image based on wp intermediate_size
4731 + *
4732 + * @return bool
4733 + */
4734 + function wdk_generate_missing_image_sizes($attachment_id, $size_name = '') {
4735 + if(empty($size_name) || $size_name == 'full' || !get_option( "{$size_name}_size_w" )) {
4736 + return true;
4737 + }
4738 +
4739 + // Check if the attachment is an image
4740 + if (!wp_attachment_is_image($attachment_id)) {
4741 + return false;
4742 + }
4743 +
4744 + $file = get_attached_file( $attachment_id );
4745 + require_once(ABSPATH . "wp-admin" . '/includes/image.php');
4746 + $metadata = wp_generate_attachment_metadata($attachment_id, $file);
4747 + if ( ! isset( $metadata['sizes'][ $size_name ] ) ) {
4748 + // Generate the missing image size
4749 + $resized = image_make_intermediate_size( $file, get_option( "{$size_name}_size_w" ), get_option( "{$size_name}_size_h" ), get_option( "{$size_name}_crop" ) );
4750 +
4751 + // If the resizing was successful, add it to the metadata
4752 + if ( $resized ) {
4753 + $metadata['sizes'][ $size_name ] = $resized;
4754 + wp_update_attachment_metadata( $attachment_id, $metadata );
4755 + }
4756 + }
4757 + return true;
4758 + }
4759 +}
4760 +
4761 +if (!function_exists('wdk_get_languages')) {
4762 +
4763 + function wdk_get_languages($lang_code_id = null)
4764 + {
4765 + $lang_pattern = ['title' => '', 'lang_code' => '', 'id' => '', 'icon' => '', 'url' => ''];
4766 + $languages = [];
4767 +
4768 + // [qTranslate X]
4769 + if (function_exists('qtranxf_getSortedLanguages')) {
4770 + global $q_config;
4771 +
4772 + if (empty($q_config)) {
4773 + // Initialize qTranslate X language settings if needed
4774 + // qtranxf_init_language();
4775 + }
4776 +
4777 + $all_langs = qtranxf_getSortedLanguages();
4778 + if (count($all_langs) > 0) {
4779 + foreach ($all_langs as $key => $lang_code) {
4780 + $languages[$key + 1] = array_merge(
4781 + $lang_pattern,
4782 + [
4783 + 'title' => $q_config['language_name'][$lang_code],
4784 + 'lang_code' => $lang_code,
4785 + 'id' => $key + 1,
4786 + 'icon' => '',
4787 + 'url' => wdk_get_language_url($lang_code),
4788 + ]
4789 + );
4790 + }
4791 + }
4792 + }
4793 + // [/qTranslate X]
4794 +
4795 + // [WPML]
4796 + if (function_exists('icl_get_languages')) {
4797 + $wpml_langs = icl_get_languages('orderby=KEY&order=DIR&link_empty_to=str');
4798 + $k = 1;
4799 + foreach ($wpml_langs as $key => $lang_data) {
4800 + $languages[$k] = array_merge(
4801 + $lang_pattern,
4802 + [
4803 + 'title' => (!empty($lang_data['translated_name'])) ? $lang_data['translated_name'] : $lang_data['native_name'],
4804 + 'lang_code' => $lang_data['language_code'],
4805 + 'id' => $k,
4806 + 'icon' => (!empty($lang_data['country_flag_url'])) ? $lang_data['country_flag_url'] : WPDIRECTORYKIT_URL.'public/img/flags/'.$lang_data['language_code'].'.png',
4807 + 'url' => wdk_get_language_url($lang_data['language_code']),
4808 + ]
4809 + );
4810 + $k++;
4811 + }
4812 + } elseif (has_filter('wpml_active_languages')) {
4813 + $wpml_langs = apply_filters('wpml_active_languages', null) ?: get_query_var('lang', 'all');
4814 + if (is_array($wpml_langs)) {
4815 + foreach ($wpml_langs as $lang_data) {
4816 + if (!isset($lang_data['code']) && isset($lang_data['language_code'])) {
4817 + $lang_data['code'] = $lang_data['language_code'];
4818 + }
4819 + if (empty($lang_data['translated_name']) && !empty($lang_data['native_name'])) {
4820 + $lang_data['translated_name'] = $lang_data['native_name'];
4821 + }
4822 + $languages[$lang_data['id']] = array_merge(
4823 + $lang_pattern,
4824 + [
4825 + 'title' => (!empty($lang_data['translated_name'])) ? $lang_data['translated_name'] : $lang_data['native_name'],
4826 + 'lang_code' => $lang_data['code'],
4827 + 'id' => $lang_data['id'],
4828 + 'icon' => (!empty($lang_data['country_flag_url'])) ? $lang_data['country_flag_url'] : WPDIRECTORYKIT_URL.'public/img/flags/'.$lang_data['language_code'].'.png',
4829 + 'url' => wdk_get_language_url($lang_data['code']),
4830 + ]
4831 + );
4832 + }
4833 + }
4834 + }
4835 + // [/WPML]
4836 +
4837 + // [TranslatePress]
4838 + if (function_exists('trp_custom_language_switcher')) {
4839 + $k = 1;
4840 + foreach (trp_custom_language_switcher() as $lang_data) {
4841 + $languages[$k++] = array_merge(
4842 + $lang_pattern,
4843 + [
4844 + 'title' => $lang_data['language_name'],
4845 + 'lang_code' => $lang_data['language_code'],
4846 + 'id' => $k,
4847 + 'icon' => $lang_data['flag_link'],
4848 + 'url' => $lang_data['current_page_url'],
4849 + ]
4850 + );
4851 + }
4852 + }
4853 + // [/TranslatePress]
4854 +
4855 + if (!empty($lang_code_id)) {
4856 + foreach ($languages as $lang) {
4857 + if (($lang['id'] == $lang_code_id) || ($lang['lang_code'] == $lang_code_id)) {
4858 + return $lang['id'] == $lang_code_id ? $lang['lang_code'] : $lang['id'];
4859 + }
4860 + }
4861 + return false;
4862 + }
4863 +
4864 + return $languages;
4865 + }
4866 +}
4867 +
4868 +if (!function_exists('wdk_default_language')) {
4869 + function wdk_default_language()
4870 + {
4871 + // [qTranslate X]
4872 + if (function_exists('qtranxf_getLanguageDefault')) {
4873 + return qtranxf_getLanguageDefault();
4874 + }
4875 + // [/qTranslate X]
4876 +
4877 + // [WPML]
4878 + if (function_exists('icl_get_languages')) {
4879 + $wpml_langs = icl_get_languages('orderby=KEY&order=DIR&link_empty_to=str');
4880 + foreach ($wpml_langs as $lang_data) {
4881 + if ($lang_data['major'] == 1) {
4882 + return $lang_data['code'];
4883 + }
4884 + }
4885 + } elseif (has_filter('wpml_default_language')) {
4886 + return apply_filters('wpml_default_language', null);
4887 + }
4888 + // [/WPML]
4889 +
4890 + return 'en';
4891 + }
4892 +}
4893 +
4894 +if (!function_exists('wdk_current_language')) {
4895 + function wdk_current_language()
4896 + {
4897 + if (function_exists('trp_get_languages')) {
4898 + global $TRP_LANGUAGE;
4899 + $trp = TRP_Translate_Press::get_trp_instance();
4900 + $settings = $trp->get_component('settings')->get_settings();
4901 + $translation_languages = $trp->get_component('languages')->get_language_names($settings['publish-languages']);
4902 + if (isset($translation_languages[$TRP_LANGUAGE])) {
4903 + return $translation_languages[$TRP_LANGUAGE];
4904 + }
4905 + }
4906 +
4907 + // [qTranslate X]
4908 + if (function_exists('qtranxf_getLanguage')) {
4909 + return qtranxf_getLanguage();
4910 + }
4911 + // [/qTranslate X]
4912 +
4913 + // [WPML]
4914 + if (function_exists('icl_get_languages')) {
4915 + $wpml_langs = icl_get_languages('orderby=KEY&order=DIR&link_empty_to=str');
4916 + foreach ($wpml_langs as $lang_data) {
4917 + if ($lang_data['active'] == 1) {
4918 + return (!empty($lang_data['native_name'])) ? $lang_data['native_name'] : $lang_data['language_code'];
4919 + }
4920 + }
4921 + } elseif (has_filter('wpml_current_language')) {
4922 + return apply_filters('wpml_current_language', null);
4923 + }
4924 + // [/WPML]
4925 +
4926 + return 'en';
4927 + }
4928 +}
4929 +
4930 +if (!function_exists('wdk_current_language_id')) {
4931 + function wdk_current_language_id()
4932 + {
4933 + $lang_id = wdk_get_languages(wdk_current_language());
4934 + return is_numeric($lang_id) ? $lang_id : wdk_default_language_id();
4935 + }
4936 +}
4937 +
4938 +if (!function_exists('wdk_default_language_id')) {
4939 + function wdk_default_language_id()
4940 + {
4941 + $lang_id = wdk_get_languages(wdk_default_language());
4942 + return is_numeric($lang_id) ? $lang_id : '1';
4943 + }
4944 +}
4945 +
4946 +if (!function_exists('wdk_get_language_name')) {
4947 + function wdk_get_language_name($id_or_code)
4948 + {
4949 + $langs = wdk_get_languages();
4950 + foreach ($langs as $lang) {
4951 + if ($lang['lang_code'] == $id_or_code || $lang['id'] == $id_or_code) {
4952 + return $lang['title'];
4953 + }
4954 + }
4955 + return '';
4956 + }
4957 +}
4958 +
4959 +if (!function_exists('wdk_get_language_url')) {
4960 + function wdk_get_language_url($lang_code)
4961 + {
4962 + // [qTranslate X]
4963 + if (function_exists('qtranxf_convertURL')) {
4964 + return qtranxf_convertURL('', $lang_code, false, true);
4965 + }
4966 + // [/qTranslate X]
4967 +
4968 + // [WPML]
4969 + if (function_exists('icl_get_languages')) {
4970 + $wpml_langs = icl_get_languages('orderby=KEY&order=DIR&link_empty_to=str');
4971 + foreach ($wpml_langs as $lang_data) {
4972 + if ($lang_data['language_code'] == $lang_code) {
4973 + return $lang_data['url'];
4974 + }
4975 + }
4976 + } elseif (has_filter('wpml_active_languages')) {
4977 + $wpml_langs = apply_filters('wpml_active_languages', null);
4978 + foreach ($wpml_langs as $lang_data) {
4979 + if (!isset($lang_data['language_code']) && isset($lang_data['language_code'])) {
4980 + $lang_data['language_code'] = $lang_data['language_code'];
4981 + }
4982 + if (empty($lang_data['translated_name']) && !empty($lang_data['native_name'])) {
4983 + $lang_data['translated_name'] = $lang_data['native_name'];
4984 + }
4985 + $url = wdk_wpml_ls_language_url($lang_data['url'], $lang_data);
4986 + if ($lang_data['language_code'] == $lang_code) {
4987 + return $url;
4988 + }
4989 + }
4990 + }
4991 + // [/WPML]
4992 +
4993 + return '';
4994 + }
4995 +}
4996 +
4997 +function wdk_set_user_default_language($user_id = null)
4998 +{
4999 + if (is_null($user_id)) {
5000 + $user_id = get_current_user_id();
5001 + }
5002 +
5003 + $get_language = get_user_meta($user_id, 'user_language', true);
5004 +
5005 + if (!$get_language && (function_exists('icl_get_languages') || has_filter('wpml_active_languages'))) {
5006 + do_action('wpml_switch_language', $get_language);
5007 + }
5008 +}
5009 +
5010 +function wdk_set_language($lang_code = null)
5011 +{
5012 + if (!is_null($lang_code) && (function_exists('icl_get_languages') || has_filter('wpml_active_languages'))) {
5013 + do_action('wpml_switch_language', $lang_code);
5014 + }
5015 +}
5016 +
5017 +function wdk_wpml_ls_language_url($url, $data)
5018 +{
5019 + global $sitepress;
5020 +
5021 + if (is_object($sitepress)) {
5022 + $sitepress_settings = $sitepress->get_settings();
5023 + }
5024 +
5025 + return $url;
5026 +}
5027 +
5028 +add_filter('wpml_ls_language_url', 'wdk_wpml_ls_language_url', 10, 3);
5029 +
5030 +if (!function_exists('wdk_calculate_nights')) {
5031 + /**
5032 + * Calculate the number of nights between two dates
5033 + *
5034 + * This function takes two date strings as input and calculates the number of nights
5035 + * (i.e., the difference in days) between them. It returns the total number of nights
5036 + * between the provided start and end dates. The date format must be valid for PHP's
5037 + * DateTime class.
5038 + *
5039 + * @param string $start_date The start date in 'Y-m-d' format.
5040 + * @param string $end_date The end date in 'Y-m-d' format.
5041 + * @return int The number of nights (days between the two dates).
5042 + */
5043 + function wdk_calculate_nights($start_date, $end_date) {
5044 +
5045 + /* normalize date */
5046 + $start_date = wdk_normalize_date_db($start_date, 'Y-m-d H:i:s', 'Y-m-d');
5047 + $end_date = wdk_normalize_date_db($end_date, 'Y-m-d H:i:s', 'Y-m-d');
5048 +
5049 + // Create DateTime objects for start and end dates
5050 + $start = new DateTime($start_date);
5051 + $end = new DateTime($end_date);
5052 +
5053 + // Calculate the difference between the two dates
5054 + $difference = $start->diff($end);
5055 +
5056 + // Return the number of nights (difference in days)
5057 + return $difference->days;
5058 + }
5059 +}
5060 +
5061 +if ( ! function_exists('wdk_select_db_field_ajax'))
5062 +{
5063 + /**
5064 + * Return select2 ajax
5065 + *
5066 + * @param string option Option key
5067 + * @return string alt or title
5068 + */
5069 + function wdk_select_db_field_ajax($name = '', $selected = NULL, $empty_value='', $filter_id = '')
5070 + {
5071 + $WMVC = &wdk_get_instance();
5072 +
5073 + static $counter = 0;
5074 + $form = '<select data-ajax="'.esc_url(admin_url('admin-ajax.php')).'" name="'.$name.'" data-id="'.$filter_id.'" data-placeholder="'.$empty_value.'" class="form-control wdk_select2_field_suggestion" id="wdk_select2_field_'.$filter_id.'_'.$counter.'" multiple="">';
5075 + if($selected) {
5076 + if(is_array($selected)) {
5077 + /* where in */
5078 + foreach ($selected as $item) {
5079 + $form .= '<option selected="selected" value="'.esc_attr($item).'">'.esc_html($item).'</option>';
5080 + }
5081 + } elseif(is_string($selected)) {
5082 + $form .= '<option selected="selected" value="'.esc_attr($selected).'">'.esc_html($selected).'</option>';
5083 + }
5084 + } else {
5085 + //$form .= '<option value="" selected="selected">'.esc_html__('Not selected', 'wpdirectorykit').'</option>';
5086 + }
5087 + $form .= '</select>';
5088 +
5089 + //load javascript library
5090 + if($counter==0)
5091 + {
5092 + wp_enqueue_script('select2-select2');
5093 + wp_enqueue_script('wdk-select2');
5094 + wp_enqueue_style('select2-select2');
5095 + }
5096 + ?>
5097 + <?php
5098 + $counter++;
5099 + return $form;
5100 +
5101 + }
5102 +}
5103 +
5104 +if ( ! function_exists('wdk_next_month_payment_day'))
5105 +{
5106 + /**
5107 + * Gets the next payment date one month later, considering the number of days in the next month.
5108 + *
5109 + * @param string $currentDate The current payment date in 'Y-m-d H:i:s' format.
5110 + * @return string|false The next payment date in 'Y-m-d H:i:s' format or false on error.
5111 + */
5112 + function wdk_next_month_payment_day($currentDate, $time = false, $wanted_day = NULL) {
5113 + $nextDate = null;
5114 + $timestamp = strtotime($currentDate);
5115 + $daysInNextMonth = gmdate('t', strtotime('+1 month', strtotime(gmdate('Y-m', $timestamp))));
5116 + $currentDay = (int)gmdate('d', $timestamp);
5117 +
5118 + $timeFormat = $time ? "H:i:s" : "00:00:00";
5119 +
5120 +
5121 + // Determine the wanted day
5122 + if ($wanted_day !== NULL) {
5123 + $wanted_day = (int)gmdate('d', strtotime($wanted_day));
5124 + } else {
5125 + $wanted_day = (int)gmdate('d', $timestamp);
5126 + }
5127 +
5128 + $nextMonth = strtotime('first day of next month', $timestamp);
5129 + $daysInNextMonth = gmdate('t', $nextMonth);
5130 +
5131 + // Adjust for the wanted day
5132 + if ($wanted_day > $daysInNextMonth ||
5133 + (
5134 + get_option('wdk_membership_next_month_calculation_with_last_day')
5135 +
5136 + && (
5137 + $currentDay >= 30 || $currentDay == gmdate('t', $timestamp)
5138 + )
5139 + )
5140 + ) {
5141 + // If the wanted day exceeds the max days of the next month, use the last day of the month
5142 + $nextDate = gmdate("Y-m-{$daysInNextMonth} {$timeFormat}", $nextMonth);
5143 + } else {
5144 + // Otherwise, set the exact wanted day
5145 + $nextDate = gmdate("Y-m-{$wanted_day} {$timeFormat}", $nextMonth);
5146 + }
5147 +
5148 + return ($nextDate) ? $nextDate : false;
5149 + }
5150 +}
5151 +
5152 +if ( ! function_exists('wdk_next_year_payment_day'))
5153 +{
5154 + /**
5155 + * Gets the next payment date one year later, considering the number of days in the next month.
5156 + *
5157 + * @param string $currentDate The current payment date in 'Y-m-d H:i:s' format.
5158 + * @return string|false The next payment date in 'Y-m-d H:i:s' format or false on error.
5159 + */
5160 +
5161 + function wdk_next_year_payment_day($currentDate, $time = false) {
5162 + $nextDate = null;
5163 + $timestamp = strtotime($currentDate);
5164 + $nextYearTimestamp = strtotime('+1 year', strtotime(gmdate('Y-m', $timestamp)));
5165 + $daysInNextMonth = gmdate('t', $nextYearTimestamp);
5166 + $currentDay = gmdate('j', $timestamp);
5167 + $timeFormat = "00:00:00";
5168 + if($time) {
5169 + $timeFormat = "H:i:s";
5170 + }
5171 + if ($currentDay > $daysInNextMonth) {
5172 + $nextDate = gmdate('Y-m-d '.$timeFormat, strtotime('last day of this month', $nextYearTimestamp));
5173 + } else {
5174 + $nextDate = gmdate('Y-m-d '.$timeFormat, strtotime('+1 year', $timestamp));
5175 + }
5176 +
5177 + return ($nextDate) ? $nextDate : false;
5178 + }
5179 +}
5180 +
5181 +if ( ! function_exists('wdk_generate_auto_login_link'))
5182 +{
5183 + function wdk_generate_auto_login_link( $user_id = null ) {
5184 + $token = substr(md5($user_id.NONCE_KEY.'wpdirectorykit'),0,10);
5185 +
5186 + $login_url = site_url( "/?auto-login=1&user_id={$user_id}&token={$token}" );
5187 + return $login_url;
5188 + }
5189 +}
5190 +
5191 +if ( ! function_exists('wdk_get_user_subscription_id'))
5192 +{
5193 + function wdk_get_user_subscription_id($user_id = null) {
5194 + global $Winter_MVC_wdk_membership;
5195 + if(!isset($Winter_MVC_wdk_membership)) {
5196 + return false;
5197 + }
5198 + $Winter_MVC_wdk_membership->model('subscription_user_m');
5199 + $user_subscription = $Winter_MVC_wdk_membership->subscription_user_m->get_by(array('user_id'=>$user_id), TRUE);
5200 + return wmvc_show_data('subscription_id', $user_subscription, '', TRUE, TRUE);
5201 + }
5202 +}
5203 +
5204 +if ( ! function_exists('is_wdk_related_validation'))
5205 + /**
5206 + * IS WDK related validation
5207 + *
5208 + * @return bool true if exists dash
5209 + */
5210 + {
5211 + function is_wdk_related_validation($param)
5212 + {
5213 +
5214 + if(empty($param)) {
5215 + return TRUE;
5216 + }
5217 +
5218 + $listing_id = (!empty($_GET['id'])) ? intval(sanitize_text_field($_GET['id'])) : null;
5219 +
5220 +
5221 + global $Winter_MVC_WDK;
5222 + $Winter_MVC_WDK->model('listing_m');
5223 +
5224 + $Winter_MVC_WDK->db->select('post_id');
5225 + $Winter_MVC_WDK->db->where(array(
5226 + '(post_id IN ('.esc_sql(sanitize_text_field($param)).'))' => NULL,
5227 + '((`listing_related_ids` IS NOT NULL AND `listing_related_ids` !="") OR (`listing_parent_post_id` IS NOT NULL AND `listing_parent_post_id` !=0))' => NULL,
5228 + ));
5229 +
5230 + if($listing_id) {
5231 + $Winter_MVC_WDK->db->where(array(
5232 + '`listing_parent_post_id` !='.esc_sql($listing_id).'' => NULL,
5233 + ));
5234 + }
5235 +
5236 + $Winter_MVC_WDK->db->from($Winter_MVC_WDK->listing_m->_table_name);
5237 + $Winter_MVC_WDK->db->limit(5);
5238 +
5239 + $Winter_MVC_WDK->db->get();
5240 + if ($Winter_MVC_WDK->db->num_rows() > 0) {
5241 + $db_results = $Winter_MVC_WDK->db->results();
5242 + } else {
5243 + $db_results = null;
5244 + }
5245 +
5246 + if (!empty($db_results)) {
5247 + return false;
5248 + }
5249 +
5250 + return TRUE;
5251 + }
5252 + }
5253 +
5254 + /**
5255 + * Renders an Elementor template by its title or post ID.
5256 + *
5257 + * Attempts to find and render an Elementor layout/template using the post title or post ID.
5258 + * If the post is found and public, its rendered Elementor content is returned, otherwise post content fallback or error.
5259 + *
5260 + * @since 1.0.0
5261 + * @param string|int $title The title (or ID if $id=true) of the Elementor template to render.
5262 + * @param bool $id Optional. If true, $title is treated as a post ID. If false (default), searches by title.
5263 + * @return string|false Rendered template HTML on success, public/content fallback, or error message/false on failure.
5264 + */
5265 + function wdk_render_elementor_template( $title, $id = false ) {
5266 + // Initialize variables.
5267 + $layout_id = null;
5268 + $template_content = '';
5269 +
5270 + // Determine the layout/post ID.
5271 + if ( ! $id ) {
5272 + // Search by post title. Returns WP_Post/object or null.
5273 + $found_post = wdk_page_by_title( $title, OBJECT, ['elementor_library','page'] );
5274 + $layout_id = $found_post ? $found_post->ID : null;
5275 +
5276 + // Support WPML translation if present.
5277 + // The filter may change $layout_id to a translated post's ID if needed.
5278 + $layout_id = apply_filters( 'wpml_object_id', $layout_id, 'elementor_library', true );
5279 + } else {
5280 + // ID provided directly.
5281 + $layout_id = intval($title);
5282 + }
5283 +
5284 + // Early return if no valid layout found.
5285 + if ( empty( $layout_id ) ) {
5286 + return false;
5287 + }
5288 +
5289 + // Get post object (Elementor template or WP Page).
5290 + $post_data = get_post( $layout_id );
5291 +
5292 +
5293 + // Validate post: should exist, be published, and not password protected.
5294 + if ( ! $post_data || $post_data->post_status !== 'publish' || post_password_required( $post_data ) ) {
5295 + return esc_html__( 'Layout is not public', 'wpdirectorykit' );
5296 + }
5297 +
5298 + // Render content depending on post type.
5299 + if (
5300 + ( isset($post_data->post_type) && $post_data->post_type === 'elementor_library' ) ||
5301 + ( isset($post_data->post_type) && $post_data->post_type === 'page' )
5302 + ) {
5303 + // Try to render using Elementor's frontend builder.
5304 + if ( class_exists('\Elementor\Plugin') && method_exists('\Elementor\Plugin', 'instance') ) {
5305 + $elementor_instance = \Elementor\Plugin::instance();
5306 + $content = $elementor_instance->frontend->get_builder_content_for_display( $layout_id );
5307 + $template_content = ! empty( $content ) ? $content : $post_data->post_content;
5308 + } else {
5309 + // Elementor not present; fallback to post content.
5310 + $template_content = $post_data->post_content;
5311 + }
5312 + } else {
5313 + // Non-Elementor post types, fallback to post content.
5314 + $template_content = $post_data->post_content;
5315 + }
5316 +
5317 + /**
5318 + * Filter: Allows modification of the rendered Elementor template content before returning.
5319 + *
5320 + * @param string $template_content The rendered template content.
5321 + * @param int $layout_id The ID of the layout/template.
5322 + * @param WP_Post $post_data The WP_Post object of the layout/template.
5323 + */
5324 + return apply_filters( 'wdk_render_elementor_template_output', $template_content, $layout_id, $post_data );
5325 + }
5326 +
5327 + if(!function_exists('wdk_esc_sql')) {
5328 + function wdk_esc_sql($value = '', $strict = false) {
5329 + $patterns = [
5330 + '/\bselect\b/i',
5331 + '/\binsert\b/i',
5332 + '/\bupdate\b/i',
5333 + '/\bdelete\b/i',
5334 + '/\bunion\b/i',
5335 + '/\bextractvalue\b/i',
5336 + '/\bversion\s*\(\)/i',
5337 + '/\bdatabase\s*\(\)/i',
5338 + '/\bconcat\s*\(/i',
5339 + '/\bdrop\b/i',
5340 + '/\bsleep\s*\(/i',
5341 + '/\bbenchmark\s*\(/i',
5342 + '/--/',
5343 + '/#/i',
5344 + '/\/\*/',
5345 +
5346 + // EXTRA BLOCK YOU REQUESTED
5347 + '/\\\\/', // remove backslash \
5348 + '/\|/', // remove |
5349 + '/%/', // remove %
5350 + ];
5351 +
5352 + // If strict mode is enabled, block additional patterns
5353 + if ($strict === true) {
5354 + $strict_patterns = [
5355 + '/\bif\b\s*\(/i',
5356 + '/\bord\b/i',
5357 + '/\bsubstr\s*\(/i',
5358 + '/\bschema\s*\(\)/i',
5359 + '/@@version/i',
5360 + ];
5361 + $patterns = array_merge($patterns, $strict_patterns);
5362 + }
5363 +
5364 + return esc_sql(trim(preg_replace($patterns, '', sanitize_text_field($value))));
5365 + }
5366 + }
5367 +
5368 + if(!function_exists('wdk_esc_sql_order_by')) {
5369 + function wdk_esc_sql_order_by($value = '', array $allowed_fields = [])
5370 + {
5371 + if (empty($value) || empty($allowed_fields)) {
5372 + return '';
5373 + }
5374 + $result = [];
5375 + foreach (explode(',', $value) as $part) {
5376 + $part = trim(sanitize_text_field($part));
5377 +
5378 + $direction = 'ASC';
5379 + if (preg_match('/\s+(ASC|DESC)$/i', $part, $match)) {
5380 + $direction = strtoupper($match[1]);
5381 + $part = trim(substr($part, 0, -strlen($match[0])));
5382 + }
5383 +
5384 + $part = sanitize_key($part);
5385 +
5386 + if (in_array($part, $allowed_fields, true)) {
5387 + $result[] = $part . ' ' . $direction;
5388 + }
5389 + }
5390 +
5391 + return implode(', ', $result);
5392 + }
5393 + }
5394 +
5395 + if(!function_exists('wdk_listing_seo_title')) {
5396 + function wdk_listing_seo_title () {
5397 + static $cached_seo_title = null;
5398 + if ($cached_seo_title !== null) {
5399 + return $cached_seo_title;
5400 + }
5401 +
5402 + $seo_title ='';
5403 + global $wp_query;
5404 + $wdk_listing_id = $wp_query->post->ID;
5405 + if(wdk_get_option('wdk_seo_listing_title')) {
5406 + global $Winter_MVC_WDK;
5407 + $Winter_MVC_WDK->model('field_m');
5408 + $Winter_MVC_WDK->load_helper('listing');
5409 +
5410 + $seo_template = wdk_get_option('wdk_seo_listing_title');
5411 +
5412 + $matches = [];
5413 + preg_match_all('/{(?:field_)?([^}]+)}/', $seo_template, $matches);
5414 + $fields_in_template = isset($matches[1]) ? $matches[1] : [];
5415 +
5416 + $fields_values = [];
5417 +
5418 + foreach ($fields_in_template as $field_id) {
5419 + $key_id = '{field_' . $field_id . '}';
5420 + if($field_id == 'category') {
5421 + $field_id = 'category_title';
5422 + }
5423 + if($field_id == 'location') {
5424 + $field_id = 'location_title';
5425 + }
5426 + // Try to get value for field_id for this listing
5427 + $fields_values[$key_id] = wdk_field_value($field_id, $wdk_listing_id);
5428 + }
5429 + // Replace the fields in template with real values
5430 + $seo_title = strtr($seo_template, $fields_values);
5431 + }
5432 +
5433 + $cached_seo_title = $seo_title;
5434 + return $seo_title;
5435 + }
5436 + }
5437 +
5438 +
5439 + if ( ! function_exists('wdk_filter_viber_phone'))
5440 + {
5441 + // Validation phone for viber
5442 + /**
5443 + * @param string $value phone in string
5444 + * @return strings +xxx
5445 + */
5446 + function wdk_filter_viber_phone($value = '') {
5447 + $value = str_replace(array(' ','-','(',')'),'',$value);
5448 + return (strpos($value, '+') !== 0) ? '+' . $value : $value;
5449 + }
5450 + }
5451 +
5452 +?>