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 +1355 -164 1.3.2 → 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,15 +593,29 @@
587 593 $columns[] = $column_name;
588 594 $external_columns[] = $column_name;
589 595 }
590 596
591 - if (isset($_GET_clone['search_rank_'.NONCE_KEY])) {
597 + if (isset($_GET_clone['search_rank'])) {
592 598 $column_name ='`rank`';
593 - $_GET_clone[$column_name] = $_GET_clone['search_rank_'.NONCE_KEY];
599 + $_GET_clone[$column_name] = $_GET_clone['search_rank'];
594 600 $columns[] = $column_name;
595 601 $external_columns[] = $column_name;
596 602 }
597 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 +
598 618 //$table_name = substr($model_name, 0, -2);
599 619 $columns_original = array();
600 620 foreach($columns as $key=>$val)
601 621 {
@@ -623,8 +643,10 @@
623 643 {
624 644 unset($_GET_clone['search']);
625 645 unset($_GET_clone['field_search']);
626 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 +
627 649 // For quick/smart search
628 650 if(wmvc_count($columns) > 0 && !empty($smart_search))
629 651 {
630 652 $gen_q = '';
@@ -682,8 +704,13 @@
682 704 /* location / categories */
683 705 if(!is_intval($smart_search)) {
684 706 $gen_q.="location_title LIKE '%$smart_search%' OR ";
685 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 +
686 713 }
687 714 /* get address and gps */
688 715 if(strlen($smart_search) > 5) {
689 716 $coordinates_center = wdk_get_gps($smart_search);
@@ -739,9 +766,9 @@
739 766
740 767 if(!empty($gen_q))
741 768 $WMVC->db->where("($gen_q)");
742 769 }
743 -
770 +
744 771 // For column search
745 772 if(isset($_GET_clone))
746 773 {
747 774 $gen_q = '';
@@ -756,43 +783,31 @@
756 783 // $col_name = $key;
757 784
758 785 if(strpos($key, 'skip') !== FALSE) continue;
759 786
760 - if(defined( 'WP_DEBUG' ) && WP_DEBUG)
761 - if(function_exists('pll_current_language'))
762 - {
763 - $lang_term_id = pll_current_language('term_id');
764 -
765 - if(is_numeric($lang_term_id))
766 - {
767 - $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);
768 - $WMVC->db->where("({$WMVC->db->prefix}term_relationships.term_taxonomy_id = $lang_term_id)");
769 - }
770 - }
771 -
772 787 if($key == 'field_booking_guest')
773 788 {
774 789 if(!$wdk_bookings_joinded){
775 - $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');
776 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
777 - $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');
778 793 $wdk_bookings_joinded = true;
779 794 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
780 - $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');
781 796 }
782 797
783 - $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 ";
784 799
785 800 }
786 801 elseif($key == 'field_booking_date_from')
787 802 {
788 803 if(!$wdk_bookings_joinded){
789 - $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');
790 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
791 - $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');
792 807 $wdk_bookings_joinded = true;
793 808 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
794 - $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');
795 810 }
796 811
797 812 if(wdk_is_date($val))
798 813 {
@@ -810,9 +825,9 @@
810 825 if(!get_option('wdk_bookings_is_hours_enabled')) {
811 826 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from'], 'Y-m-d H:i:s', 'Y-m-d');
812 827 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to'], 'Y-m-d H:i:s', 'Y-m-d');
813 828
814 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
829 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
815 830 SELECT post_id
816 831 FROM ".$WMVC->db->prefix."wdk_booking_reservation
817 832 WHERE
818 833 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -825,9 +840,9 @@
825 840 } else {
826 841 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from']);
827 842 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to']);
828 843
829 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
844 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
830 845 SELECT post_id
831 846 FROM ".$WMVC->db->prefix."wdk_booking_reservation
832 847 WHERE
833 848 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -842,13 +857,13 @@
842 857 }
843 858 elseif($key == 'field_booking_date_to')
844 859 {
845 860 if(!$wdk_bookings_joinded){
846 - $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');
847 - $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');
848 863 $wdk_bookings_joinded = true;
849 864 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
850 - $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');
851 866 }
852 867
853 868 if(wdk_is_date($val))
854 869 {
@@ -864,9 +879,33 @@
864 879 }
865 880 elseif(substr($key, -8) == '_exactly')
866 881 {
867 882 $col_name = substr($key, 0, -8);
868 - $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 + }
869 908 }
870 909 elseif(substr($key, -4) == '_max')
871 910 {
872 911 $col_name = substr($key, 0, -4);
@@ -956,9 +995,9 @@
956 995 }
957 996
958 997 if(is_array($val)) {
959 998
960 - $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');
961 1000 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
962 1001 $sql_search = '';
963 1002 foreach ($val as $v) {
964 1003 if(empty($v)) continue;
@@ -973,9 +1012,9 @@
973 1012 if(!empty($sql_search))
974 1013 $gen_q.=" ( ".$sql_search." ) AND ";
975 1014
976 1015 } elseif(is_string($val) && !empty($val)) {
977 - $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');
978 1017 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
979 1018 $sql_search =" ".$WMVC->listing_m->_table_name.".`user_id_editor` = ".intval($val)." OR `".$WMVC->db->prefix."wdk_listings_users`.`user_id` = ".intval($val)." ";
980 1019 $gen_q.=" ( ".$sql_search." ) AND ";
981 1020 }
@@ -1132,10 +1171,15 @@
1132 1171
1133 1172 if(!empty($sql_search))
1134 1173 $gen_q.=" ( ".$sql_search." ) AND ";
1135 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 + }
1136 1181 }
1137 -
1138 1182 }
1139 1183
1140 1184 $gen_q = substr($gen_q, 0, -5);
1141 1185
@@ -1142,8 +1186,20 @@
1142 1186 if(!empty($gen_q))
1143 1187 $WMVC->db->where("($gen_q)");
1144 1188 }
1145 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 +
1146 1202 // [RECTANGLE SEARCH]
1147 1203 if(isset($_GET_clone['rectangle_ne']) && isset($_GET_clone['rectangle_sw']))
1148 1204 {
1149 1205 if(wdk_is_gps($_GET_clone['rectangle_ne']) && wdk_is_gps($_GET_clone['rectangle_sw'])) {
@@ -1157,12 +1213,92 @@
1157 1213 }
1158 1214 // [/RECTANGLE SEARCH]
1159 1215
1160 1216 // order
1161 - if(isset($_GET_clone['order_by']))
1162 - {
1163 - $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_listings.post_id', $_GET_clone['order_by']);
1164 - $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 +
1165 1301 }
1166 1302
1167 1303 }
1168 1304 }
@@ -1179,9 +1315,9 @@
1179 1315
1180 1316 if(isset($custom_parameters['order_by'])) {
1181 1317
1182 1318 if(isset($_GET_clone['order_by']) && !empty($_GET_clone['order_by'])) {
1183 - $_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']);
1184 1320 } else {
1185 1321 $_GET_clone['order_by'] = $custom_parameters['order_by'];
1186 1322 }
1187 1323
@@ -1195,9 +1331,9 @@
1195 1331 $WMVC->model($model_name);
1196 1332
1197 1333 $smart_search = '';
1198 1334 if(isset($_GET_clone['profile_search']))
1199 - $smart_search = sanitize_text_field($_GET_clone['profile_search']);
1335 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['profile_search']));
1200 1336
1201 1337 $available_fields = array('user_login','user_nicename','user_email','user_url','display_name');
1202 1338
1203 1339 if(isset($_GET_clone['is_activated'])){
@@ -1364,9 +1500,9 @@
1364 1500 // order
1365 1501 if(isset($_GET_clone['order_by']))
1366 1502 {
1367 1503 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_favorite.post_id', $_GET_clone['order_by']);
1368 - $WMVC->db->order_by($_GET_clone['order_by']);
1504 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by'])));
1369 1505 }
1370 1506
1371 1507 }
1372 1508 }
@@ -1382,9 +1518,9 @@
1382 1518 //$WMVC->model('listing_m');
1383 1519
1384 1520 $smart_search = '';
1385 1521 if(isset($_GET_clone['search']))
1386 - $smart_search = sanitize_text_field($_GET_clone['search']);
1522 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['search']));
1387 1523
1388 1524 $available_fields = $WMVC->$model_name->get_available_fields();
1389 1525
1390 1526 /* Пet column names from wdk_package and add to allow search +
@@ -1495,9 +1631,9 @@
1495 1631 $detect_date = strtotime($gen_search);
1496 1632
1497 1633 if(wdk_payments_is_date($val) && $detect_date > 1000)
1498 1634 {
1499 - $gen_search = date('Y-m-d H:i:s', $detect_date);
1635 + $gen_search = gmdate('Y-m-d H:i:s', $detect_date);
1500 1636 $gen_q.=$col_name." > '".$gen_search."' AND ";
1501 1637 }
1502 1638 else
1503 1639 {
@@ -1535,9 +1671,9 @@
1535 1671 // order
1536 1672 if(isset($_GET_clone['order_by']))
1537 1673 {
1538 1674 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_messages.post_id', $_GET_clone['order_by']);
1539 - $WMVC->db->order_by($_GET_clone['order_by']);
1675 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by']), true));
1540 1676 }
1541 1677
1542 1678 }
1543 1679 }
@@ -1544,9 +1680,9 @@
1544 1680
1545 1681 function wdk_date() {
1546 1682 $date_format = get_option('date_format');
1547 1683 $time_format = get_option('time_format');
1548 - $date = date("{$date_format} {$time_format}", current_time('timestamp'));
1684 + $date = gmdate("{$date_format} {$time_format}", current_time('timestamp'));
1549 1685 return $date;
1550 1686 }
1551 1687
1552 1688 if(!function_exists('wdk_placeholder_image_src')) {
@@ -1570,18 +1706,20 @@
1570 1706
1571 1707 if(isset($_GET[$page_var]))
1572 1708 $current_page = intval(wmvc_xss_clean($_GET[$page_var]));
1573 1709
1574 - if(!isset($texts['previous_page']))$texts['previous_page'] = 'Previous page';
1575 - 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');
1576 1712 if(!isset($texts['first_page']))$texts['first_page'] = '';
1577 1713 if(!isset($texts['last_page']))$texts['last_page'] = '';
1578 - if(!isset($texts['items']))$texts['items'] = 'items';
1714 + if(!isset($texts['items']))$texts['items'] = esc_html__('items', 'wpdirectorykit');
1579 1715
1580 1716 if(empty($current_page))$current_page = 1;
1581 1717
1582 1718 // get url
1583 - $url = strtok($_SERVER["REQUEST_URI"], '?');
1719 + $url = strtok(wdk_server_current_url(), '?');
1720 +
1721 +
1584 1722 $qs_parameters = wmvc_xss_clean( $_GET );
1585 1723 unset($qs_parameters[$page_var]);
1586 1724 $qs_part = http_build_query($qs_parameters);
1587 1725 $url = wdk_url_suffix($url, $qs_part);
@@ -1604,16 +1742,16 @@
1604 1742
1605 1743 $output .= '<div class="nav-links">';
1606 1744
1607 1745 if($enable_latest_first && $current_page-1 > 0)
1608 - $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>';
1609 1747
1610 1748 if ($current_page-1 > 0) {
1611 1749
1612 - $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>';
1613 1751 } elseif($enable_compact)
1614 1752 {
1615 - $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>';
1616 1754 }
1617 1755
1618 1756 if (!$enable_compact) {
1619 1757 for ($i = 1 ; $i <= $total_pages; $i++) {
@@ -1621,9 +1759,9 @@
1621 1759 if(($current_page-$limit_items) <= $i && ($current_page+$limit_items) >= $i) {
1622 1760 if (($current_page == $i)) {
1623 1761 $output.= '<span aria-current="page" class="page-numbers current">'.$i.'</span>';
1624 1762 } else {
1625 - $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>';
1626 1764 }
1627 1765 }
1628 1766 }
1629 1767 } else {
@@ -1631,17 +1769,17 @@
1631 1769 }
1632 1770
1633 1771 if($current_page+1 <= $total_pages)
1634 1772 {
1635 - $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>';
1636 1774 }
1637 1775 elseif($enable_compact)
1638 1776 {
1639 - $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>';
1640 1778 }
1641 1779
1642 1780 if($enable_latest_first && $current_page+1 <= $total_pages)
1643 - $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>';
1644 1782
1645 1783
1646 1784 $output.= '</div>';
1647 1785 $output.= '</nav>';
@@ -1696,22 +1834,27 @@
1696 1834 }
1697 1835
1698 1836 ?>
1699 1837 <div class="wdk-col wdk-col-btns">
1700 - <div class="wdk-field wdk-field-btn">
1838 + <div class="wdk-field wdk-field-btn">
1701 1839 <div class="wdk-field-group wdk-field-group-additional">
1702 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>
1703 - <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' />
1704 1842 </div>
1705 1843 <div class="wdk-field-group wdk-field-group-reset">
1706 - <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>
1707 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;?>
1708 1851 <div class="wdk-field-group wdk-field-group-search">
1709 - <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>
1710 1853
1711 1854 <?php if(function_exists('run_wdk_save_search') && get_option('wdk_save_search_show_on_searchform')):?>
1712 1855 <div class="section-widget-control right">
1713 - <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">
1714 1857 <i class="fas fa-save" aria-hidden="true"></i>
1715 1858 <i class="fa fa-spinner fa-spin fa-ajax-indicator"></i>
1716 1859 </a>
1717 1860 </div>
@@ -1716,8 +1859,9 @@
1716 1859 </a>
1717 1860 </div>
1718 1861 <?php endif;?>
1719 1862 </div>
1863 +
1720 1864 </div>
1721 1865 </div>
1722 1866 <div id='wdk-form-additional' class="wdk-col" style="<?php echo esc_attr($form_closed) ;?>">
1723 1867 <div class="wdk-row">
@@ -1760,9 +1904,9 @@
1760 1904
1761 1905 if(empty($selected))
1762 1906 $selected='';
1763 1907
1764 - $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/>';
1765 1909
1766 1910 $skip_id = '';
1767 1911 //load javascript library
1768 1912 if($counter==0)
@@ -1769,39 +1913,39 @@
1769 1913 {
1770 1914 wp_enqueue_script('wdk-treefield');
1771 1915 wp_enqueue_style('wdk-treefield');
1772 1916 }
1773 - ?>
1774 - <script>
1775 - jQuery(document).ready(function($) {
1776 - $('#wdktreeelem<?php echo esc_js($counter);?>:not(.init)').wdkTreefield({
1777 - 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')) . "',
1778 1922 ajax_param: {
1779 - "page": 'wdk_frontendajax',
1780 - "function": 'treefieldid',
1781 - "action": 'wdk_public_action',
1782 - "table": '<?php echo esc_js($table); ?>',
1783 - "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1784 - "start_id": '<?php if(!empty($filter_ids)) esc_js($selected); else echo ""; ?>',
1785 - "empty_value": '<?php echo esc_js($empty_value); ?>',
1786 - "user_check": '<?php echo esc_js($user_check); ?>',
1787 - "sql_where": '<?php echo esc_js($sql_where); ?>',
1788 - "hide_fields": '<?php echo esc_js($hide_fields); ?>'
1789 - },
1790 - attribute_id: '<?php echo esc_js($attribute_id); ?>',
1791 - language_id: '<?php echo esc_js($language_id); ?>',
1792 - attribute_value: '<?php echo esc_js($column); ?>',
1793 - 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: '',
1794 1939 empty_value: ' - ',
1795 - text_search: '<?php esc_html_e('Search term', 'wpdirectorykit');?>',
1796 - 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') . "',
1797 1942 callback_selected: function(key) {
1798 - $('#wdktreeelem<?php echo esc_js($counter);?>').trigger("change");
1943 + $('#wdktreeelem" . esc_js($counter) . "').trigger('change');
1799 1944 }
1800 1945 }).addClass('init');
1801 - });
1802 - </script>
1803 - <?php
1946 + });"
1947 + );
1804 1948 $counter++;
1805 1949 return $form;
1806 1950 }
1807 1951 }
@@ -1869,9 +2013,9 @@
1869 2013 if(empty($values)) {
1870 2014 $values = $empty_value;
1871 2015 }
1872 2016
1873 - $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/>';
1874 2018
1875 2019 $skip_id = '';
1876 2020 //load javascript library
1877 2021 if($counter==0)
@@ -1882,13 +2026,14 @@
1882 2026 ?>
1883 2027 <script>
1884 2028 jQuery(document).ready(function($) {
1885 2029 $('#wdktreeelem_checkbox<?php echo esc_js($counter);?>:not(.init)').wdkTreefieldCheckboxes({
1886 - ajax_url: '<?php echo admin_url('admin-ajax.php'); ?>',
2030 + ajax_url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
1887 2031 ajax_param: {
1888 2032 "page": 'wdk_frontendajax',
1889 2033 "function": 'treefieldid_checkboxes',
1890 2034 "action": 'wdk_public_action',
2035 + "wdk_secure": '<?php echo esc_js(wp_create_nonce( 'wdk_secure_treefieldid_checkboxes' ));?>',
1891 2036 "table": '<?php echo esc_js($table); ?>',
1892 2037 "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1893 2038 "empty_value": '<?php echo esc_js($empty_value); ?>',
1894 2039 "user_check": '<?php echo esc_js($user_check); ?>',
@@ -1917,14 +2062,19 @@
1917 2062 if ( ! function_exists('wdk_filter_decimal'))
1918 2063 {
1919 2064 function wdk_filter_decimal($string = '')
1920 2065 {
1921 - if(substr($string, -3, 3) === ".00") {
1922 - return substr($string, 0, -3);
1923 - }
1924 - if(substr($string, -3, 1) === "." && substr($string, -1, 1) === "0") {
1925 - return substr($string, 0, -1);
1926 - }
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 + }
1927 2077
1928 2078 return $string;
1929 2079 }
1930 2080 }
@@ -2052,9 +2202,9 @@
2052 2202 }
2053 2203
2054 2204 /* check is date on strtotime */
2055 2205 if((bool)strtotime($date)){
2056 - return date($return_format, strtotime($date));
2206 + return gmdate($return_format, strtotime($date));
2057 2207 }
2058 2208
2059 2209 return false;
2060 2210 }
@@ -2074,9 +2224,100 @@
2074 2224 return $base_url.$extension_url;
2075 2225 }
2076 2226 }
2077 2227
2228 +
2078 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 +/**
2079 2320 * Insert an attachment from an URL address.
2080 2321 *
2081 2322 * @param String $url
2082 2323 * @param Int $parent_post_id
@@ -2098,14 +2339,14 @@
2098 2339 $filename = substr($filename, 0, strpos($filename, '?'));
2099 2340 }
2100 2341
2101 2342 /* if unsoported extension */
2102 - 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){
2103 2344 $data = getimagesizefromstring($response['body']);
2104 2345 if(!$data) return false;
2105 2346 if(empty($data['mime'])) return false;
2106 2347
2107 - $filename = time().rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2348 + $filename = time().wp_rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2108 2349 }
2109 2350 $upload = wp_upload_bits( $filename, null, $response['body'] );
2110 2351
2111 2352 if( !empty( $upload['error'] ) ) {
@@ -2197,17 +2438,12 @@
2197 2438 */
2198 2439
2199 2440 function wdk_generate_profile_permalink($profile = array())
2200 2441 {
2201 -
2202 2442 $profile_slug = '';
2203 - if(wmvc_show_data('user_login', $profile, false)){
2204 - $profile_slug = wmvc_show_data('user_login', $profile);
2205 - if(wmvc_show_data('wdk_slug', $profile))
2206 - $profile_slug = wmvc_show_data('wdk_slug', $profile);
2207 - } else if(is_intval($profile)){
2443 + if(is_intval($profile)){
2208 2444 $profile_data = get_userdata($profile);
2209 - if(wmvc_show_data('wdk_slug', $profile, false)){
2445 + if(wmvc_show_data('wdk_slug', $profile_data, false)){
2210 2446 $profile_slug = wmvc_show_data('wdk_slug', $profile);
2211 2447 }elseif(wmvc_show_data('user_login', $profile_data, false)){
2212 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2213 2449 } else {
@@ -2212,10 +2448,14 @@
2212 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2213 2449 } else {
2214 2450 $profile_slug = $profile;
2215 2451 }
2216 - }
2217 -
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 +
2218 2458 $user_profile_page = get_option('wdk_membership_profile_preview_page');
2219 2459 if(!$user_profile_page) {
2220 2460 return '#';
2221 2461 }
@@ -2470,19 +2710,19 @@
2470 2710 <!-- Your add & remove file links -->
2471 2711 <p class="hide-if-no-js">
2472 2712 <a class="upload-custom-img <?php if ( $you_have_file ) { echo 'hidden'; } ?>"
2473 2713 href="<?php echo esc_url($upload_link) ?>">
2474 - <?php echo esc_html__('Select file','wmvc_win') ?>
2714 + <?php echo esc_html__('Select file','wpdirectorykit') ?>
2475 2715 </a>
2476 2716 <a class="delete-custom-img <?php if ( ! $you_have_file ) { echo 'hidden'; } ?>"
2477 2717 href="#">
2478 - <?php echo esc_html__('Remove file','wmvc_win') ?>
2718 + <?php echo esc_html__('Remove all files','wpdirectorykit') ?>
2479 2719 </a>
2480 2720 </p>
2481 2721 <?php //endif; ?>
2482 2722
2483 2723 <!-- A hidden input to set and post the chosen file id -->
2484 - <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); ?>" />
2485 2725 </div>
2486 2726
2487 2727 <?php
2488 2728 $custom_js ='';
@@ -2490,8 +2730,9 @@
2490 2730 if( typeof jQuery.fn.wpMediaElementFile == 'function')
2491 2731 $('#".esc_js($field_name)."meta-box-id.postbox-upload').wpMediaElementFile();
2492 2732 });";
2493 2733
2734 +// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2494 2735 echo "<script>".$custom_js."</script>";
2495 2736
2496 2737 ?>
2497 2738
@@ -2542,19 +2783,15 @@
2542 2783 function wdk_upload_multi_files($field_name, $image_ids='', $texts = array())
2543 2784 {
2544 2785 static $media_element_counter = 0;
2545 2786
2546 - if(!isset($texts['file_select']))$texts['file_select'] = esc_html__('Select file','wmvc_win');
2547 - 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');
2548 2789
2549 2790 $media_element_counter++;
2550 2791
2551 2792 $img_field = $field_name.'_'.$media_element_counter;
2552 2793
2553 - wp_register_script( 'wpmediaelement_file', WPDIRECTORYKIT_URL . 'admin/js/jquery.wpmediaelement_file.js', array( 'jquery' ), false, false );
2554 - wp_enqueue_script( 'wpmediaelement_file' );
2555 - wp_enqueue_media();
2556 -
2557 2794 wp_enqueue_script( 'wpmediamultiple' );
2558 2795 wp_enqueue_script( 'jquery-ui-mouse' );
2559 2796 wp_enqueue_media();
2560 2797
@@ -2591,9 +2828,9 @@
2591 2828 <!-- Your image container, which can be manipulated with js -->
2592 2829 <div class="custom-img-container winter_mvc-media">
2593 2830 <?php if($you_have_img)foreach($your_img_src as $image_id => $img_src) : ?>
2594 2831 <div class="winter_mvc-media-card" data-media-id="<?php echo esc_attr($image_id);?>">
2595 - <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"/>
2596 2833 <a href="#" class="remove"></a>
2597 2834 </div>
2598 2835 <?php endforeach; ?>
2599 2836 </div>
@@ -2613,9 +2850,9 @@
2613 2850 </p>
2614 2851 <?php //endif; ?>
2615 2852
2616 2853 <!-- A hidden input to set and post the chosen image id -->
2617 - <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); ?>" />
2618 2855 </div>
2619 2856 <?php
2620 2857 $custom_js ='';
2621 2858 $custom_js .=" jQuery(function($) {
@@ -2621,11 +2858,14 @@
2621 2858 $custom_js .=" jQuery(function($) {
2622 2859 if( typeof jQuery.fn.wpMediaMultiple == 'function')
2623 2860 $('#".esc_js($field_name)."meta-box-id.postbox-upload-multiple').wpMediaMultiple({
2624 2861 frame: {
2625 - 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'))."',
2626 2863 button: '".esc_js(__('Use this media','wpdirectorykit'))."',
2627 - }
2864 + },
2865 + library: {
2866 + type: ['application', 'image', 'video']
2867 + },
2628 2868 });
2629 2869 /* order */
2630 2870 var re_order = function(media_element){
2631 2871 var list_media = '';
@@ -2652,8 +2892,9 @@
2652 2892 })
2653 2893 });
2654 2894 ";
2655 2895
2896 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2656 2897 echo "<script>".$custom_js."</script>";
2657 2898
2658 2899 ?>
2659 2900
@@ -2734,8 +2975,59 @@
2734 2975
2735 2976 }
2736 2977 }
2737 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 +
2738 3030 if ( ! function_exists('wdk_recaptcha_field'))
2739 3031 {
2740 3032 function wdk_recaptcha_field($is_compact=false, $style="", $load_script=true)
2741 3033 {
@@ -2745,9 +3037,16 @@
2745 3037 if(get_option('wdk_recaptcha_site_key') !== FALSE && get_option('wdk_recaptcha_secret_key') !== NULL)
2746 3038 {
2747 3039 if($load_script && $counter===0)
2748 3040 {
2749 - 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 +
2750 3049 }
2751 3050 $counter++;
2752 3051
2753 3052 $compact_tag='';
@@ -2759,15 +3058,15 @@
2759 3058 }
2760 3059
2761 3060 $recaptcha_array[$counter] = array('size'=>$size_tag);
2762 3061
2763 - 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>';
2764 3063 ?>
2765 3064
2766 3065 <script>
2767 3066 <?php if($counter===1)echo 'var ';?>CaptchaCallback = function(){
2768 3067 <?php for($j=1;$j<=$counter;$j++): ?>
2769 - 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')); ?>'});
2770 3069 <?php endfor; ?>
2771 3070 };
2772 3071 </script>
2773 3072
@@ -2869,9 +3168,9 @@
2869 3168 if(is_array($val))
2870 3169 {
2871 3170 return wdk_clean($_POST);
2872 3171 }
2873 - else
3172 + elseif(is_string($val))
2874 3173 {
2875 3174 if(strpos($val, '<iframe') === 0)
2876 3175 $val = str_replace("'",'"', $val);
2877 3176
@@ -2910,9 +3209,9 @@
2910 3209 if(is_array($val))
2911 3210 {
2912 3211 $arr_cleaned[sanitize_text_field($key)] = wdk_clean($val);
2913 3212 }
2914 - else
3213 + elseif(is_string($val))
2915 3214 {
2916 3215 $arr_cleaned[sanitize_text_field($key)] = wp_kses_post($val);
2917 3216 }
2918 3217
@@ -2922,8 +3221,34 @@
2922 3221
2923 3222 return $arr_cleaned;
2924 3223 }
2925 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 +
2926 3251 /*
2927 3252 <select class="form-control" name="<?php echo 'control_operator_'.$i_fieldnum; ?>">
2928 3253 <option value="CONTAINS">CONTAINS</option>
2929 3254 <option value="NOT_CONTAINS">NOT_CONTAINS</option>
@@ -2964,9 +3289,9 @@
2964 3289
2965 3290 if(is_array($filter_ids)) $filter_ids = implode(',', $filter_ids);
2966 3291
2967 3292 static $counter = 0;
2968 - $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="">';
2969 3294
2970 3295
2971 3296 if(false)
2972 3297 if( $column_key == 'idcategory') {
@@ -2980,9 +3305,9 @@
2980 3305
2981 3306 $ids = array();
2982 3307 foreach($selected as $selected_item) {
2983 3308 if(!empty($selected_item)) {
2984 - $ids [] = $selected_item;
3309 + $ids [] = (int) $selected_item;
2985 3310 }
2986 3311 }
2987 3312
2988 3313 /* where in */
@@ -2993,15 +3318,19 @@
2993 3318
2994 3319 $results = $WMVC->$table->get();
2995 3320 foreach ($results as $item) {
2996 3321 if($item)
2997 - $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>';
2998 3325 }
2999 3326 }
3000 3327 } elseif(is_intval($selected)) {
3001 3328 $db_item = $WMVC->$table->get($selected, TRUE);
3002 3329 if($db_item)
3003 - $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>';
3004 3333 }
3005 3334 } else {
3006 3335 //$form .= '<option value="" selected="selected">'.esc_html__('Not selected', 'wpdirectorykit').'</option>';
3007 3336 }
@@ -3009,11 +3338,11 @@
3009 3338
3010 3339 //load javascript library
3011 3340 if($counter==0)
3012 3341 {
3013 - wp_enqueue_script('select2');
3342 + wp_enqueue_script('select2-select2');
3014 3343 wp_enqueue_script('wdk-select2');
3015 - wp_enqueue_style('select2');
3344 + wp_enqueue_style('select2-select2');
3016 3345 }
3017 3346 ?>
3018 3347 <?php
3019 3348 $counter++;
@@ -3057,11 +3386,11 @@
3057 3386
3058 3387 //load javascript library
3059 3388 if($counter==0)
3060 3389 {
3061 - wp_enqueue_script('select2');
3390 + wp_enqueue_script('select2-select2');
3062 3391 wp_enqueue_script('wdk-select2');
3063 - wp_enqueue_style('select2');
3392 + wp_enqueue_style('select2-select2');
3064 3393 }
3065 3394 ?>
3066 3395 <?php
3067 3396 $counter++;
@@ -3139,11 +3468,30 @@
3139 3468 'r'=>'llll',
3140 3469 'u'=>'x',
3141 3470 );
3142 3471
3143 - $replaced_from = array_keys($replaced);
3144 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3145 - 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);
3146 3494 }
3147 3495 }
3148 3496
3149 3497 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3184,11 +3532,29 @@
3184 3532 'u'=>'@',
3185 3533 ':'=>'',
3186 3534 );
3187 3535
3188 - $replaced_from = array_keys($replaced);
3189 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3190 - 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);
3191 3557 }
3192 3558 }
3193 3559
3194 3560 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3229,11 +3595,31 @@
3229 3595 'u'=>'@',
3230 3596 ':'=>'',
3231 3597 );
3232 3598
3233 - $replaced_from = array_keys($replaced);
3234 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3235 - 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 +
3236 3622 }
3237 3623 }
3238 3624
3239 3625 if ( ! function_exists('wdk_get_gps'))
@@ -3261,9 +3647,17 @@
3261 3647
3262 3648 if(!isset($results[$address])) {
3263 3649 $results[$address] = NULL;
3264 3650 $url = 'https://nominatim.openstreetmap.org/search?format=json&q=' . $address;
3265 - $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);
3266 3660 $response = '';
3267 3661
3268 3662 // request failed
3269 3663 if ( is_wp_error( $request ) ) {
@@ -3419,8 +3813,32 @@
3419 3813 return false;
3420 3814 }
3421 3815 }
3422 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 +
3423 3841 if ( ! function_exists('wdk_filter_phone'))
3424 3842 {
3425 3843 // Validation phone
3426 3844 /**
@@ -3556,9 +3974,22 @@
3556 3974
3557 3975 $value = filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
3558 3976 $value = (float)str_replace(array(","," ",'&nbsp;'), "", $value);
3559 3977
3560 - 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);
3561 3992 }
3562 3993 }
3563 3994
3564 3995 if ( ! function_exists('wdk_currency_symbol'))
@@ -3691,9 +4122,20 @@
3691 4122 $user_data['wdk_position_title'] = wmvc_show_data('cacheduser_wdk_position_title', $row);
3692 4123 $user_data['agency_name'] = wmvc_show_data('cacheduser_agency_name', $row);
3693 4124 $user_data['description'] = wmvc_show_data('cacheduser_description', $row);
3694 4125 $user_data['user_url'] = wmvc_show_data('cacheduser_user_url', $row);
3695 - $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 + }
3696 4138
3697 4139 return $user_data;
3698 4140 }
3699 4141 }
@@ -3937,11 +4379,11 @@
3937 4379 $page_title,
3938 4380 $post_type
3939 4381 );
3940 4382 }
3941 -
3942 - $page = $wpdb->get_var( $sql );
3943 -
4383 + $page = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
4384 +
4385 +
3944 4386 if ( $page ) {
3945 4387 return get_post( $page, $output );
3946 4388 }
3947 4389
@@ -4005,9 +4447,9 @@
4005 4447 $output .= '<tr>';
4006 4448 foreach($var as $k => $v) {
4007 4449 if(count($columns) > 0 && !in_array($k, $columns))continue;
4008 4450
4009 - $output .= '<td><strong>' . $k . '</strong></td>';
4451 + $output .= '<td><strong>' . esc_html($k) . '</strong></td>';
4010 4452 }
4011 4453 $output .= '</tr>';
4012 4454 }
4013 4455
@@ -4014,13 +4456,14 @@
4014 4456 $output .= '<tr>';
4015 4457 foreach($var as $k => $v) {
4016 4458 if(count($columns) > 0 && !in_array($k, $columns))continue;
4017 4459
4018 - $output .= '<td>' . $v . '</td>';
4460 + $output .= '<td>' . esc_html($v) . '</td>';
4019 4461 }
4020 4462 $output .= '</tr>';
4021 4463 }
4022 4464 $output .= '</table>';
4465 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
4023 4466 echo $output;
4024 4467 }
4025 4468 }
4026 4469
@@ -4026,9 +4469,9 @@
4026 4469
4027 4470 if ( ! function_exists('wdk_move_gps'))
4028 4471 {
4029 4472 function wdk_move_gps($value) {
4030 - return $value+0.001 * rand(1, 9);
4473 + return $value+0.001 * wp_rand(1, 9);
4031 4474 }
4032 4475 }
4033 4476
4034 4477 if ( ! function_exists('wdk_get_near_location'))
@@ -4036,10 +4479,10 @@
4036 4479 function wdk_get_near_location($latitude, $longitude, $radius = 10000) {
4037 4480 // Convert radius from meters to degrees
4038 4481 $radiusInDegrees = $radius / 111000;
4039 4482
4040 - $u = mt_rand() / mt_getrandmax();
4041 - $v = mt_rand() / mt_getrandmax();
4483 + $u = wp_rand() / mt_getrandmax();
4484 + $v = wp_rand() / mt_getrandmax();
4042 4485 $w = $radiusInDegrees * sqrt($u);
4043 4486 $t = 2 * M_PI * $v;
4044 4487 $x = $w * cos($t);
4045 4488 $y = $w * sin($t);
@@ -4165,9 +4608,9 @@
4165 4608 // For french
4166 4609 $str = str_replace(array('â','é','è','û','ê', 'à','Â','ç','ï','î','ä','î'),
4167 4610 array('a','e','e','u','e', 'a','c','c','i','î','a','î'), $str);
4168 4611
4169 - $str = strip_tags(strtolower($str));
4612 + $str = wp_strip_all_tags(strtolower($str));
4170 4613
4171 4614
4172 4615 foreach ($trans as $key => $val)
4173 4616 {
@@ -4256,6 +4699,754 @@
4256 4699
4257 4700 return false;
4258 4701 }
4259 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 + }
4260 5451
4261 5452 ?>