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 +1398 -164 1.3.0 → 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,9 +546,9 @@
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
@@ -587,8 +593,29 @@
587 593 $columns[] = $column_name;
588 594 $external_columns[] = $column_name;
589 595 }
590 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 +
591 618 //$table_name = substr($model_name, 0, -2);
592 619 $columns_original = array();
593 620 foreach($columns as $key=>$val)
594 621 {
@@ -616,8 +643,10 @@
616 643 {
617 644 unset($_GET_clone['search']);
618 645 unset($_GET_clone['field_search']);
619 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 +
620 649 // For quick/smart search
621 650 if(wmvc_count($columns) > 0 && !empty($smart_search))
622 651 {
623 652 $gen_q = '';
@@ -675,8 +704,13 @@
675 704 /* location / categories */
676 705 if(!is_intval($smart_search)) {
677 706 $gen_q.="location_title LIKE '%$smart_search%' OR ";
678 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 +
679 713 }
680 714 /* get address and gps */
681 715 if(strlen($smart_search) > 5) {
682 716 $coordinates_center = wdk_get_gps($smart_search);
@@ -732,9 +766,9 @@
732 766
733 767 if(!empty($gen_q))
734 768 $WMVC->db->where("($gen_q)");
735 769 }
736 -
770 +
737 771 // For column search
738 772 if(isset($_GET_clone))
739 773 {
740 774 $gen_q = '';
@@ -749,43 +783,31 @@
749 783 // $col_name = $key;
750 784
751 785 if(strpos($key, 'skip') !== FALSE) continue;
752 786
753 - if(defined( 'WP_DEBUG' ) && WP_DEBUG)
754 - if(function_exists('pll_current_language'))
755 - {
756 - $lang_term_id = pll_current_language('term_id');
757 -
758 - if(is_numeric($lang_term_id))
759 - {
760 - $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);
761 - $WMVC->db->where("({$WMVC->db->prefix}term_relationships.term_taxonomy_id = $lang_term_id)");
762 - }
763 - }
764 -
765 787 if($key == 'field_booking_guest')
766 788 {
767 789 if(!$wdk_bookings_joinded){
768 - $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');
769 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
770 - $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');
771 793 $wdk_bookings_joinded = true;
772 794 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
773 - $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');
774 796 }
775 797
776 - $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 ";
777 799
778 800 }
779 801 elseif($key == 'field_booking_date_from')
780 802 {
781 803 if(!$wdk_bookings_joinded){
782 - $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');
783 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
784 - $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');
785 807 $wdk_bookings_joinded = true;
786 808 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
787 - $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');
788 810 }
789 811
790 812 if(wdk_is_date($val))
791 813 {
@@ -803,9 +825,9 @@
803 825 if(!get_option('wdk_bookings_is_hours_enabled')) {
804 826 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from'], 'Y-m-d H:i:s', 'Y-m-d');
805 827 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to'], 'Y-m-d H:i:s', 'Y-m-d');
806 828
807 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
829 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
808 830 SELECT post_id
809 831 FROM ".$WMVC->db->prefix."wdk_booking_reservation
810 832 WHERE
811 833 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -818,9 +840,9 @@
818 840 } else {
819 841 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from']);
820 842 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to']);
821 843
822 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
844 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
823 845 SELECT post_id
824 846 FROM ".$WMVC->db->prefix."wdk_booking_reservation
825 847 WHERE
826 848 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -835,13 +857,13 @@
835 857 }
836 858 elseif($key == 'field_booking_date_to')
837 859 {
838 860 if(!$wdk_bookings_joinded){
839 - $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');
840 - $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');
841 863 $wdk_bookings_joinded = true;
842 864 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
843 - $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');
844 866 }
845 867
846 868 if(wdk_is_date($val))
847 869 {
@@ -857,9 +879,33 @@
857 879 }
858 880 elseif(substr($key, -8) == '_exactly')
859 881 {
860 882 $col_name = substr($key, 0, -8);
861 - $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 + }
862 908 }
863 909 elseif(substr($key, -4) == '_max')
864 910 {
865 911 $col_name = substr($key, 0, -4);
@@ -949,9 +995,9 @@
949 995 }
950 996
951 997 if(is_array($val)) {
952 998
953 - $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');
954 1000 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
955 1001 $sql_search = '';
956 1002 foreach ($val as $v) {
957 1003 if(empty($v)) continue;
@@ -966,9 +1012,9 @@
966 1012 if(!empty($sql_search))
967 1013 $gen_q.=" ( ".$sql_search." ) AND ";
968 1014
969 1015 } elseif(is_string($val) && !empty($val)) {
970 - $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');
971 1017 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
972 1018 $sql_search =" ".$WMVC->listing_m->_table_name.".`user_id_editor` = ".intval($val)." OR `".$WMVC->db->prefix."wdk_listings_users`.`user_id` = ".intval($val)." ";
973 1019 $gen_q.=" ( ".$sql_search." ) AND ";
974 1020 }
@@ -1125,10 +1171,15 @@
1125 1171
1126 1172 if(!empty($sql_search))
1127 1173 $gen_q.=" ( ".$sql_search." ) AND ";
1128 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 + }
1129 1181 }
1130 -
1131 1182 }
1132 1183
1133 1184 $gen_q = substr($gen_q, 0, -5);
1134 1185
@@ -1135,8 +1186,20 @@
1135 1186 if(!empty($gen_q))
1136 1187 $WMVC->db->where("($gen_q)");
1137 1188 }
1138 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 +
1139 1202 // [RECTANGLE SEARCH]
1140 1203 if(isset($_GET_clone['rectangle_ne']) && isset($_GET_clone['rectangle_sw']))
1141 1204 {
1142 1205 if(wdk_is_gps($_GET_clone['rectangle_ne']) && wdk_is_gps($_GET_clone['rectangle_sw'])) {
@@ -1150,12 +1213,92 @@
1150 1213 }
1151 1214 // [/RECTANGLE SEARCH]
1152 1215
1153 1216 // order
1154 - if(isset($_GET_clone['order_by']))
1155 - {
1156 - $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_listings.post_id', $_GET_clone['order_by']);
1157 - $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 +
1158 1301 }
1159 1302
1160 1303 }
1161 1304 }
@@ -1172,9 +1315,9 @@
1172 1315
1173 1316 if(isset($custom_parameters['order_by'])) {
1174 1317
1175 1318 if(isset($_GET_clone['order_by']) && !empty($_GET_clone['order_by'])) {
1176 - $_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']);
1177 1320 } else {
1178 1321 $_GET_clone['order_by'] = $custom_parameters['order_by'];
1179 1322 }
1180 1323
@@ -1188,9 +1331,9 @@
1188 1331 $WMVC->model($model_name);
1189 1332
1190 1333 $smart_search = '';
1191 1334 if(isset($_GET_clone['profile_search']))
1192 - $smart_search = sanitize_text_field($_GET_clone['profile_search']);
1335 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['profile_search']));
1193 1336
1194 1337 $available_fields = array('user_login','user_nicename','user_email','user_url','display_name');
1195 1338
1196 1339 if(isset($_GET_clone['is_activated'])){
@@ -1357,9 +1500,9 @@
1357 1500 // order
1358 1501 if(isset($_GET_clone['order_by']))
1359 1502 {
1360 1503 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_favorite.post_id', $_GET_clone['order_by']);
1361 - $WMVC->db->order_by($_GET_clone['order_by']);
1504 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by'])));
1362 1505 }
1363 1506
1364 1507 }
1365 1508 }
@@ -1375,9 +1518,9 @@
1375 1518 //$WMVC->model('listing_m');
1376 1519
1377 1520 $smart_search = '';
1378 1521 if(isset($_GET_clone['search']))
1379 - $smart_search = sanitize_text_field($_GET_clone['search']);
1522 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['search']));
1380 1523
1381 1524 $available_fields = $WMVC->$model_name->get_available_fields();
1382 1525
1383 1526 /* Пet column names from wdk_package and add to allow search +
@@ -1488,9 +1631,9 @@
1488 1631 $detect_date = strtotime($gen_search);
1489 1632
1490 1633 if(wdk_payments_is_date($val) && $detect_date > 1000)
1491 1634 {
1492 - $gen_search = date('Y-m-d H:i:s', $detect_date);
1635 + $gen_search = gmdate('Y-m-d H:i:s', $detect_date);
1493 1636 $gen_q.=$col_name." > '".$gen_search."' AND ";
1494 1637 }
1495 1638 else
1496 1639 {
@@ -1528,9 +1671,9 @@
1528 1671 // order
1529 1672 if(isset($_GET_clone['order_by']))
1530 1673 {
1531 1674 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_messages.post_id', $_GET_clone['order_by']);
1532 - $WMVC->db->order_by($_GET_clone['order_by']);
1675 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by']), true));
1533 1676 }
1534 1677
1535 1678 }
1536 1679 }
@@ -1537,9 +1680,9 @@
1537 1680
1538 1681 function wdk_date() {
1539 1682 $date_format = get_option('date_format');
1540 1683 $time_format = get_option('time_format');
1541 - $date = date("{$date_format} {$time_format}", current_time('timestamp'));
1684 + $date = gmdate("{$date_format} {$time_format}", current_time('timestamp'));
1542 1685 return $date;
1543 1686 }
1544 1687
1545 1688 if(!function_exists('wdk_placeholder_image_src')) {
@@ -1563,18 +1706,20 @@
1563 1706
1564 1707 if(isset($_GET[$page_var]))
1565 1708 $current_page = intval(wmvc_xss_clean($_GET[$page_var]));
1566 1709
1567 - if(!isset($texts['previous_page']))$texts['previous_page'] = 'Previous page';
1568 - 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');
1569 1712 if(!isset($texts['first_page']))$texts['first_page'] = '';
1570 1713 if(!isset($texts['last_page']))$texts['last_page'] = '';
1571 - if(!isset($texts['items']))$texts['items'] = 'items';
1714 + if(!isset($texts['items']))$texts['items'] = esc_html__('items', 'wpdirectorykit');
1572 1715
1573 1716 if(empty($current_page))$current_page = 1;
1574 1717
1575 1718 // get url
1576 - $url = strtok($_SERVER["REQUEST_URI"], '?');
1719 + $url = strtok(wdk_server_current_url(), '?');
1720 +
1721 +
1577 1722 $qs_parameters = wmvc_xss_clean( $_GET );
1578 1723 unset($qs_parameters[$page_var]);
1579 1724 $qs_part = http_build_query($qs_parameters);
1580 1725 $url = wdk_url_suffix($url, $qs_part);
@@ -1597,16 +1742,16 @@
1597 1742
1598 1743 $output .= '<div class="nav-links">';
1599 1744
1600 1745 if($enable_latest_first && $current_page-1 > 0)
1601 - $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>';
1602 1747
1603 1748 if ($current_page-1 > 0) {
1604 1749
1605 - $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>';
1606 1751 } elseif($enable_compact)
1607 1752 {
1608 - $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>';
1609 1754 }
1610 1755
1611 1756 if (!$enable_compact) {
1612 1757 for ($i = 1 ; $i <= $total_pages; $i++) {
@@ -1614,9 +1759,9 @@
1614 1759 if(($current_page-$limit_items) <= $i && ($current_page+$limit_items) >= $i) {
1615 1760 if (($current_page == $i)) {
1616 1761 $output.= '<span aria-current="page" class="page-numbers current">'.$i.'</span>';
1617 1762 } else {
1618 - $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>';
1619 1764 }
1620 1765 }
1621 1766 }
1622 1767 } else {
@@ -1624,17 +1769,17 @@
1624 1769 }
1625 1770
1626 1771 if($current_page+1 <= $total_pages)
1627 1772 {
1628 - $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>';
1629 1774 }
1630 1775 elseif($enable_compact)
1631 1776 {
1632 - $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>';
1633 1778 }
1634 1779
1635 1780 if($enable_latest_first && $current_page+1 <= $total_pages)
1636 - $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>';
1637 1782
1638 1783
1639 1784 $output.= '</div>';
1640 1785 $output.= '</nav>';
@@ -1689,22 +1834,27 @@
1689 1834 }
1690 1835
1691 1836 ?>
1692 1837 <div class="wdk-col wdk-col-btns">
1693 - <div class="wdk-field wdk-field-btn">
1838 + <div class="wdk-field wdk-field-btn">
1694 1839 <div class="wdk-field-group wdk-field-group-additional">
1695 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>
1696 - <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' />
1697 1842 </div>
1698 1843 <div class="wdk-field-group wdk-field-group-reset">
1699 - <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>
1700 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;?>
1701 1851 <div class="wdk-field-group wdk-field-group-search">
1702 - <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>
1703 1853
1704 1854 <?php if(function_exists('run_wdk_save_search') && get_option('wdk_save_search_show_on_searchform')):?>
1705 1855 <div class="section-widget-control right">
1706 - <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">
1707 1857 <i class="fas fa-save" aria-hidden="true"></i>
1708 1858 <i class="fa fa-spinner fa-spin fa-ajax-indicator"></i>
1709 1859 </a>
1710 1860 </div>
@@ -1709,8 +1859,9 @@
1709 1859 </a>
1710 1860 </div>
1711 1861 <?php endif;?>
1712 1862 </div>
1863 +
1713 1864 </div>
1714 1865 </div>
1715 1866 <div id='wdk-form-additional' class="wdk-col" style="<?php echo esc_attr($form_closed) ;?>">
1716 1867 <div class="wdk-row">
@@ -1753,9 +1904,9 @@
1753 1904
1754 1905 if(empty($selected))
1755 1906 $selected='';
1756 1907
1757 - $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/>';
1758 1909
1759 1910 $skip_id = '';
1760 1911 //load javascript library
1761 1912 if($counter==0)
@@ -1762,39 +1913,39 @@
1762 1913 {
1763 1914 wp_enqueue_script('wdk-treefield');
1764 1915 wp_enqueue_style('wdk-treefield');
1765 1916 }
1766 - ?>
1767 - <script>
1768 - jQuery(document).ready(function($) {
1769 - $('#wdktreeelem<?php echo esc_js($counter);?>:not(.init)').wdkTreefield({
1770 - 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')) . "',
1771 1922 ajax_param: {
1772 - "page": 'wdk_frontendajax',
1773 - "function": 'treefieldid',
1774 - "action": 'wdk_public_action',
1775 - "table": '<?php echo esc_js($table); ?>',
1776 - "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1777 - "start_id": '<?php if(!empty($filter_ids)) esc_js($selected); else echo ""; ?>',
1778 - "empty_value": '<?php echo esc_js($empty_value); ?>',
1779 - "user_check": '<?php echo esc_js($user_check); ?>',
1780 - "sql_where": '<?php echo esc_js($sql_where); ?>',
1781 - "hide_fields": '<?php echo esc_js($hide_fields); ?>'
1782 - },
1783 - attribute_id: '<?php echo esc_js($attribute_id); ?>',
1784 - language_id: '<?php echo esc_js($language_id); ?>',
1785 - attribute_value: '<?php echo esc_js($column); ?>',
1786 - 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: '',
1787 1939 empty_value: ' - ',
1788 - text_search: '<?php esc_html_e('Search term', 'wpdirectorykit');?>',
1789 - 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') . "',
1790 1942 callback_selected: function(key) {
1791 - $('#wdktreeelem<?php echo esc_js($counter);?>').trigger("change");
1943 + $('#wdktreeelem" . esc_js($counter) . "').trigger('change');
1792 1944 }
1793 1945 }).addClass('init');
1794 - });
1795 - </script>
1796 - <?php
1946 + });"
1947 + );
1797 1948 $counter++;
1798 1949 return $form;
1799 1950 }
1800 1951 }
@@ -1862,9 +2013,9 @@
1862 2013 if(empty($values)) {
1863 2014 $values = $empty_value;
1864 2015 }
1865 2016
1866 - $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/>';
1867 2018
1868 2019 $skip_id = '';
1869 2020 //load javascript library
1870 2021 if($counter==0)
@@ -1875,13 +2026,14 @@
1875 2026 ?>
1876 2027 <script>
1877 2028 jQuery(document).ready(function($) {
1878 2029 $('#wdktreeelem_checkbox<?php echo esc_js($counter);?>:not(.init)').wdkTreefieldCheckboxes({
1879 - ajax_url: '<?php echo admin_url('admin-ajax.php'); ?>',
2030 + ajax_url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
1880 2031 ajax_param: {
1881 2032 "page": 'wdk_frontendajax',
1882 2033 "function": 'treefieldid_checkboxes',
1883 2034 "action": 'wdk_public_action',
2035 + "wdk_secure": '<?php echo esc_js(wp_create_nonce( 'wdk_secure_treefieldid_checkboxes' ));?>',
1884 2036 "table": '<?php echo esc_js($table); ?>',
1885 2037 "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1886 2038 "empty_value": '<?php echo esc_js($empty_value); ?>',
1887 2039 "user_check": '<?php echo esc_js($user_check); ?>',
@@ -1910,14 +2062,19 @@
1910 2062 if ( ! function_exists('wdk_filter_decimal'))
1911 2063 {
1912 2064 function wdk_filter_decimal($string = '')
1913 2065 {
1914 - if(substr($string, -3, 3) === ".00") {
1915 - return substr($string, 0, -3);
1916 - }
1917 - if(substr($string, -3, 1) === "." && substr($string, -1, 1) === "0") {
1918 - return substr($string, 0, -1);
1919 - }
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 + }
1920 2077
1921 2078 return $string;
1922 2079 }
1923 2080 }
@@ -2045,9 +2202,9 @@
2045 2202 }
2046 2203
2047 2204 /* check is date on strtotime */
2048 2205 if((bool)strtotime($date)){
2049 - return date($return_format, strtotime($date));
2206 + return gmdate($return_format, strtotime($date));
2050 2207 }
2051 2208
2052 2209 return false;
2053 2210 }
@@ -2067,9 +2224,100 @@
2067 2224 return $base_url.$extension_url;
2068 2225 }
2069 2226 }
2070 2227
2228 +
2071 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 +/**
2072 2320 * Insert an attachment from an URL address.
2073 2321 *
2074 2322 * @param String $url
2075 2323 * @param Int $parent_post_id
@@ -2091,14 +2339,14 @@
2091 2339 $filename = substr($filename, 0, strpos($filename, '?'));
2092 2340 }
2093 2341
2094 2342 /* if unsoported extension */
2095 - 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){
2096 2344 $data = getimagesizefromstring($response['body']);
2097 2345 if(!$data) return false;
2098 2346 if(empty($data['mime'])) return false;
2099 2347
2100 - $filename = time().rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2348 + $filename = time().wp_rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2101 2349 }
2102 2350 $upload = wp_upload_bits( $filename, null, $response['body'] );
2103 2351
2104 2352 if( !empty( $upload['error'] ) ) {
@@ -2190,17 +2438,12 @@
2190 2438 */
2191 2439
2192 2440 function wdk_generate_profile_permalink($profile = array())
2193 2441 {
2194 -
2195 2442 $profile_slug = '';
2196 - if(wmvc_show_data('user_login', $profile, false)){
2197 - $profile_slug = wmvc_show_data('user_login', $profile);
2198 - if(wmvc_show_data('wdk_slug', $profile))
2199 - $profile_slug = wmvc_show_data('wdk_slug', $profile);
2200 - } else if(is_intval($profile)){
2443 + if(is_intval($profile)){
2201 2444 $profile_data = get_userdata($profile);
2202 - if(wmvc_show_data('wdk_slug', $profile, false)){
2445 + if(wmvc_show_data('wdk_slug', $profile_data, false)){
2203 2446 $profile_slug = wmvc_show_data('wdk_slug', $profile);
2204 2447 }elseif(wmvc_show_data('user_login', $profile_data, false)){
2205 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2206 2449 } else {
@@ -2205,10 +2448,14 @@
2205 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2206 2449 } else {
2207 2450 $profile_slug = $profile;
2208 2451 }
2209 - }
2210 -
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 +
2211 2458 $user_profile_page = get_option('wdk_membership_profile_preview_page');
2212 2459 if(!$user_profile_page) {
2213 2460 return '#';
2214 2461 }
@@ -2332,10 +2579,10 @@
2332 2579 if(empty($subject))
2333 2580 $subject = __("New message", "wpdirectorykit");
2334 2581
2335 2582 $headers = array('Content-Type: text/html; charset=UTF-8');
2336 - $headers[] = 'From: '.$email_from;
2337 -
2583 + $headers[] = 'From: "'.get_bloginfo('name').'" <'.$email_from.'>';
2584 +
2338 2585 if(!empty($reply_to)) {
2339 2586 $headers[] = 'Reply-To: '.$reply_to;
2340 2587 } else {
2341 2588 $headers[] = 'Reply-To: '.$email_from;
@@ -2463,19 +2710,19 @@
2463 2710 <!-- Your add & remove file links -->
2464 2711 <p class="hide-if-no-js">
2465 2712 <a class="upload-custom-img <?php if ( $you_have_file ) { echo 'hidden'; } ?>"
2466 2713 href="<?php echo esc_url($upload_link) ?>">
2467 - <?php echo esc_html__('Select file','wmvc_win') ?>
2714 + <?php echo esc_html__('Select file','wpdirectorykit') ?>
2468 2715 </a>
2469 2716 <a class="delete-custom-img <?php if ( ! $you_have_file ) { echo 'hidden'; } ?>"
2470 2717 href="#">
2471 - <?php echo esc_html__('Remove file','wmvc_win') ?>
2718 + <?php echo esc_html__('Remove all files','wpdirectorykit') ?>
2472 2719 </a>
2473 2720 </p>
2474 2721 <?php //endif; ?>
2475 2722
2476 2723 <!-- A hidden input to set and post the chosen file id -->
2477 - <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); ?>" />
2478 2725 </div>
2479 2726
2480 2727 <?php
2481 2728 $custom_js ='';
@@ -2483,8 +2730,9 @@
2483 2730 if( typeof jQuery.fn.wpMediaElementFile == 'function')
2484 2731 $('#".esc_js($field_name)."meta-box-id.postbox-upload').wpMediaElementFile();
2485 2732 });";
2486 2733
2734 +// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2487 2735 echo "<script>".$custom_js."</script>";
2488 2736
2489 2737 ?>
2490 2738
@@ -2535,19 +2783,15 @@
2535 2783 function wdk_upload_multi_files($field_name, $image_ids='', $texts = array())
2536 2784 {
2537 2785 static $media_element_counter = 0;
2538 2786
2539 - if(!isset($texts['file_select']))$texts['file_select'] = esc_html__('Select file','wmvc_win');
2540 - 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');
2541 2789
2542 2790 $media_element_counter++;
2543 2791
2544 2792 $img_field = $field_name.'_'.$media_element_counter;
2545 2793
2546 - wp_register_script( 'wpmediaelement_file', WPDIRECTORYKIT_URL . 'admin/js/jquery.wpmediaelement_file.js', array( 'jquery' ), false, false );
2547 - wp_enqueue_script( 'wpmediaelement_file' );
2548 - wp_enqueue_media();
2549 -
2550 2794 wp_enqueue_script( 'wpmediamultiple' );
2551 2795 wp_enqueue_script( 'jquery-ui-mouse' );
2552 2796 wp_enqueue_media();
2553 2797
@@ -2584,9 +2828,9 @@
2584 2828 <!-- Your image container, which can be manipulated with js -->
2585 2829 <div class="custom-img-container winter_mvc-media">
2586 2830 <?php if($you_have_img)foreach($your_img_src as $image_id => $img_src) : ?>
2587 2831 <div class="winter_mvc-media-card" data-media-id="<?php echo esc_attr($image_id);?>">
2588 - <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"/>
2589 2833 <a href="#" class="remove"></a>
2590 2834 </div>
2591 2835 <?php endforeach; ?>
2592 2836 </div>
@@ -2606,9 +2850,9 @@
2606 2850 </p>
2607 2851 <?php //endif; ?>
2608 2852
2609 2853 <!-- A hidden input to set and post the chosen image id -->
2610 - <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); ?>" />
2611 2855 </div>
2612 2856 <?php
2613 2857 $custom_js ='';
2614 2858 $custom_js .=" jQuery(function($) {
@@ -2614,11 +2858,14 @@
2614 2858 $custom_js .=" jQuery(function($) {
2615 2859 if( typeof jQuery.fn.wpMediaMultiple == 'function')
2616 2860 $('#".esc_js($field_name)."meta-box-id.postbox-upload-multiple').wpMediaMultiple({
2617 2861 frame: {
2618 - 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'))."',
2619 2863 button: '".esc_js(__('Use this media','wpdirectorykit'))."',
2620 - }
2864 + },
2865 + library: {
2866 + type: ['application', 'image', 'video']
2867 + },
2621 2868 });
2622 2869 /* order */
2623 2870 var re_order = function(media_element){
2624 2871 var list_media = '';
@@ -2645,8 +2892,9 @@
2645 2892 })
2646 2893 });
2647 2894 ";
2648 2895
2896 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2649 2897 echo "<script>".$custom_js."</script>";
2650 2898
2651 2899 ?>
2652 2900
@@ -2727,8 +2975,59 @@
2727 2975
2728 2976 }
2729 2977 }
2730 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 +
2731 3030 if ( ! function_exists('wdk_recaptcha_field'))
2732 3031 {
2733 3032 function wdk_recaptcha_field($is_compact=false, $style="", $load_script=true)
2734 3033 {
@@ -2738,9 +3037,16 @@
2738 3037 if(get_option('wdk_recaptcha_site_key') !== FALSE && get_option('wdk_recaptcha_secret_key') !== NULL)
2739 3038 {
2740 3039 if($load_script && $counter===0)
2741 3040 {
2742 - 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 +
2743 3049 }
2744 3050 $counter++;
2745 3051
2746 3052 $compact_tag='';
@@ -2752,15 +3058,15 @@
2752 3058 }
2753 3059
2754 3060 $recaptcha_array[$counter] = array('size'=>$size_tag);
2755 3061
2756 - 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>';
2757 3063 ?>
2758 3064
2759 3065 <script>
2760 3066 <?php if($counter===1)echo 'var ';?>CaptchaCallback = function(){
2761 3067 <?php for($j=1;$j<=$counter;$j++): ?>
2762 - 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')); ?>'});
2763 3069 <?php endfor; ?>
2764 3070 };
2765 3071 </script>
2766 3072
@@ -2862,9 +3168,9 @@
2862 3168 if(is_array($val))
2863 3169 {
2864 3170 return wdk_clean($_POST);
2865 3171 }
2866 - else
3172 + elseif(is_string($val))
2867 3173 {
2868 3174 if(strpos($val, '<iframe') === 0)
2869 3175 $val = str_replace("'",'"', $val);
2870 3176
@@ -2903,9 +3209,9 @@
2903 3209 if(is_array($val))
2904 3210 {
2905 3211 $arr_cleaned[sanitize_text_field($key)] = wdk_clean($val);
2906 3212 }
2907 - else
3213 + elseif(is_string($val))
2908 3214 {
2909 3215 $arr_cleaned[sanitize_text_field($key)] = wp_kses_post($val);
2910 3216 }
2911 3217
@@ -2915,8 +3221,34 @@
2915 3221
2916 3222 return $arr_cleaned;
2917 3223 }
2918 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 +
2919 3251 /*
2920 3252 <select class="form-control" name="<?php echo 'control_operator_'.$i_fieldnum; ?>">
2921 3253 <option value="CONTAINS">CONTAINS</option>
2922 3254 <option value="NOT_CONTAINS">NOT_CONTAINS</option>
@@ -2957,9 +3289,9 @@
2957 3289
2958 3290 if(is_array($filter_ids)) $filter_ids = implode(',', $filter_ids);
2959 3291
2960 3292 static $counter = 0;
2961 - $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="">';
2962 3294
2963 3295
2964 3296 if(false)
2965 3297 if( $column_key == 'idcategory') {
@@ -2973,9 +3305,9 @@
2973 3305
2974 3306 $ids = array();
2975 3307 foreach($selected as $selected_item) {
2976 3308 if(!empty($selected_item)) {
2977 - $ids [] = $selected_item;
3309 + $ids [] = (int) $selected_item;
2978 3310 }
2979 3311 }
2980 3312
2981 3313 /* where in */
@@ -2986,15 +3318,19 @@
2986 3318
2987 3319 $results = $WMVC->$table->get();
2988 3320 foreach ($results as $item) {
2989 3321 if($item)
2990 - $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>';
2991 3325 }
2992 3326 }
2993 3327 } elseif(is_intval($selected)) {
2994 3328 $db_item = $WMVC->$table->get($selected, TRUE);
2995 3329 if($db_item)
2996 - $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>';
2997 3333 }
2998 3334 } else {
2999 3335 //$form .= '<option value="" selected="selected">'.esc_html__('Not selected', 'wpdirectorykit').'</option>';
3000 3336 }
@@ -3002,11 +3338,11 @@
3002 3338
3003 3339 //load javascript library
3004 3340 if($counter==0)
3005 3341 {
3006 - wp_enqueue_script('select2');
3342 + wp_enqueue_script('select2-select2');
3007 3343 wp_enqueue_script('wdk-select2');
3008 - wp_enqueue_style('select2');
3344 + wp_enqueue_style('select2-select2');
3009 3345 }
3010 3346 ?>
3011 3347 <?php
3012 3348 $counter++;
@@ -3050,11 +3386,11 @@
3050 3386
3051 3387 //load javascript library
3052 3388 if($counter==0)
3053 3389 {
3054 - wp_enqueue_script('select2');
3390 + wp_enqueue_script('select2-select2');
3055 3391 wp_enqueue_script('wdk-select2');
3056 - wp_enqueue_style('select2');
3392 + wp_enqueue_style('select2-select2');
3057 3393 }
3058 3394 ?>
3059 3395 <?php
3060 3396 $counter++;
@@ -3132,11 +3468,30 @@
3132 3468 'r'=>'llll',
3133 3469 'u'=>'x',
3134 3470 );
3135 3471
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);
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);
3139 3494 }
3140 3495 }
3141 3496
3142 3497 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3177,11 +3532,29 @@
3177 3532 'u'=>'@',
3178 3533 ':'=>'',
3179 3534 );
3180 3535
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);
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);
3184 3557 }
3185 3558 }
3186 3559
3187 3560 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3222,11 +3595,31 @@
3222 3595 'u'=>'@',
3223 3596 ':'=>'',
3224 3597 );
3225 3598
3226 - $replaced_from = array_keys($replaced);
3227 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3228 - 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 +
3229 3622 }
3230 3623 }
3231 3624
3232 3625 if ( ! function_exists('wdk_get_gps'))
@@ -3254,9 +3647,17 @@
3254 3647
3255 3648 if(!isset($results[$address])) {
3256 3649 $results[$address] = NULL;
3257 3650 $url = 'https://nominatim.openstreetmap.org/search?format=json&q=' . $address;
3258 - $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);
3259 3660 $response = '';
3260 3661
3261 3662 // request failed
3262 3663 if ( is_wp_error( $request ) ) {
@@ -3412,8 +3813,32 @@
3412 3813 return false;
3413 3814 }
3414 3815 }
3415 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 +
3416 3841 if ( ! function_exists('wdk_filter_phone'))
3417 3842 {
3418 3843 // Validation phone
3419 3844 /**
@@ -3549,9 +3974,22 @@
3549 3974
3550 3975 $value = filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
3551 3976 $value = (float)str_replace(array(","," ",'&nbsp;'), "", $value);
3552 3977
3553 - 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);
3554 3992 }
3555 3993 }
3556 3994
3557 3995 if ( ! function_exists('wdk_currency_symbol'))
@@ -3684,9 +4122,20 @@
3684 4122 $user_data['wdk_position_title'] = wmvc_show_data('cacheduser_wdk_position_title', $row);
3685 4123 $user_data['agency_name'] = wmvc_show_data('cacheduser_agency_name', $row);
3686 4124 $user_data['description'] = wmvc_show_data('cacheduser_description', $row);
3687 4125 $user_data['user_url'] = wmvc_show_data('cacheduser_user_url', $row);
3688 - $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 + }
3689 4138
3690 4139 return $user_data;
3691 4140 }
3692 4141 }
@@ -3930,11 +4379,11 @@
3930 4379 $page_title,
3931 4380 $post_type
3932 4381 );
3933 4382 }
3934 -
3935 - $page = $wpdb->get_var( $sql );
3936 -
4383 + $page = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
4384 +
4385 +
3937 4386 if ( $page ) {
3938 4387 return get_post( $page, $output );
3939 4388 }
3940 4389
@@ -3998,9 +4447,9 @@
3998 4447 $output .= '<tr>';
3999 4448 foreach($var as $k => $v) {
4000 4449 if(count($columns) > 0 && !in_array($k, $columns))continue;
4001 4450
4002 - $output .= '<td><strong>' . $k . '</strong></td>';
4451 + $output .= '<td><strong>' . esc_html($k) . '</strong></td>';
4003 4452 }
4004 4453 $output .= '</tr>';
4005 4454 }
4006 4455
@@ -4007,13 +4456,14 @@
4007 4456 $output .= '<tr>';
4008 4457 foreach($var as $k => $v) {
4009 4458 if(count($columns) > 0 && !in_array($k, $columns))continue;
4010 4459
4011 - $output .= '<td>' . $v . '</td>';
4460 + $output .= '<td>' . esc_html($v) . '</td>';
4012 4461 }
4013 4462 $output .= '</tr>';
4014 4463 }
4015 4464 $output .= '</table>';
4465 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
4016 4466 echo $output;
4017 4467 }
4018 4468 }
4019 4469
@@ -4019,9 +4469,9 @@
4019 4469
4020 4470 if ( ! function_exists('wdk_move_gps'))
4021 4471 {
4022 4472 function wdk_move_gps($value) {
4023 - return $value+0.001 * rand(1, 9);
4473 + return $value+0.001 * wp_rand(1, 9);
4024 4474 }
4025 4475 }
4026 4476
4027 4477 if ( ! function_exists('wdk_get_near_location'))
@@ -4029,10 +4479,10 @@
4029 4479 function wdk_get_near_location($latitude, $longitude, $radius = 10000) {
4030 4480 // Convert radius from meters to degrees
4031 4481 $radiusInDegrees = $radius / 111000;
4032 4482
4033 - $u = mt_rand() / mt_getrandmax();
4034 - $v = mt_rand() / mt_getrandmax();
4483 + $u = wp_rand() / mt_getrandmax();
4484 + $v = wp_rand() / mt_getrandmax();
4035 4485 $w = $radiusInDegrees * sqrt($u);
4036 4486 $t = 2 * M_PI * $v;
4037 4487 $x = $w * cos($t);
4038 4488 $y = $w * sin($t);
@@ -4158,9 +4608,9 @@
4158 4608 // For french
4159 4609 $str = str_replace(array('â','é','è','û','ê', 'à','Â','ç','ï','î','ä','î'),
4160 4610 array('a','e','e','u','e', 'a','c','c','i','î','a','î'), $str);
4161 4611
4162 - $str = strip_tags(strtolower($str));
4612 + $str = wp_strip_all_tags(strtolower($str));
4163 4613
4164 4614
4165 4615 foreach ($trans as $key => $val)
4166 4616 {
@@ -4213,6 +4663,790 @@
4213 4663
4214 4664 return false;
4215 4665 }
4216 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 + }
4217 5451
4218 5452 ?>