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 +1258 -139 1.3.6 → 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'] = wdk_clean($_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);
@@ -759,28 +786,28 @@
759 786
760 787 if($key == 'field_booking_guest')
761 788 {
762 789 if(!$wdk_bookings_joinded){
763 - $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');
764 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
765 - $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');
766 793 $wdk_bookings_joinded = true;
767 794 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
768 - $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');
769 796 }
770 797
771 - $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 ";
772 799
773 800 }
774 801 elseif($key == 'field_booking_date_from')
775 802 {
776 803 if(!$wdk_bookings_joinded){
777 - $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');
778 - $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
779 - $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');
780 807 $wdk_bookings_joinded = true;
781 808 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
782 - $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');
783 810 }
784 811
785 812 if(wdk_is_date($val))
786 813 {
@@ -798,9 +825,9 @@
798 825 if(!get_option('wdk_bookings_is_hours_enabled')) {
799 826 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from'], 'Y-m-d H:i:s', 'Y-m-d');
800 827 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to'], 'Y-m-d H:i:s', 'Y-m-d');
801 828
802 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
829 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
803 830 SELECT post_id
804 831 FROM ".$WMVC->db->prefix."wdk_booking_reservation
805 832 WHERE
806 833 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -813,9 +840,9 @@
813 840 } else {
814 841 $gen_search_from = wdk_normalize_date_db($_GET_clone['field_booking_date_from']);
815 842 $gen_search_to = wdk_normalize_date_db($_GET_clone['field_booking_date_to']);
816 843
817 - $gen_q.= $WMVC->listing_m->_table_name.".post_id NOT IN (
844 + $gen_q.= $WMVC->db->prefix."posts.ID NOT IN (
818 845 SELECT post_id
819 846 FROM ".$WMVC->db->prefix."wdk_booking_reservation
820 847 WHERE
821 848 ".$WMVC->db->prefix."wdk_booking_reservation.is_approved = 1
@@ -830,13 +857,13 @@
830 857 }
831 858 elseif($key == 'field_booking_date_to')
832 859 {
833 860 if(!$wdk_bookings_joinded){
834 - $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');
835 - $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');
836 863 $wdk_bookings_joinded = true;
837 864 $gen_q.= $WMVC->db->prefix.'wdk_booking_price.is_activated = 1 AND ';
838 - $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');
839 866 }
840 867
841 868 if(wdk_is_date($val))
842 869 {
@@ -852,8 +879,15 @@
852 879 }
853 880 elseif(substr($key, -8) == '_exactly')
854 881 {
855 882 $col_name = substr($key, 0, -8);
883 +
884 + if(is_string($val) && strpos($val, ',') !== FALSE){
885 + $val =explode(',', $val);
886 + } elseif(is_string($val)){
887 + $val =array($val);
888 + }
889 +
856 890 if(is_array($val))
857 891 {
858 892 $sql_search = '';
859 893 foreach ($val as $v) {
@@ -961,9 +995,9 @@
961 995 }
962 996
963 997 if(is_array($val)) {
964 998
965 - $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');
966 1000 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
967 1001 $sql_search = '';
968 1002 foreach ($val as $v) {
969 1003 if(empty($v)) continue;
@@ -978,9 +1012,9 @@
978 1012 if(!empty($sql_search))
979 1013 $gen_q.=" ( ".$sql_search." ) AND ";
980 1014
981 1015 } elseif(is_string($val) && !empty($val)) {
982 - $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');
983 1017 $WMVC->db->distinct($WMVC->listing_m->_table_name.'.post_id');
984 1018 $sql_search =" ".$WMVC->listing_m->_table_name.".`user_id_editor` = ".intval($val)." OR `".$WMVC->db->prefix."wdk_listings_users`.`user_id` = ".intval($val)." ";
985 1019 $gen_q.=" ( ".$sql_search." ) AND ";
986 1020 }
@@ -1137,10 +1171,15 @@
1137 1171
1138 1172 if(!empty($sql_search))
1139 1173 $gen_q.=" ( ".$sql_search." ) AND ";
1140 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 + }
1141 1181 }
1142 -
1143 1182 }
1144 1183
1145 1184 $gen_q = substr($gen_q, 0, -5);
1146 1185
@@ -1154,9 +1193,8 @@
1154 1193 $lang_term_id = pll_current_language('term_id');
1155 1194
1156 1195 if(is_numeric($lang_term_id))
1157 1196 {
1158 - //echo $lang_term_id.'<br />';
1159 1197 $WMVC->db->join($WMVC->db->prefix.'term_relationships ON '.$WMVC->db->prefix.'posts.ID = '.$WMVC->db->prefix.'term_relationships.object_id', NULL, NULL);
1160 1198 $WMVC->db->where("({$WMVC->db->prefix}term_relationships.term_taxonomy_id = $lang_term_id)");
1161 1199 }
1162 1200 }
@@ -1175,12 +1213,92 @@
1175 1213 }
1176 1214 // [/RECTANGLE SEARCH]
1177 1215
1178 1216 // order
1179 - if(isset($_GET_clone['order_by']))
1180 - {
1181 - $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_listings.post_id', $_GET_clone['order_by']);
1182 - $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 +
1183 1301 }
1184 1302
1185 1303 }
1186 1304 }
@@ -1197,9 +1315,9 @@
1197 1315
1198 1316 if(isset($custom_parameters['order_by'])) {
1199 1317
1200 1318 if(isset($_GET_clone['order_by']) && !empty($_GET_clone['order_by'])) {
1201 - $_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']);
1202 1320 } else {
1203 1321 $_GET_clone['order_by'] = $custom_parameters['order_by'];
1204 1322 }
1205 1323
@@ -1213,9 +1331,9 @@
1213 1331 $WMVC->model($model_name);
1214 1332
1215 1333 $smart_search = '';
1216 1334 if(isset($_GET_clone['profile_search']))
1217 - $smart_search = sanitize_text_field($_GET_clone['profile_search']);
1335 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['profile_search']));
1218 1336
1219 1337 $available_fields = array('user_login','user_nicename','user_email','user_url','display_name');
1220 1338
1221 1339 if(isset($_GET_clone['is_activated'])){
@@ -1382,9 +1500,9 @@
1382 1500 // order
1383 1501 if(isset($_GET_clone['order_by']))
1384 1502 {
1385 1503 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_favorite.post_id', $_GET_clone['order_by']);
1386 - $WMVC->db->order_by($_GET_clone['order_by']);
1504 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by'])));
1387 1505 }
1388 1506
1389 1507 }
1390 1508 }
@@ -1400,9 +1518,9 @@
1400 1518 //$WMVC->model('listing_m');
1401 1519
1402 1520 $smart_search = '';
1403 1521 if(isset($_GET_clone['search']))
1404 - $smart_search = sanitize_text_field($_GET_clone['search']);
1522 + $smart_search = wdk_esc_sql(sanitize_text_field($_GET_clone['search']));
1405 1523
1406 1524 $available_fields = $WMVC->$model_name->get_available_fields();
1407 1525
1408 1526 /* Пet column names from wdk_package and add to allow search +
@@ -1513,9 +1631,9 @@
1513 1631 $detect_date = strtotime($gen_search);
1514 1632
1515 1633 if(wdk_payments_is_date($val) && $detect_date > 1000)
1516 1634 {
1517 - $gen_search = date('Y-m-d H:i:s', $detect_date);
1635 + $gen_search = gmdate('Y-m-d H:i:s', $detect_date);
1518 1636 $gen_q.=$col_name." > '".$gen_search."' AND ";
1519 1637 }
1520 1638 else
1521 1639 {
@@ -1553,9 +1671,9 @@
1553 1671 // order
1554 1672 if(isset($_GET_clone['order_by']))
1555 1673 {
1556 1674 $_GET_clone['order_by'] = str_replace('post_id', $WMVC->db->prefix.'wdk_messages.post_id', $_GET_clone['order_by']);
1557 - $WMVC->db->order_by($_GET_clone['order_by']);
1675 + $WMVC->db->order_by(wdk_esc_sql(sanitize_text_field($_GET_clone['order_by']), true));
1558 1676 }
1559 1677
1560 1678 }
1561 1679 }
@@ -1562,9 +1680,9 @@
1562 1680
1563 1681 function wdk_date() {
1564 1682 $date_format = get_option('date_format');
1565 1683 $time_format = get_option('time_format');
1566 - $date = date("{$date_format} {$time_format}", current_time('timestamp'));
1684 + $date = gmdate("{$date_format} {$time_format}", current_time('timestamp'));
1567 1685 return $date;
1568 1686 }
1569 1687
1570 1688 if(!function_exists('wdk_placeholder_image_src')) {
@@ -1716,22 +1834,27 @@
1716 1834 }
1717 1835
1718 1836 ?>
1719 1837 <div class="wdk-col wdk-col-btns">
1720 - <div class="wdk-field wdk-field-btn">
1838 + <div class="wdk-field wdk-field-btn">
1721 1839 <div class="wdk-field-group wdk-field-group-additional">
1722 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>
1723 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' />
1724 1842 </div>
1725 1843 <div class="wdk-field-group wdk-field-group-reset">
1726 - <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>
1727 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;?>
1728 1851 <div class="wdk-field-group wdk-field-group-search">
1729 - <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>
1730 1853
1731 1854 <?php if(function_exists('run_wdk_save_search') && get_option('wdk_save_search_show_on_searchform')):?>
1732 1855 <div class="section-widget-control right">
1733 - <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">
1734 1857 <i class="fas fa-save" aria-hidden="true"></i>
1735 1858 <i class="fa fa-spinner fa-spin fa-ajax-indicator"></i>
1736 1859 </a>
1737 1860 </div>
@@ -1736,8 +1859,9 @@
1736 1859 </a>
1737 1860 </div>
1738 1861 <?php endif;?>
1739 1862 </div>
1863 +
1740 1864 </div>
1741 1865 </div>
1742 1866 <div id='wdk-form-additional' class="wdk-col" style="<?php echo esc_attr($form_closed) ;?>">
1743 1867 <div class="wdk-row">
@@ -1780,9 +1904,9 @@
1780 1904
1781 1905 if(empty($selected))
1782 1906 $selected='';
1783 1907
1784 - $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/>';
1785 1909
1786 1910 $skip_id = '';
1787 1911 //load javascript library
1788 1912 if($counter==0)
@@ -1789,39 +1913,39 @@
1789 1913 {
1790 1914 wp_enqueue_script('wdk-treefield');
1791 1915 wp_enqueue_style('wdk-treefield');
1792 1916 }
1793 - ?>
1794 - <script>
1795 - jQuery(document).ready(function($) {
1796 - $('#wdktreeelem<?php echo esc_js($counter);?>:not(.init)').wdkTreefield({
1797 - 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')) . "',
1798 1922 ajax_param: {
1799 - "page": 'wdk_frontendajax',
1800 - "function": 'treefieldid',
1801 - "action": 'wdk_public_action',
1802 - "table": '<?php echo esc_js($table); ?>',
1803 - "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1804 - "start_id": '<?php if(!empty($filter_ids)) esc_js($selected); else echo ""; ?>',
1805 - "empty_value": '<?php echo esc_js($empty_value); ?>',
1806 - "user_check": '<?php echo esc_js($user_check); ?>',
1807 - "sql_where": '<?php echo esc_js($sql_where); ?>',
1808 - "hide_fields": '<?php echo esc_js($hide_fields); ?>'
1809 - },
1810 - attribute_id: '<?php echo esc_js($attribute_id); ?>',
1811 - language_id: '<?php echo esc_js($language_id); ?>',
1812 - attribute_value: '<?php echo esc_js($column); ?>',
1813 - 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: '',
1814 1939 empty_value: ' - ',
1815 - text_search: '<?php esc_html_e('Search term', 'wpdirectorykit');?>',
1816 - 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') . "',
1817 1942 callback_selected: function(key) {
1818 - $('#wdktreeelem<?php echo esc_js($counter);?>').trigger("change");
1943 + $('#wdktreeelem" . esc_js($counter) . "').trigger('change');
1819 1944 }
1820 1945 }).addClass('init');
1821 - });
1822 - </script>
1823 - <?php
1946 + });"
1947 + );
1824 1948 $counter++;
1825 1949 return $form;
1826 1950 }
1827 1951 }
@@ -1889,9 +2013,9 @@
1889 2013 if(empty($values)) {
1890 2014 $values = $empty_value;
1891 2015 }
1892 2016
1893 - $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/>';
1894 2018
1895 2019 $skip_id = '';
1896 2020 //load javascript library
1897 2021 if($counter==0)
@@ -1902,13 +2026,14 @@
1902 2026 ?>
1903 2027 <script>
1904 2028 jQuery(document).ready(function($) {
1905 2029 $('#wdktreeelem_checkbox<?php echo esc_js($counter);?>:not(.init)').wdkTreefieldCheckboxes({
1906 - ajax_url: '<?php echo admin_url('admin-ajax.php'); ?>',
2030 + ajax_url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
1907 2031 ajax_param: {
1908 2032 "page": 'wdk_frontendajax',
1909 2033 "function": 'treefieldid_checkboxes',
1910 2034 "action": 'wdk_public_action',
2035 + "wdk_secure": '<?php echo esc_js(wp_create_nonce( 'wdk_secure_treefieldid_checkboxes' ));?>',
1911 2036 "table": '<?php echo esc_js($table); ?>',
1912 2037 "filter_ids": '<?php echo esc_js($filter_ids); ?>',
1913 2038 "empty_value": '<?php echo esc_js($empty_value); ?>',
1914 2039 "user_check": '<?php echo esc_js($user_check); ?>',
@@ -1937,14 +2062,19 @@
1937 2062 if ( ! function_exists('wdk_filter_decimal'))
1938 2063 {
1939 2064 function wdk_filter_decimal($string = '')
1940 2065 {
1941 - if(substr($string, -3, 3) === ".00") {
1942 - return substr($string, 0, -3);
1943 - }
1944 - if(substr($string, -3, 1) === "." && substr($string, -1, 1) === "0") {
1945 - return substr($string, 0, -1);
1946 - }
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 + }
1947 2077
1948 2078 return $string;
1949 2079 }
1950 2080 }
@@ -2072,9 +2202,9 @@
2072 2202 }
2073 2203
2074 2204 /* check is date on strtotime */
2075 2205 if((bool)strtotime($date)){
2076 - return date($return_format, strtotime($date));
2206 + return gmdate($return_format, strtotime($date));
2077 2207 }
2078 2208
2079 2209 return false;
2080 2210 }
@@ -2094,9 +2224,100 @@
2094 2224 return $base_url.$extension_url;
2095 2225 }
2096 2226 }
2097 2227
2228 +
2098 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 +/**
2099 2320 * Insert an attachment from an URL address.
2100 2321 *
2101 2322 * @param String $url
2102 2323 * @param Int $parent_post_id
@@ -2118,14 +2339,14 @@
2118 2339 $filename = substr($filename, 0, strpos($filename, '?'));
2119 2340 }
2120 2341
2121 2342 /* if unsoported extension */
2122 - 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){
2123 2344 $data = getimagesizefromstring($response['body']);
2124 2345 if(!$data) return false;
2125 2346 if(empty($data['mime'])) return false;
2126 2347
2127 - $filename = time().rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2348 + $filename = time().wp_rand(0000,9999).'.'.wdk_mime2ext($data['mime']);
2128 2349 }
2129 2350 $upload = wp_upload_bits( $filename, null, $response['body'] );
2130 2351
2131 2352 if( !empty( $upload['error'] ) ) {
@@ -2217,17 +2438,12 @@
2217 2438 */
2218 2439
2219 2440 function wdk_generate_profile_permalink($profile = array())
2220 2441 {
2221 -
2222 2442 $profile_slug = '';
2223 - if(wmvc_show_data('user_login', $profile, false)){
2224 - $profile_slug = wmvc_show_data('user_login', $profile);
2225 - if(wmvc_show_data('wdk_slug', $profile))
2226 - $profile_slug = wmvc_show_data('wdk_slug', $profile);
2227 - } else if(is_intval($profile)){
2443 + if(is_intval($profile)){
2228 2444 $profile_data = get_userdata($profile);
2229 - if(wmvc_show_data('wdk_slug', $profile, false)){
2445 + if(wmvc_show_data('wdk_slug', $profile_data, false)){
2230 2446 $profile_slug = wmvc_show_data('wdk_slug', $profile);
2231 2447 }elseif(wmvc_show_data('user_login', $profile_data, false)){
2232 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2233 2449 } else {
@@ -2232,10 +2448,14 @@
2232 2448 $profile_slug = wmvc_show_data('user_login', $profile_data);
2233 2449 } else {
2234 2450 $profile_slug = $profile;
2235 2451 }
2236 - }
2237 -
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 +
2238 2458 $user_profile_page = get_option('wdk_membership_profile_preview_page');
2239 2459 if(!$user_profile_page) {
2240 2460 return '#';
2241 2461 }
@@ -2490,19 +2710,19 @@
2490 2710 <!-- Your add & remove file links -->
2491 2711 <p class="hide-if-no-js">
2492 2712 <a class="upload-custom-img <?php if ( $you_have_file ) { echo 'hidden'; } ?>"
2493 2713 href="<?php echo esc_url($upload_link) ?>">
2494 - <?php echo esc_html__('Select file','wmvc_win') ?>
2714 + <?php echo esc_html__('Select file','wpdirectorykit') ?>
2495 2715 </a>
2496 2716 <a class="delete-custom-img <?php if ( ! $you_have_file ) { echo 'hidden'; } ?>"
2497 2717 href="#">
2498 - <?php echo esc_html__('Remove file','wmvc_win') ?>
2718 + <?php echo esc_html__('Remove all files','wpdirectorykit') ?>
2499 2719 </a>
2500 2720 </p>
2501 2721 <?php //endif; ?>
2502 2722
2503 2723 <!-- A hidden input to set and post the chosen file id -->
2504 - <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); ?>" />
2505 2725 </div>
2506 2726
2507 2727 <?php
2508 2728 $custom_js ='';
@@ -2510,8 +2730,9 @@
2510 2730 if( typeof jQuery.fn.wpMediaElementFile == 'function')
2511 2731 $('#".esc_js($field_name)."meta-box-id.postbox-upload').wpMediaElementFile();
2512 2732 });";
2513 2733
2734 +// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2514 2735 echo "<script>".$custom_js."</script>";
2515 2736
2516 2737 ?>
2517 2738
@@ -2562,19 +2783,15 @@
2562 2783 function wdk_upload_multi_files($field_name, $image_ids='', $texts = array())
2563 2784 {
2564 2785 static $media_element_counter = 0;
2565 2786
2566 - if(!isset($texts['file_select']))$texts['file_select'] = esc_html__('Select file','wmvc_win');
2567 - 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');
2568 2789
2569 2790 $media_element_counter++;
2570 2791
2571 2792 $img_field = $field_name.'_'.$media_element_counter;
2572 2793
2573 - wp_register_script( 'wpmediaelement_file', WPDIRECTORYKIT_URL . 'admin/js/jquery.wpmediaelement_file.js', array( 'jquery' ), false, false );
2574 - wp_enqueue_script( 'wpmediaelement_file' );
2575 - wp_enqueue_media();
2576 -
2577 2794 wp_enqueue_script( 'wpmediamultiple' );
2578 2795 wp_enqueue_script( 'jquery-ui-mouse' );
2579 2796 wp_enqueue_media();
2580 2797
@@ -2611,9 +2828,9 @@
2611 2828 <!-- Your image container, which can be manipulated with js -->
2612 2829 <div class="custom-img-container winter_mvc-media">
2613 2830 <?php if($you_have_img)foreach($your_img_src as $image_id => $img_src) : ?>
2614 2831 <div class="winter_mvc-media-card" data-media-id="<?php echo esc_attr($image_id);?>">
2615 - <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"/>
2616 2833 <a href="#" class="remove"></a>
2617 2834 </div>
2618 2835 <?php endforeach; ?>
2619 2836 </div>
@@ -2633,9 +2850,9 @@
2633 2850 </p>
2634 2851 <?php //endif; ?>
2635 2852
2636 2853 <!-- A hidden input to set and post the chosen image id -->
2637 - <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); ?>" />
2638 2855 </div>
2639 2856 <?php
2640 2857 $custom_js ='';
2641 2858 $custom_js .=" jQuery(function($) {
@@ -2641,11 +2858,14 @@
2641 2858 $custom_js .=" jQuery(function($) {
2642 2859 if( typeof jQuery.fn.wpMediaMultiple == 'function')
2643 2860 $('#".esc_js($field_name)."meta-box-id.postbox-upload-multiple').wpMediaMultiple({
2644 2861 frame: {
2645 - 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'))."',
2646 2863 button: '".esc_js(__('Use this media','wpdirectorykit'))."',
2647 - }
2864 + },
2865 + library: {
2866 + type: ['application', 'image', 'video']
2867 + },
2648 2868 });
2649 2869 /* order */
2650 2870 var re_order = function(media_element){
2651 2871 var list_media = '';
@@ -2672,8 +2892,9 @@
2672 2892 })
2673 2893 });
2674 2894 ";
2675 2895
2896 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
2676 2897 echo "<script>".$custom_js."</script>";
2677 2898
2678 2899 ?>
2679 2900
@@ -2754,8 +2975,59 @@
2754 2975
2755 2976 }
2756 2977 }
2757 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 +
2758 3030 if ( ! function_exists('wdk_recaptcha_field'))
2759 3031 {
2760 3032 function wdk_recaptcha_field($is_compact=false, $style="", $load_script=true)
2761 3033 {
@@ -2765,9 +3037,16 @@
2765 3037 if(get_option('wdk_recaptcha_site_key') !== FALSE && get_option('wdk_recaptcha_secret_key') !== NULL)
2766 3038 {
2767 3039 if($load_script && $counter===0)
2768 3040 {
2769 - 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 +
2770 3049 }
2771 3050 $counter++;
2772 3051
2773 3052 $compact_tag='';
@@ -2779,15 +3058,15 @@
2779 3058 }
2780 3059
2781 3060 $recaptcha_array[$counter] = array('size'=>$size_tag);
2782 3061
2783 - 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>';
2784 3063 ?>
2785 3064
2786 3065 <script>
2787 3066 <?php if($counter===1)echo 'var ';?>CaptchaCallback = function(){
2788 3067 <?php for($j=1;$j<=$counter;$j++): ?>
2789 - 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')); ?>'});
2790 3069 <?php endfor; ?>
2791 3070 };
2792 3071 </script>
2793 3072
@@ -2889,9 +3168,9 @@
2889 3168 if(is_array($val))
2890 3169 {
2891 3170 return wdk_clean($_POST);
2892 3171 }
2893 - else
3172 + elseif(is_string($val))
2894 3173 {
2895 3174 if(strpos($val, '<iframe') === 0)
2896 3175 $val = str_replace("'",'"', $val);
2897 3176
@@ -2930,9 +3209,9 @@
2930 3209 if(is_array($val))
2931 3210 {
2932 3211 $arr_cleaned[sanitize_text_field($key)] = wdk_clean($val);
2933 3212 }
2934 - else
3213 + elseif(is_string($val))
2935 3214 {
2936 3215 $arr_cleaned[sanitize_text_field($key)] = wp_kses_post($val);
2937 3216 }
2938 3217
@@ -2942,8 +3221,34 @@
2942 3221
2943 3222 return $arr_cleaned;
2944 3223 }
2945 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 +
2946 3251 /*
2947 3252 <select class="form-control" name="<?php echo 'control_operator_'.$i_fieldnum; ?>">
2948 3253 <option value="CONTAINS">CONTAINS</option>
2949 3254 <option value="NOT_CONTAINS">NOT_CONTAINS</option>
@@ -2984,9 +3289,9 @@
2984 3289
2985 3290 if(is_array($filter_ids)) $filter_ids = implode(',', $filter_ids);
2986 3291
2987 3292 static $counter = 0;
2988 - $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="">';
2989 3294
2990 3295
2991 3296 if(false)
2992 3297 if( $column_key == 'idcategory') {
@@ -3000,9 +3305,9 @@
3000 3305
3001 3306 $ids = array();
3002 3307 foreach($selected as $selected_item) {
3003 3308 if(!empty($selected_item)) {
3004 - $ids [] = $selected_item;
3309 + $ids [] = (int) $selected_item;
3005 3310 }
3006 3311 }
3007 3312
3008 3313 /* where in */
@@ -3013,15 +3318,19 @@
3013 3318
3014 3319 $results = $WMVC->$table->get();
3015 3320 foreach ($results as $item) {
3016 3321 if($item)
3017 - $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>';
3018 3325 }
3019 3326 }
3020 3327 } elseif(is_intval($selected)) {
3021 3328 $db_item = $WMVC->$table->get($selected, TRUE);
3022 3329 if($db_item)
3023 - $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>';
3024 3333 }
3025 3334 } else {
3026 3335 //$form .= '<option value="" selected="selected">'.esc_html__('Not selected', 'wpdirectorykit').'</option>';
3027 3336 }
@@ -3029,11 +3338,11 @@
3029 3338
3030 3339 //load javascript library
3031 3340 if($counter==0)
3032 3341 {
3033 - wp_enqueue_script('select2');
3342 + wp_enqueue_script('select2-select2');
3034 3343 wp_enqueue_script('wdk-select2');
3035 - wp_enqueue_style('select2');
3344 + wp_enqueue_style('select2-select2');
3036 3345 }
3037 3346 ?>
3038 3347 <?php
3039 3348 $counter++;
@@ -3077,11 +3386,11 @@
3077 3386
3078 3387 //load javascript library
3079 3388 if($counter==0)
3080 3389 {
3081 - wp_enqueue_script('select2');
3390 + wp_enqueue_script('select2-select2');
3082 3391 wp_enqueue_script('wdk-select2');
3083 - wp_enqueue_style('select2');
3392 + wp_enqueue_style('select2-select2');
3084 3393 }
3085 3394 ?>
3086 3395 <?php
3087 3396 $counter++;
@@ -3159,11 +3468,30 @@
3159 3468 'r'=>'llll',
3160 3469 'u'=>'x',
3161 3470 );
3162 3471
3163 - $replaced_from = array_keys($replaced);
3164 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3165 - 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);
3166 3494 }
3167 3495 }
3168 3496
3169 3497 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3204,11 +3532,29 @@
3204 3532 'u'=>'@',
3205 3533 ':'=>'',
3206 3534 );
3207 3535
3208 - $replaced_from = array_keys($replaced);
3209 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3210 - 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);
3211 3557 }
3212 3558 }
3213 3559
3214 3560 if ( ! function_exists('wdk_convert_date_format_jquery'))
@@ -3249,11 +3595,31 @@
3249 3595 'u'=>'@',
3250 3596 ':'=>'',
3251 3597 );
3252 3598
3253 - $replaced_from = array_keys($replaced);
3254 - $date_format = str_replace($replaced_from, array_keys($replaced_from), $date_format);
3255 - 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 +
3256 3622 }
3257 3623 }
3258 3624
3259 3625 if ( ! function_exists('wdk_get_gps'))
@@ -3281,9 +3647,17 @@
3281 3647
3282 3648 if(!isset($results[$address])) {
3283 3649 $results[$address] = NULL;
3284 3650 $url = 'https://nominatim.openstreetmap.org/search?format=json&q=' . $address;
3285 - $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);
3286 3660 $response = '';
3287 3661
3288 3662 // request failed
3289 3663 if ( is_wp_error( $request ) ) {
@@ -3439,8 +3813,32 @@
3439 3813 return false;
3440 3814 }
3441 3815 }
3442 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 +
3443 3841 if ( ! function_exists('wdk_filter_phone'))
3444 3842 {
3445 3843 // Validation phone
3446 3844 /**
@@ -3576,9 +3974,22 @@
3576 3974
3577 3975 $value = filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
3578 3976 $value = (float)str_replace(array(","," ",'&nbsp;'), "", $value);
3579 3977
3580 - 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);
3581 3992 }
3582 3993 }
3583 3994
3584 3995 if ( ! function_exists('wdk_currency_symbol'))
@@ -3711,9 +4122,20 @@
3711 4122 $user_data['wdk_position_title'] = wmvc_show_data('cacheduser_wdk_position_title', $row);
3712 4123 $user_data['agency_name'] = wmvc_show_data('cacheduser_agency_name', $row);
3713 4124 $user_data['description'] = wmvc_show_data('cacheduser_description', $row);
3714 4125 $user_data['user_url'] = wmvc_show_data('cacheduser_user_url', $row);
3715 - $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 + }
3716 4138
3717 4139 return $user_data;
3718 4140 }
3719 4141 }
@@ -3957,11 +4379,11 @@
3957 4379 $page_title,
3958 4380 $post_type
3959 4381 );
3960 4382 }
3961 -
3962 - $page = $wpdb->get_var( $sql );
3963 -
4383 + $page = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
4384 +
4385 +
3964 4386 if ( $page ) {
3965 4387 return get_post( $page, $output );
3966 4388 }
3967 4389
@@ -4025,9 +4447,9 @@
4025 4447 $output .= '<tr>';
4026 4448 foreach($var as $k => $v) {
4027 4449 if(count($columns) > 0 && !in_array($k, $columns))continue;
4028 4450
4029 - $output .= '<td><strong>' . $k . '</strong></td>';
4451 + $output .= '<td><strong>' . esc_html($k) . '</strong></td>';
4030 4452 }
4031 4453 $output .= '</tr>';
4032 4454 }
4033 4455
@@ -4034,13 +4456,14 @@
4034 4456 $output .= '<tr>';
4035 4457 foreach($var as $k => $v) {
4036 4458 if(count($columns) > 0 && !in_array($k, $columns))continue;
4037 4459
4038 - $output .= '<td>' . $v . '</td>';
4460 + $output .= '<td>' . esc_html($v) . '</td>';
4039 4461 }
4040 4462 $output .= '</tr>';
4041 4463 }
4042 4464 $output .= '</table>';
4465 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.NonSingularStringLiteralText
4043 4466 echo $output;
4044 4467 }
4045 4468 }
4046 4469
@@ -4046,9 +4469,9 @@
4046 4469
4047 4470 if ( ! function_exists('wdk_move_gps'))
4048 4471 {
4049 4472 function wdk_move_gps($value) {
4050 - return $value+0.001 * rand(1, 9);
4473 + return $value+0.001 * wp_rand(1, 9);
4051 4474 }
4052 4475 }
4053 4476
4054 4477 if ( ! function_exists('wdk_get_near_location'))
@@ -4056,10 +4479,10 @@
4056 4479 function wdk_get_near_location($latitude, $longitude, $radius = 10000) {
4057 4480 // Convert radius from meters to degrees
4058 4481 $radiusInDegrees = $radius / 111000;
4059 4482
4060 - $u = mt_rand() / mt_getrandmax();
4061 - $v = mt_rand() / mt_getrandmax();
4483 + $u = wp_rand() / mt_getrandmax();
4484 + $v = wp_rand() / mt_getrandmax();
4062 4485 $w = $radiusInDegrees * sqrt($u);
4063 4486 $t = 2 * M_PI * $v;
4064 4487 $x = $w * cos($t);
4065 4488 $y = $w * sin($t);
@@ -4185,9 +4608,9 @@
4185 4608 // For french
4186 4609 $str = str_replace(array('â','é','è','û','ê', 'à','Â','ç','ï','î','ä','î'),
4187 4610 array('a','e','e','u','e', 'a','c','c','i','î','a','î'), $str);
4188 4611
4189 - $str = strip_tags(strtolower($str));
4612 + $str = wp_strip_all_tags(strtolower($str));
4190 4613
4191 4614
4192 4615 foreach ($trans as $key => $val)
4193 4616 {
@@ -4312,8 +4735,13 @@
4312 4735 if(empty($size_name) || $size_name == 'full' || !get_option( "{$size_name}_size_w" )) {
4313 4736 return true;
4314 4737 }
4315 4738
4739 + // Check if the attachment is an image
4740 + if (!wp_attachment_is_image($attachment_id)) {
4741 + return false;
4742 + }
4743 +
4316 4744 $file = get_attached_file( $attachment_id );
4317 4745 require_once(ABSPATH . "wp-admin" . '/includes/image.php');
4318 4746 $metadata = wp_generate_attachment_metadata($attachment_id, $file);
4319 4747 if ( ! isset( $metadata['sizes'][ $size_name ] ) ) {
@@ -4328,6 +4756,697 @@
4328 4756 }
4329 4757 return true;
4330 4758 }
4331 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 + }
4332 5451
4333 5452 ?>