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 +1581 -182 1.2.9 → 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
@@ -358,8 +360,9 @@
358 360 }
359 361 }
360 362
361 363 if($print){
364 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
362 365 echo $output;
363 366 return FALSE;
364 367 }
365 368
@@ -390,9 +393,10 @@
390 393 $wdk_bookings_joinded = false;
391 394 static $available_fields_listings = NULL;
392 395 static $available_fields_static = array();
393 396 static $list_fields_static = NULL;
394 -
397 + $fields_type = array();
398 +
395 399 /* add if missing columns */
396 400 if(!in_array('post_id', $columns)) {
397 401 $columns[] = $Winter_MVC_WDK->db->prefix.'wdk_listings.post_id';
398 402 }
@@ -408,10 +412,10 @@
408 412
409 413 if(isset($custom_parameters['order_by'])) {
410 414
411 415 if(isset($_GET_clone['order_by']) && !empty($_GET_clone['order_by'])) {
412 - $_GET_clone['order_by'] = $custom_parameters['order_by'].', '.$_GET_clone['order_by'];
413 - } 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'])) {
414 418 $_GET_clone['order_by'] = $custom_parameters['order_by'];
415 419 }
416 420
417 421 unset($custom_parameters['order_by']);
@@ -426,12 +430,12 @@
426 430 $WMVC->model('listingfield_m');
427 431
428 432 $smart_search = '';
429 433 if(isset($_GET_clone['search']))
430 - $smart_search = sanitize_text_field($_GET_clone['search']);
434 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['search']));
431 435
432 436 if(isset($_GET_clone['field_search']))
433 - $smart_search = sanitize_text_field($_GET_clone['field_search']);
437 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['field_search']));
434 438
435 439 if(!isset($available_fields_static[$model_name]))
436 440 {
437 441 $available_fields = $WMVC->$model_name->get_available_fields();
@@ -464,8 +468,10 @@
464 468 foreach($list_fields as $field_data) {
465 469
466 470 $field_id = wmvc_show_data('idfield',$field_data);
467 471 $field_type = wmvc_show_data('field_type',$field_data);
472 +
473 + $fields_type[$field_id] = $field_type;
468 474 $column_name ='field_'.$field_id.'_'.$field_type;
469 475 if(!isset($available_fields_listings[$column_name])) continue;
470 476
471 477 if(isset($_GET_clone['field_'.$field_id])) {
@@ -483,9 +489,9 @@
483 489 if(isset($_GET_clone['field_'.$field_id.'_min'])) {
484 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);
485 491 }
486 492 if(isset($_GET_clone['field_'.$field_id.'_exactly'])) {
487 - $_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']);
488 494 }
489 495
490 496 $columns[] = $column_name;
491 497 $columns[] = $column_name.'_max';
@@ -540,13 +546,34 @@
540 546 }
541 547
542 548 if(isset($_GET_clone['field_post_id'])) {
543 549 $column_name ='ID_exactly';
544 - $_GET_clone[$column_name] = intval($_GET_clone['field_post_id']);
550 + $_GET_clone[$column_name] = sanitize_text_field($_GET_clone['field_post_id']);
545 551 $columns[] = $column_name;
546 552 $external_columns[] = $column_name;
547 553 }
548 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 +
549 576 if (function_exists('run_wdk_bookings') && isset($_GET_clone['field_booking_date_from'])) {
550 577 $column_name ='field_booking_date_from';
551 578 $_GET_clone[$column_name] = $_GET_clone['field_booking_date_from'];
552 579 $columns[] = $column_name;
@@ -566,8 +593,29 @@
566 593 $columns[] = $column_name;
567 594 $external_columns[] = $column_name;
568 595 }
569 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 +
570 618 //$table_name = substr($model_name, 0, -2);
571 619 $columns_original = array();
572 620 foreach($columns as $key=>$val)
573 621 {
@@ -595,8 +643,10 @@
595 643 {
596 644 unset($_GET_clone['search']);
597 645 unset($_GET_clone['field_search']);
598 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 +
599 649 // For quick/smart search
600 650 if(wmvc_count($columns) > 0 && !empty($smart_search))
601 651 {
602 652 $gen_q = '';
@@ -654,8 +704,13 @@
654 704 /* location / categories */
655 705 if(!is_intval($smart_search)) {
656 706 $gen_q.="location_title LIKE '%$smart_search%' OR ";
657 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 +
658 713 }
659 714 /* get address and gps */
660 715 if(strlen($smart_search) > 5) {
661 716 $coordinates_center = wdk_get_gps($smart_search);
@@ -711,9 +766,9 @@
711 766
712 767 if(!empty($gen_q))
713 768 $WMVC->db->where("($gen_q)");
714 769 }
715 -
770 +
716 771 // For column search
717 772 if(isset($_GET_clone))
718 773 {
719 774 $gen_q = '';
@@ -721,9 +776,9 @@
721 776 {
722 777 if(!empty($val) && in_array($key, $columns))
723 778 {
724 779 $col_name = $key;
725 -
780 +
726 781 $val = esc_sql($val);
727 782 //if(isset($key))
728 783 // $col_name = $key;
729 784
@@ -728,43 +783,31 @@
728 783 // $col_name = $key;
729 784
730 785 if(strpos($key, 'skip') !== FALSE) continue;
731 786
732 - if(defined( 'WP_DEBUG' ) && WP_DEBUG)
733 - if(function_exists('pll_current_language'))
734 - {
735 - $lang_term_id = pll_current_language('term_id');
736 -
737 - if(is_numeric($lang_term_id))
738 - {
739 - $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);
740 - $WMVC->db->where("({$WMVC->db->prefix}term_relationships.term_taxonomy_id = $lang_term_id)");
741 - }
742 - }
743 -
744 787 if($key == 'field_booking_guest')
745 788 {
746 789 if(!$wdk_bookings_joinded){
747 - $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');
748 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
749 - $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');
750 793 $wdk_bookings_joinded = true;
751 794 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
752 - $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');
753 796 }
754 797
755 - $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 ";
756 799
757 800 }
758 801 elseif($key == 'field_booking_date_from')
759 802 {
760 803 if(!$wdk_bookings_joinded){
761 - $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');
762 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
763 - $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');
764 807 $wdk_bookings_joinded = true;
765 808 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
766 - $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');
767 810 }
768 811
769 812 if(wdk_is_date($val))
770 813 {
@@ -782,9 +825,9 @@
782 825 if(!get_option('wdk_bookings_is_hours_enabled')) {
783 826 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from'], 'Y-m-d H:i:s', 'Y-m-d');
784 827 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to'], 'Y-m-d H:i:s', 'Y-m-d');
785 828
786 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
829 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
787 830 SELECT post_id
788 831 FROM ".$WMVC->db->prefix."wdk_booking_reservation
789 832 WHERE
790 833 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -797,9 +840,9 @@
797 840 } else {
798 841 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from']);
799 842 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to']);
800 843
801 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
844 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
802 845 SELECT post_id
803 846 FROM ".$WMVC->db->prefix."wdk_booking_reservation
804 847 WHERE
805 848 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -814,13 +857,13 @@
814 857 }
815 858 elseif($key == 'field_booking_date_to')
816 859 {
817 860 if(!$wdk_bookings_joinded){
818 - $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');
819 - $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');
820 863 $wdk_bookings_joinded = true;
821 864 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
822 - $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');
823 866 }
824 867
825 868 if(wdk_is_date($val))
826 869 {
@@ -836,9 +879,33 @@
836 879 }
837 880 elseif(substr($key, -8) == '_exactly')
838 881 {
839 882 $col_name = substr($key, 0, -8);
840 - $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 + }
841 908 }
842 909 elseif(substr($key, -4) == '_max')
843 910 {
844 911 $col_name = substr($key, 0, -4);
@@ -857,9 +924,9 @@
857 924 }
858 925 else if(substr($key, -4) == '_min')
859 926 {
860 927 $col_name = substr($key, 0, -4);
861 -
928 +
862 929 if(strpos($key, 'NUMBER') !== FALSE) {
863 930 $gen_q.=$col_name." >= ".intval($val)." AND ";
864 931 } else if(strpos($key, 'DATE') !== FALSE) {
865 932 if(wdk_is_date($val))
@@ -928,9 +995,9 @@
928 995 }
929 996
930 997 if(is_array($val)) {
931 998
932 - $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');
933 1000 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
934 1001 $sql_search = '';
935 1002 foreach ($val as $v) {
936 1003 if(empty($v)) continue;
@@ -945,9 +1012,9 @@
945 1012 if(!empty($sql_search))
946 1013 $gen_q.=" ( ".$sql_search." ) AND ";
947 1014
948 1015 } elseif(is_string($val) && !empty($val)) {
949 - $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');
950 1017 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
951 1018 $sql_search =" ".$WMVC->listing_m->_table_name.".`user_id_editor` = ".intval($val)." OR `".$WMVC->db->prefix."wdk_listings_users`.`user_id` = ".intval($val)." ";
952 1019 $gen_q.=" ( ".$sql_search." ) AND ";
953 1020 }
@@ -1104,10 +1171,15 @@
1104 1171
1105 1172 if(!empty($sql_search))
1106 1173 $gen_q.=" ( ".$sql_search." ) AND ";
1107 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 + }
1108 1181 }
1109 -
1110 1182 }
1111 1183
1112 1184 $gen_q = substr($gen_q, 0, -5);
1113 1185
@@ -1113,14 +1185,120 @@
1113 1185
1114 1186 if(!empty($gen_q))
1115 1187 $WMVC->db->where("($gen_q)");
1116 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]
1117 1215
1118 1216 // order
1119 - if(isset($_GET_clone['order_by']))
1120 - {
1121 - $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_listings.post_id', $_GET_clone['order_by']);
1122 - $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 +
1123 1301 }
1124 1302
1125 1303 }
1126 1304 }
@@ -1137,9 +1315,9 @@
1137 1315
1138 1316 if(isset($custom_parameters['order_by'])) {
1139 1317
1140 1318 if(isset($_GET_clone['order_by']) && !empty($_GET_clone['order_by'])) {
1141 - $_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']);
1142 1320 } else {
1143 1321 $_GET_clone['order_by'] = $custom_parameters['order_by'];
1144 1322 }
1145 1323
@@ -1153,9 +1331,9 @@
1153 1331 $WMVC->model($model_name);
1154 1332
1155 1333 $smart_search = '';
1156 1334 if(isset($_GET_clone['profile_search']))
1157 - $smart_search = sanitize_text_field($_GET_clone['profile_search']);
1335 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['profile_search']));
1158 1336
1159 1337 $available_fields = array('user_login','user_nicename','user_email','user_url','display_name');
1160 1338
1161 1339 if(isset($_GET_clone['is_activated'])){
@@ -1322,9 +1500,9 @@
1322 1500 // order
1323 1501 if(isset($_GET_clone['order_by']))
1324 1502 {
1325 1503 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_favorite.post_id', $_GET_clone['order_by']);
1326 - $WMVC->db->order_by($_GET_clone['order_by']);
1504 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by'])));
1327 1505 }
1328 1506
1329 1507 }
1330 1508 }
@@ -1340,9 +1518,9 @@
1340 1518 //$WMVC->model('listing_m');
1341 1519
1342 1520 $smart_search = '';
1343 1521 if(isset($_GET_clone['search']))
1344 - $smart_search = sanitize_text_field($_GET_clone['search']);
1522 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['search']));
1345 1523
1346 1524 $available_fields = $WMVC->$model_name->get_available_fields();
1347 1525
1348 1526 /* Пet column names from wdk_package and add to allow search +
@@ -1453,9 +1631,9 @@
1453 1631 $detect_date = strtotime($gen_search);
1454 1632
1455 1633 if(wdk_payments_is_date($val) && $detect_date > 1000)
1456 1634 {
1457 - $gen_search = date('Y-m-d H:i:s', $detect_date);
1635 + $gen_search = gmdate('Y-m-d H:i:s', $detect_date);
1458 1636 $gen_q.=$col_name." > '".$gen_search."' AND ";
1459 1637 }
1460 1638 else
1461 1639 {
@@ -1493,9 +1671,9 @@
1493 1671 // order
1494 1672 if(isset($_GET_clone['order_by']))
1495 1673 {
1496 1674 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_messages.post_id', $_GET_clone['order_by']);
1497 - $WMVC->db->order_by($_GET_clone['order_by']);
1675 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by']), true));
1498 1676 }
1499 1677
1500 1678 }
1501 1679 }
@@ -1502,9 +1680,9 @@
1502 1680
1503 1681 function wdk_date() {
1504 1682 $date_format = get_option('date_format');
1505 1683 $time_format = get_option('time_format');
1506 - $date = date("{$date_format} {$time_format}", current_time('timestamp'));
1684 + $date = gmdate("{$date_format} {$time_format}", current_time('timestamp'));
1507 1685 return $date;
1508 1686 }
1509 1687
1510 1688 if(!function_exists('wdk_placeholder_image_src')) {
@@ -1528,18 +1706,20 @@
1528 1706
1529 1707 if(isset($_GET[$page_var]))
1530 1708 $current_page = intval(wmvc_xss_clean($_GET[$page_var]));
1531 1709
1532 - if(!isset($texts['previous_page']))$texts['previous_page'] = 'Previous page';
1533 - 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');
1534 1712 if(!isset($texts['first_page']))$texts['first_page'] = '';
1535 1713 if(!isset($texts['last_page']))$texts['last_page'] = '';
1536 - if(!isset($texts['items']))$texts['items'] = 'items';
1714 + if(!isset($texts['items']))$texts['items'] = esc_html__('items', 'wpdirectorykit');
1537 1715
1538 1716 if(empty($current_page))$current_page = 1;
1539 1717
1540 1718 // get url
1541 - $url = strtok($_SERVER["REQUEST_URI"], '?');
1719 + $url = strtok(wdk_server_current_url(), '?');
1720 +
1721 +
1542 1722 $qs_parameters = wmvc_xss_clean( $_GET );
1543 1723 unset($qs_parameters[$page_var]);
1544 1724 $qs_part = http_build_query($qs_parameters);
1545 1725 $url = wdk_url_suffix($url, $qs_part);
@@ -1562,16 +1742,16 @@
1562 1742
1563 1743 $output .= '<div class="nav-links">';
1564 1744
1565 1745 if($enable_latest_first && $current_page-1 > 0)
1566 - $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>';
1567 1747
1568 1748 if ($current_page-1 > 0) {
1569 1749
1570 - $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>';
1571 1751 } elseif($enable_compact)
1572 1752 {
1573 - $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>';
1574 1754 }
1575 1755
1576 1756 if (!$enable_compact) {
1577 1757 for ($i = 1 ; $i <= $total_pages; $i++) {
@@ -1579,9 +1759,9 @@
1579 1759 if(($current_page-$limit_items) <= $i && ($current_page+$limit_items) >= $i) {
1580 1760 if (($current_page == $i)) {
1581 1761 $output.= '<span aria-current="page" class="page-numbers current">'.$i.'</span>';
1582 1762 } else {
1583 - $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>';
1584 1764 }
1585 1765 }
1586 1766 }
1587 1767 } else {
@@ -1589,17 +1769,17 @@
1589 1769 }
1590 1770
1591 1771 if($current_page+1 <= $total_pages)
1592 1772 {
1593 - $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>';
1594 1774 }
1595 1775 elseif($enable_compact)
1596 1776 {
1597 - $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>';
1598 1778 }
1599 1779
1600 1780 if($enable_latest_first && $current_page+1 <= $total_pages)
1601 - $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>';
1602 1782
1603 1783
1604 1784 $output.= '</div>';
1605 1785 $output.= '</nav>';
@@ -1654,22 +1834,27 @@
1654 1834 }
1655 1835
1656 1836 ?>
1657 1837 <div class="wdk-col wdk-col-btns">
1658 - <div class="wdk-field wdk-field-btn">
1838 + <div class="wdk-field wdk-field-btn">
1659 1839 <div class="wdk-field-group wdk-field-group-additional">
1660 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>
1661 - <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' />
1662 1842 </div>
1663 1843 <div class="wdk-field-group wdk-field-group-reset">
1664 - <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>
1665 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;?>
1666 1851 <div class="wdk-field-group wdk-field-group-search">
1667 - <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>
1668 1853
1669 1854 <?php if(function_exists('run_wdk_save_search') && get_option('wdk_save_search_show_on_searchform')):?>
1670 1855 <div class="section-widget-control right">
1671 - <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">
1672 1857 <i class="fas fa-save" aria-hidden="true"></i>
1673 1858 <i class="fa fa-spinner fa-spin fa-ajax-indicator"></i>
1674 1859 </a>
1675 1860 </div>
@@ -1674,8 +1859,9 @@
1674 1859 </a>
1675 1860 </div>
1676 1861 <?php endif;?>
1677 1862 </div>
1863 +
1678 1864 </div>
1679 1865 </div>
1680 1866 <div id='wdk-form-additional' class="wdk-col" style="<?php echo esc_attr($form_closed) ;?>">
1681 1867 <div class="wdk-row">
@@ -1718,9 +1904,9 @@
1718 1904
1719 1905 if(empty($selected))
1720 1906 $selected='';
1721 1907
1722 - $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/>';
1723 1909
1724 1910 $skip_id = '';
1725 1911 //load javascript library
1726 1912 if($counter==0)
@@ -1727,39 +1913,39 @@
1727 1913 {
1728 1914 wp_enqueue_script('wdk-treefield');
1729 1915 wp_enqueue_style('wdk-treefield');
1730 1916 }
1731 - ?>
1732 - <script>
1733 - jQuery(document).ready(function($) {
1734 - $('#wdktreeelem<?php echo esc_js($counter);?>:not(.init)').wdkTreefield({
1735 - 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')) . "',
1736 1922 ajax_param: {
1737 - "page": 'wdk_frontendajax',
1738 - "function": 'treefieldid',
1739 - "action": 'wdk_public_action',
1740 - "table": '<?php echo esc_js($table); ?>',
1741 - "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1742 - "start_id": '<?php if(!empty($filter_ids)) esc_js($selected); else echo ""; ?>',
1743 - "empty_value": '<?php echo esc_js($empty_value); ?>',
1744 - "user_check": '<?php echo esc_js($user_check); ?>',
1745 - "sql_where": '<?php echo esc_js($sql_where); ?>',
1746 - "hide_fields": '<?php echo esc_js($hide_fields); ?>'
1747 - },
1748 - attribute_id: '<?php echo esc_js($attribute_id); ?>',
1749 - language_id: '<?php echo esc_js($language_id); ?>',
1750 - attribute_value: '<?php echo esc_js($column); ?>',
1751 - 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: '',
1752 1939 empty_value: ' - ',
1753 - text_search: '<?php esc_html_e('Search term', 'wpdirectorykit');?>',
1754 - 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') . "',
1755 1942 callback_selected: function(key) {
1756 - $('#wdktreeelem<?php echo esc_js($counter);?>').trigger("change");
1943 + $('#wdktreeelem" . esc_js($counter) . "').trigger('change');
1757 1944 }
1758 1945 }).addClass('init');
1759 - });
1760 - </script>
1761 - <?php
1946 + });"
1947 + );
1762 1948 $counter++;
1763 1949 return $form;
1764 1950 }
1765 1951 }
@@ -1827,9 +2013,9 @@
1827 2013 if(empty($values)) {
1828 2014 $values = $empty_value;
1829 2015 }
1830 2016
1831 - $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/>';
1832 2018
1833 2019 $skip_id = '';
1834 2020 //load javascript library
1835 2021 if($counter==0)
@@ -1840,13 +2026,14 @@
1840 2026 ?>
1841 2027 <script>
1842 2028 jQuery(document).ready(function($) {
1843 2029 $('#wdktreeelem_checkbox<?php echo esc_js($counter);?>:not(.init)').wdkTreefieldCheckboxes({
1844 - ajax_url: '<?php echo admin_url('admin-ajax.php'); ?>',
2030 + ajax_url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
1845 2031 ajax_param: {
1846 2032 "page": 'wdk_frontendajax',
1847 2033 "function": 'treefieldid_checkboxes',
1848 2034 "action": 'wdk_public_action',
2035 + "wdk_secure": '<?php echo esc_js(wp_create_nonce( 'wdk_secure_treefieldid_checkboxes' ));?>',
1849 2036 "table": '<?php echo esc_js($table); ?>',
1850 2037 "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1851 2038 "empty_value": '<?php echo esc_js($empty_value); ?>',
1852 2039 "user_check": '<?php echo esc_js($user_check); ?>',
@@ -1875,11 +2062,19 @@
1875 2062 if ( ! function_exists('wdk_filter_decimal'))
1876 2063 {
1877 2064 function wdk_filter_decimal($string = '')
1878 2065 {
1879 - if(substr($string, -3, 3) === ".00") {
1880 - return substr($string, 0, -3);
1881 - }
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 + }
1882 2077
1883 2078 return $string;
1884 2079 }
1885 2080 }
@@ -1957,12 +2152,8 @@
1957 2152 * @return string date in format Y-m-d H:i:s
1958 2153 */
1959 2154 function wdk_normalize_date_db($date, $format = 'Y-m-d H:i:s', $return_format = 'Y-m-d H:i:s')
1960 2155 {
1961 - /* check is date on strtotime */
1962 - if((bool)strtotime($date)){
1963 - return date($return_format, strtotime($date));
1964 - }
1965 2156
1966 2157 /* check is date from argument */
1967 2158 $d = \DateTime::createFromFormat($format, $date);
1968 2159 if($d) {
@@ -1993,24 +2184,29 @@
1993 2184 return $d->format($return_format);
1994 2185 }
1995 2186 }
1996 2187
1997 - /* issue with pm/am inside date, example bug format like "2023 01 19 pm8:06" => 'Y n j ag:i' */
1998 - $format = get_option('date_format').' '.get_option('time_format');
1999 - if(strpos($format, 'a') !== FALSE) {
2000 - $format = str_replace('a', '',$format).' a';
2001 - if(strpos($date, 'am') !== FALSE) {
2002 - $date = str_replace('am', '',$date).' am';
2003 - }
2004 - if(strpos($date, 'pm') !== FALSE) {
2005 - $date = str_replace('pm', '',$date).' pm';
2006 - }
2007 - $d = \DateTime::createFromFormat($format, $date);
2008 - if($d) {
2009 - return $d->format($return_format);
2010 - }
2011 - }
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 + }
2012 2203
2204 + /* check is date on strtotime */
2205 + if((bool)strtotime($date)){
2206 + return gmdate($return_format, strtotime($date));
2207 + }
2208 +
2013 2209 return false;
2014 2210 }
2015 2211 }
2016 2212
@@ -2028,9 +2224,100 @@
2028 2224 return $base_url.$extension_url;
2029 2225 }
2030 2226 }
2031 2227
2228 +
2032 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 +/**
2033 2320 * Insert an attachment from an URL address.
2034 2321 *
2035 2322 * @param String $url
2036 2323 * @param Int $parent_post_id
@@ -2052,14 +2339,14 @@
2052 2339 $filename = substr($filename, 0, strpos($filename, '?'));
2053 2340 }
2054 2341
2055 2342 /* if unsoported extension */
2056 - 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){
2057 2344 $data = getimagesizefromstring($response['body']);
2058 2345 if(!$data) return false;
2059 2346 if(empty($data['mime'])) return false;
2060 2347
2061 - $filename = time().rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2348 + $filename = time().wp_rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2062 2349 }
2063 2350 $upload = wp_upload_bits( $filename, null, $response['body'] );
2064 2351
2065 2352 if( !empty( $upload['error'] ) ) {
@@ -2151,17 +2438,12 @@
2151 2438 */
2152 2439
2153 2440 function wdk_generate_profile_permalink($profile = array())
2154 2441 {
2155 -
2156 2442 $profile_slug = '';
2157 - if(wmvc_show_data('user_login', $profile, false)){
2158 - $profile_slug = wmvc_show_data('user_login', $profile);
2159 - if(wmvc_show_data('wdk_slug', $profile))
2160 - $profile_slug = wmvc_show_data('wdk_slug', $profile);
2161 - } else if(is_intval($profile)){
2443 + if(is_intval($profile)){
2162 2444 $profile_data = get_userdata($profile);
2163 - if(wmvc_show_data('wdk_slug', $profile, false)){
2445 + if(wmvc_show_data('wdk_slug', $profile_data, false)){
2164 2446 $profile_slug = wmvc_show_data('wdk_slug', $profile);
2165 2447 }elseif(wmvc_show_data('user_login', $profile_data, false)){
2166 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2167 2449 } else {
@@ -2166,10 +2448,14 @@
2166 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2167 2449 } else {
2168 2450 $profile_slug = $profile;
2169 2451 }
2170 - }
2171 -
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 +
2172 2458 $user_profile_page = get_option('wdk_membership_profile_preview_page');
2173 2459 if(!$user_profile_page) {
2174 2460 return '#';
2175 2461 }
@@ -2263,12 +2549,18 @@
2263 2549 {
2264 2550 $url = wp_login_url($url_redirect);
2265 2551
2266 2552 if(get_option('wdk_membership_login_page')){
2267 - $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 + }
2268 2560 }
2269 2561
2270 - return $url;
2562 + return trim($url, '?');
2271 2563 }
2272 2564 }
2273 2565
2274 2566 if(!function_exists('wdk_mail')) {
@@ -2287,10 +2579,10 @@
2287 2579 if(empty($subject))
2288 2580 $subject = __("New message", "wpdirectorykit");
2289 2581
2290 2582 $headers = array('Content-Type: text/html; charset=UTF-8');
2291 - $headers[] = 'From: '.$email_from;
2292 -
2583 + $headers[] = 'From: "'.get_bloginfo('name').'" <'.$email_from.'>';
2584 +
2293 2585 if(!empty($reply_to)) {
2294 2586 $headers[] = 'Reply-To: '.$reply_to;
2295 2587 } else {
2296 2588 $headers[] = 'Reply-To: '.$email_from;
@@ -2418,19 +2710,19 @@
2418 2710 <!-- Your add & remove file links -->
2419 2711 <p class="hide-if-no-js">
2420 2712 <a class="upload-custom-img <?php if ( $you_have_file ) { echo 'hidden'; } ?>"
2421 2713 href="<?php echo esc_url($upload_link) ?>">
2422 - <?php echo esc_html__('Select file','wmvc_win') ?>
2714 + <?php echo esc_html__('Select file','wpdirectorykit') ?>
2423 2715 </a>
2424 2716 <a class="delete-custom-img <?php if ( ! $you_have_file ) { echo 'hidden'; } ?>"
2425 2717 href="#">
2426 - <?php echo esc_html__('Remove file','wmvc_win') ?>
2718 + <?php echo esc_html__('Remove all files','wpdirectorykit') ?>
2427 2719 </a>
2428 2720 </p>
2429 2721 <?php //endif; ?>
2430 2722
2431 2723 <!-- A hidden input to set and post the chosen file id -->
2432 - <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); ?>" />
2433 2725 </div>
2434 2726
2435 2727 <?php
2436 2728 $custom_js ='';
@@ -2438,8 +2730,9 @@
2438 2730 if( typeof jQuery.fn.wpMediaElementFile == 'function')
2439 2731 $('#".esc_js($field_name)."meta-box-id.postbox-upload').wpMediaElementFile();
2440 2732 });";
2441 2733
2734 +// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2442 2735 echo "<script>".$custom_js."</script>";
2443 2736
2444 2737 ?>
2445 2738
@@ -2490,19 +2783,15 @@
2490 2783 function wdk_upload_multi_files($field_name, $image_ids='', $texts = array())
2491 2784 {
2492 2785 static $media_element_counter = 0;
2493 2786
2494 - if(!isset($texts['file_select']))$texts['file_select'] = esc_html__('Select file','wmvc_win');
2495 - 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');
2496 2789
2497 2790 $media_element_counter++;
2498 2791
2499 2792 $img_field = $field_name.'_'.$media_element_counter;
2500 2793
2501 - wp_register_script( 'wpmediaelement_file', WPDIRECTORYKIT_URL . 'admin/js/jquery.wpmediaelement_file.js', array( 'jquery' ), false, false );
2502 - wp_enqueue_script( 'wpmediaelement_file' );
2503 - wp_enqueue_media();
2504 -
2505 2794 wp_enqueue_script( 'wpmediamultiple' );
2506 2795 wp_enqueue_script( 'jquery-ui-mouse' );
2507 2796 wp_enqueue_media();
2508 2797
@@ -2539,9 +2828,9 @@
2539 2828 <!-- Your image container, which can be manipulated with js -->
2540 2829 <div class="custom-img-container winter_mvc-media">
2541 2830 <?php if($you_have_img)foreach($your_img_src as $image_id => $img_src) : ?>
2542 2831 <div class="winter_mvc-media-card" data-media-id="<?php echo esc_attr($image_id);?>">
2543 - <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"/>
2544 2833 <a href="#" class="remove"></a>
2545 2834 </div>
2546 2835 <?php endforeach; ?>
2547 2836 </div>
@@ -2561,9 +2850,9 @@
2561 2850 </p>
2562 2851 <?php //endif; ?>
2563 2852
2564 2853 <!-- A hidden input to set and post the chosen image id -->
2565 - <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); ?>" />
2566 2855 </div>
2567 2856 <?php
2568 2857 $custom_js ='';
2569 2858 $custom_js .=" jQuery(function($) {
@@ -2569,11 +2858,14 @@
2569 2858 $custom_js .=" jQuery(function($) {
2570 2859 if( typeof jQuery.fn.wpMediaMultiple == 'function')
2571 2860 $('#".esc_js($field_name)."meta-box-id.postbox-upload-multiple').wpMediaMultiple({
2572 2861 frame: {
2573 - 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'))."',
2574 2863 button: '".esc_js(__('Use this media','wpdirectorykit'))."',
2575 - }
2864 + },
2865 + library: {
2866 + type: ['application', 'image', 'video']
2867 + },
2576 2868 });
2577 2869 /* order */
2578 2870 var re_order = function(media_element){
2579 2871 var list_media = '';
@@ -2600,8 +2892,9 @@
2600 2892 })
2601 2893 });
2602 2894 ";
2603 2895
2896 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2604 2897 echo "<script>".$custom_js."</script>";
2605 2898
2606 2899 ?>
2607 2900
@@ -2682,8 +2975,59 @@
2682 2975
2683 2976 }
2684 2977 }
2685 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 +
2686 3030 if ( ! function_exists('wdk_recaptcha_field'))
2687 3031 {
2688 3032 function wdk_recaptcha_field($is_compact=false, $style="", $load_script=true)
2689 3033 {
@@ -2693,9 +3037,16 @@
2693 3037 if(get_option('wdk_recaptcha_site_key') !== FALSE && get_option('wdk_recaptcha_secret_key') !== NULL)
2694 3038 {
2695 3039 if($load_script && $counter===0)
2696 3040 {
2697 - 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 +
2698 3049 }
2699 3050 $counter++;
2700 3051
2701 3052 $compact_tag='';
@@ -2707,15 +3058,15 @@
2707 3058 }
2708 3059
2709 3060 $recaptcha_array[$counter] = array('size'=>$size_tag);
2710 3061
2711 - 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>';
2712 3063 ?>
2713 3064
2714 3065 <script>
2715 3066 <?php if($counter===1)echo 'var ';?>CaptchaCallback = function(){
2716 3067 <?php for($j=1;$j<=$counter;$j++): ?>
2717 - 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')); ?>'});
2718 3069 <?php endfor; ?>
2719 3070 };
2720 3071 </script>
2721 3072
@@ -2817,9 +3168,9 @@
2817 3168 if(is_array($val))
2818 3169 {
2819 3170 return wdk_clean($_POST);
2820 3171 }
2821 - else
3172 + elseif(is_string($val))
2822 3173 {
2823 3174 if(strpos($val, '<iframe') === 0)
2824 3175 $val = str_replace("'",'"', $val);
2825 3176
@@ -2858,9 +3209,9 @@
2858 3209 if(is_array($val))
2859 3210 {
2860 3211 $arr_cleaned[sanitize_text_field($key)] = wdk_clean($val);
2861 3212 }
2862 - else
3213 + elseif(is_string($val))
2863 3214 {
2864 3215 $arr_cleaned[sanitize_text_field($key)] = wp_kses_post($val);
2865 3216 }
2866 3217
@@ -2870,8 +3221,34 @@
2870 3221
2871 3222 return $arr_cleaned;
2872 3223 }
2873 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 +
2874 3251 /*
2875 3252 <select class="form-control" name="<?php echo 'control_operator_'.$i_fieldnum; ?>">
2876 3253 <option value="CONTAINS">CONTAINS</option>
2877 3254 <option value="NOT_CONTAINS">NOT_CONTAINS</option>
@@ -2912,9 +3289,9 @@
2912 3289
2913 3290 if(is_array($filter_ids)) $filter_ids = implode(',', $filter_ids);
2914 3291
2915 3292 static $counter = 0;
2916 - $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="">';
2917 3294
2918 3295
2919 3296 if(false)
2920 3297 if( $column_key == 'idcategory') {
@@ -2928,9 +3305,9 @@
2928 3305
2929 3306 $ids = array();
2930 3307 foreach($selected as $selected_item) {
2931 3308 if(!empty($selected_item)) {
2932 - $ids [] = $selected_item;
3309 + $ids [] = (int) $selected_item;
2933 3310 }
2934 3311 }
2935 3312
2936 3313 /* where in */
@@ -2941,15 +3318,19 @@
2941 3318
2942 3319 $results = $WMVC->$table->get();
2943 3320 foreach ($results as $item) {
2944 3321 if($item)
2945 - $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>';
2946 3325 }
2947 3326 }
2948 3327 } elseif(is_intval($selected)) {
2949 3328 $db_item = $WMVC->$table->get($selected, TRUE);
2950 3329 if($db_item)
2951 - $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>';
2952 3333 }
2953 3334 } else {
2954 3335 //$form .= '<option value="" selected="selected">'.esc_html__('Not selected', 'wpdirectorykit').'</option>';
2955 3336 }
@@ -2957,11 +3338,11 @@
2957 3338
2958 3339 //load javascript library
2959 3340 if($counter==0)
2960 3341 {
2961 - wp_enqueue_script('select2');
3342 + wp_enqueue_script('select2-select2');
2962 3343 wp_enqueue_script('wdk-select2');
2963 - wp_enqueue_style('select2');
3344 + wp_enqueue_style('select2-select2');
2964 3345 }
2965 3346 ?>
2966 3347 <?php
2967 3348 $counter++;
@@ -3005,11 +3386,11 @@
3005 3386
3006 3387 //load javascript library
3007 3388 if($counter==0)
3008 3389 {
3009 - wp_enqueue_script('select2');
3390 + wp_enqueue_script('select2-select2');
3010 3391 wp_enqueue_script('wdk-select2');
3011 - wp_enqueue_style('select2');
3392 + wp_enqueue_style('select2-select2');
3012 3393 }
3013 3394 ?>
3014 3395 <?php
3015 3396 $counter++;
@@ -3087,11 +3468,30 @@
3087 3468 'r'=>'llll',
3088 3469 'u'=>'x',
3089 3470 );
3090 3471
3091 - $replaced_from = array_keys($replaced);
3092 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3093 - 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);
3094 3494 }
3095 3495 }
3096 3496
3097 3497 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3132,11 +3532,29 @@
3132 3532 'u'=>'@',
3133 3533 ':'=>'',
3134 3534 );
3135 3535
3136 - $replaced_from = array_keys($replaced);
3137 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3138 - 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);
3139 3557 }
3140 3558 }
3141 3559
3142 3560 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3177,11 +3595,31 @@
3177 3595 'u'=>'@',
3178 3596 ':'=>'',
3179 3597 );
3180 3598
3181 - $replaced_from = array_keys($replaced);
3182 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3183 - 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 +
3184 3622 }
3185 3623 }
3186 3624
3187 3625 if ( ! function_exists('wdk_get_gps'))
@@ -3209,9 +3647,17 @@
3209 3647
3210 3648 if(!isset($results[$address])) {
3211 3649 $results[$address] = NULL;
3212 3650 $url = 'https://nominatim.openstreetmap.org/search?format=json&q=' . $address;
3213 - $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);
3214 3660 $response = '';
3215 3661
3216 3662 // request failed
3217 3663 if ( is_wp_error( $request ) ) {
@@ -3367,8 +3813,32 @@
3367 3813 return false;
3368 3814 }
3369 3815 }
3370 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 +
3371 3841 if ( ! function_exists('wdk_filter_phone'))
3372 3842 {
3373 3843 // Validation phone
3374 3844 /**
@@ -3504,9 +3974,22 @@
3504 3974
3505 3975 $value = filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
3506 3976 $value = (float)str_replace(array(","," ",'&nbsp;'), "", $value);
3507 3977
3508 - 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);
3509 3992 }
3510 3993 }
3511 3994
3512 3995 if ( ! function_exists('wdk_currency_symbol'))
@@ -3636,11 +4119,23 @@
3636 4119 $user_data['wdk_viber'] = wmvc_show_data('cacheduser_wdk_viber', $row);
3637 4120 $user_data['wdk_iban'] = wmvc_show_data('cacheduser_wdk_iban', $row);
3638 4121 $user_data['wdk_telegram'] = wmvc_show_data('cacheduser_wdk_telegram', $row);
3639 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);
3640 4124 $user_data['description'] = wmvc_show_data('cacheduser_description', $row);
3641 4125 $user_data['user_url'] = wmvc_show_data('cacheduser_user_url', $row);
3642 - $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 + }
3643 4138
3644 4139 return $user_data;
3645 4140 }
3646 4141 }
@@ -3884,11 +4379,11 @@
3884 4379 $page_title,
3885 4380 $post_type
3886 4381 );
3887 4382 }
3888 -
3889 - $page = $wpdb->get_var( $sql );
3890 -
4383 + $page = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
4384 +
4385 +
3891 4386 if ( $page ) {
3892 4387 return get_post( $page, $output );
3893 4388 }
3894 4389
@@ -3952,9 +4447,9 @@
3952 4447 $output .= '<tr>';
3953 4448 foreach($var as $k => $v) {
3954 4449 if(count($columns) > 0 && !in_array($k, $columns))continue;
3955 4450
3956 - $output .= '<td><strong>' . $k . '</strong></td>';
4451 + $output .= '<td><strong>' . esc_html($k) . '</strong></td>';
3957 4452 }
3958 4453 $output .= '</tr>';
3959 4454 }
3960 4455
@@ -3961,13 +4456,14 @@
3961 4456 $output .= '<tr>';
3962 4457 foreach($var as $k => $v) {
3963 4458 if(count($columns) > 0 && !in_array($k, $columns))continue;
3964 4459
3965 - $output .= '<td>' . $v . '</td>';
4460 + $output .= '<td>' . esc_html($v) . '</td>';
3966 4461 }
3967 4462 $output .= '</tr>';
3968 4463 }
3969 4464 $output .= '</table>';
4465 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
3970 4466 echo $output;
3971 4467 }
3972 4468 }
3973 4469
@@ -3973,9 +4469,9 @@
3973 4469
3974 4470 if ( ! function_exists('wdk_move_gps'))
3975 4471 {
3976 4472 function wdk_move_gps($value) {
3977 - return $value+0.001 * rand(1, 9);
4473 + return $value+0.001 * wp_rand(1, 9);
3978 4474 }
3979 4475 }
3980 4476
3981 4477 if ( ! function_exists('wdk_get_near_location'))
@@ -3983,10 +4479,10 @@
3983 4479 function wdk_get_near_location($latitude, $longitude, $radius = 10000) {
3984 4480 // Convert radius from meters to degrees
3985 4481 $radiusInDegrees = $radius / 111000;
3986 4482
3987 - $u = mt_rand() / mt_getrandmax();
3988 - $v = mt_rand() / mt_getrandmax();
4483 + $u = wp_rand() / mt_getrandmax();
4484 + $v = wp_rand() / mt_getrandmax();
3989 4485 $w = $radiusInDegrees * sqrt($u);
3990 4486 $t = 2 * M_PI * $v;
3991 4487 $x = $w * cos($t);
3992 4488 $y = $w * sin($t);
@@ -4048,6 +4544,909 @@
4048 4544
4049 4545 return $fields;
4050 4546 }
4051 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 + }
4052 5451
4053 5452 ?>