PluginProbe
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings / 6.3.5
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings v6.3.5
7.2.1 7.2 7.1.2 7.1.1 7.1 7.0.4 7.0.6 7.0.7 6.3.8 6.3.7 6.3.6 6.3.5 6.3.4 6.3.3 6.3.1 trunk 5.7.3 5.7.5 5.8.1 5.8.2 5.8.3 5.8.4 5.8.6 6.0.4 6.0.5 All 36 releases
mlsimport / mlsimport.php

mlsimport.php in MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings 6.3.5, at mlsimport.php

648 lines 21.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: MlsImport
4 * Plugin URI: https://mlsimport.com/
5 * Description: MLS Import - The MLSImport plugin facilitates the connection to your real estate MLS database, allowing you to download and synchronize real estate property data from the MLS.
6 * Version: 6.3.5
7 * Requires at least: 5.2
8 * Requires PHP: 7.4
9 * License: GPLv3
10 * License URI: https://www.gnu.org/licenses/gpl-3.0.html
11 * Author: MlsImport
12 * Text Domain: mlsimport
13 * Domain Path: /languages
14 */
15
16 // If this file is called directly, abort.
17
18 if ( ! defined( 'WPINC' ) ) {
19 die;
20 }
21
22
23 define( 'MLSIMPORT_VERSION', '6.3.5');
24 define( 'MLSIMPORT_CLUBLINK', 'mlsimport.com' );
25 define( 'MLSIMPORT_CLUBLINKSSL', 'https' );
26 define( 'MLSIMPORT_CRON_STEP', 20 );
27 define( 'MLSIMPORT_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
28 define( 'MLSIMPORT_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
29
30
31 //define( 'MLSIMPORT_API_URL', 'https://requests.mlsimport.com/' );
32 //define( 'MLSIMPORT_API_URL', 'https://pyjzsilw7b.execute-api.us-east-1.amazonaws.com/dev/' );
33 define( 'MLSIMPORT_API_URL', 'https://srky9ddikl.execute-api.us-east-1.amazonaws.com/blue/');
34
35
36
37
38
39
40 if ( ! defined( 'MLSIMPORT_HIDE_SETUP_NOTICE' ) ) {
41 define( 'MLSIMPORT_HIDE_SETUP_NOTICE', false );
42 }
43
44
45
46 /**
47 * The code that runs during plugin activation.
48 * This action is documented in includes/class-mlsimport-activator.php
49 */
50 function mlsimport_activate() {
51 require_once plugin_dir_path( __FILE__ ) . 'includes/class-mlsimport-activator.php';
52 Mlsimport_Activator::activate();
53 mlsimport_telemetry_set_once( 'installed_at', time() );
54 }
55
56
57
58 /**
59 * The code that runs during plugin deactivation.
60 * This action is documented in includes/class-mlsimport-deactivator.php
61 */
62 function mlsimport_deactivate() {
63 require_once plugin_dir_path( __FILE__ ) . 'includes/class-mlsimport-deactivator.php';
64 wp_clear_scheduled_hook( 'event_mls_import_auto' );
65 wp_clear_scheduled_hook( 'mlsimport_reconciliation_event' );
66 wp_clear_scheduled_hook( 'mlsimport_daily_telemetry_event' );
67 Mlsimport_Deactivator::deactivate();
68 }
69
70
71
72 register_activation_hook( __FILE__, 'mlsimport_activate' );
73 register_deactivation_hook( __FILE__, 'mlsimport_deactivate' );
74
75 /**
76 * Show one-time modal about the switch from Delete Statuses to Protected Statuses.
77 */
78 add_action( 'admin_footer', 'mlsimport_protected_statuses_upgrade_modal' );
79 function mlsimport_protected_statuses_upgrade_modal() {
80 if ( get_option( 'mlsimport_dismiss_protected_status_notice' ) ) {
81 return;
82 }
83 // Only show for sites that had a version before 6.2 (not fresh installs)
84 $show_modal = get_option( 'mlsimport_show_protected_status_modal' );
85 if ( ! $show_modal ) {
86 return;
87 }
88 $nonce = wp_create_nonce( 'mlsimport_dismiss_protected_notice' );
89 $import_tasks_url = admin_url( 'edit.php?post_type=mlsimport_item' );
90 ?>
91 <div id="mlsimport-protected-status-modal" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:999999;display:flex;align-items:center;justify-content:center;">
92 <div style="background:#fff;max-width:520px;width:90%;border-radius:8px;padding:30px;box-shadow:0 4px 20px rgba(0,0,0,0.3);">
93 <h2 style="margin-top:0;color:#d63638;">MLSImport - Important Change</h2>
94 <p><strong>"Delete Statuses"</strong> have been removed. The plugin now uses <strong>Protected Statuses</strong> only.</p>
95 <p>Properties with a Protected Status will be kept during reconciliation. All other properties no longer found in MLS <strong>will be deleted</strong>.</p>
96 <p style="background:#fff3cd;border-left:4px solid #dba617;padding:10px 14px;"><strong>Action required:</strong> Go to each of your <a href="<?php echo esc_url( $import_tasks_url ); ?>">Import Tasks</a> and set the Protected Statuses field to the statuses you want to keep (e.g. Active, Pending, Coming Soon).</p>
97 <button id="mlsimport-acknowledge-btn" class="button button-primary" style="margin-top:10px;font-size:14px;padding:6px 24px;">I acknowledge</button>
98 </div>
99 </div>
100 <script>
101 document.getElementById('mlsimport-acknowledge-btn').addEventListener('click', function() {
102 var btn = this;
103 btn.disabled = true;
104 btn.textContent = 'Saving...';
105 var xhr = new XMLHttpRequest();
106 xhr.open('POST', ajaxurl);
107 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
108 xhr.onload = function() {
109 document.getElementById('mlsimport-protected-status-modal').style.display = 'none';
110 };
111 xhr.send('action=mlsimport_dismiss_protected_notice&_wpnonce=<?php echo esc_js( $nonce ); ?>');
112 });
113 </script>
114 <?php
115 }
116 add_action( 'wp_ajax_mlsimport_dismiss_protected_notice', 'mlsimport_handle_dismiss_protected_notice' );
117 function mlsimport_handle_dismiss_protected_notice() {
118 check_ajax_referer( 'mlsimport_dismiss_protected_notice' );
119 update_option( 'mlsimport_dismiss_protected_status_notice', true );
120 delete_option( 'mlsimport_show_protected_status_modal' );
121 wp_send_json_success();
122 }
123
124 /**
125 * Track installed version and flag upgrade modals.
126 * Fresh installs get current version immediately, so no upgrade modal.
127 * Upgrades from < 6.2 flag the protected status modal.
128 */
129 $mlsimport_prev_version = get_option( 'mlsimport_installed_version', '' );
130 if ( $mlsimport_prev_version !== MLSIMPORT_VERSION ) {
131 if ( ! empty( $mlsimport_prev_version ) && version_compare( $mlsimport_prev_version, '6.2', '<' ) ) {
132 update_option( 'mlsimport_show_protected_status_modal', true );
133 }
134 update_option( 'mlsimport_installed_version', MLSIMPORT_VERSION );
135 }
136
137 /**
138 * The core plugin class that is used to define internationalization,
139 * admin-specific hooks, and public-facing site hooks.
140 */
141
142 require 'vendor/autoload.php';
143 require_once plugin_dir_path( __FILE__ ) . 'includes/help_functions.php';
144 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-status-taxonomy.php';
145 require_once plugin_dir_path( __FILE__ ) . 'includes/class-mlsimport.php';
146 require_once plugin_dir_path( __FILE__ ) . 'includes/ThemeImport.php';
147 require_once plugin_dir_path( __FILE__ ) . 'enviroment/ResidenceClass.php';
148 require_once plugin_dir_path( __FILE__ ) . 'enviroment/EstateClass.php';
149 require_once plugin_dir_path( __FILE__ ) . 'enviroment/HouzezClass.php';
150 require_once plugin_dir_path( __FILE__ ) . 'enviroment/RealHomesClass.php';
151 require_once plugin_dir_path( __FILE__ ) . 'enviroment/ResoBase.php';
152 require_once plugin_dir_path( __FILE__ ) . 'enviroment/SparkResoClass.php';
153 require_once plugin_dir_path( __FILE__ ) . 'enviroment/BridgeResoClass.php';
154 require_once plugin_dir_path( __FILE__ ) . 'enviroment/TresleResoClass.php';
155 require_once plugin_dir_path( __FILE__ ) . 'enviroment/MlsgridResoClass.php';
156 require_once plugin_dir_path( __FILE__ ) . 'enviroment/MlsgridResoClass.php';
157 require_once plugin_dir_path( __FILE__ ) . 'includes/addons/agents_offices.php';
158 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-onboarding.php';
159
160 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-field-selector-functions.php';
161 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-progressive-save.php';
162 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-telemetry.php';
163 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-activity-log.php';
164
165 if ( ! wp_next_scheduled( 'event_mls_import_auto' ) ) {
166 wp_schedule_event( time(), 'hourly', 'event_mls_import_auto' );
167 }
168
169
170 /**
171 * Scheduled event: Processes MLSimport items marked for cron processing, in memory-safe batches.
172 *
173 * This function is triggered by the 'event_mls_import_auto' action.
174 * It fetches mlsimport_item post IDs in small batches (not all at once!) to minimize memory usage.
175 * Only posts with meta 'mlsimport_item_stat_cron' = 1 are processed.
176 * For each item, calls mlsimport_saas_start_cron_links_per_item().
177 *
178 * Optimizations:
179 * - Uses 'fields' => 'ids' so only post IDs are loaded (saves memory)
180 * - Batches with posts_per_page/paged, so memory does not spike for large data sets
181 * - Calls gc_collect_cycles() periodically to further reduce memory leaks
182 * - Skips processing if MLS is not connected or token is missing
183 *
184 * @return void
185 */
186 add_action('event_mls_import_auto', 'mlsimport_saas_event_mls_import_auto_function');
187 /**
188 * Scheduled event handler for MLS Import Auto (runs via WP Cron).
189 * Processes mlsimport_item posts in batches and logs memory usage.
190 */
191 function mlsimport_saas_event_mls_import_auto_function() {
192 global $mlsimport;
193
194 //error_log('[AutoCron] Start: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB');
195
196 // 1. Get the API token from transient - exit if not set
197 $token = $mlsimport->admin->mlsimport_saas_get_mls_api_token_from_transient();
198 //error_log('[AutoCron] After token fetch: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB');
199 if (trim($token) === '') {
200 //error_log('[AutoCron] No token, exiting.');
201 return;
202 }
203
204 // 2. Check if MLS connection is valid - exit if not
205 $is_mls_connected = get_option('mlsimport_connection_test', '');
206 //error_log('[AutoCron] After connection check: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB');
207 if ('yes' !== $is_mls_connected) {
208 //error_log('[AutoCron] No valid connection, exiting.');
209 return;
210 }
211
212 // Record sync attempt in telemetry
213 mlsimport_telemetry_bump( 'syncs' );
214 mlsimport_telemetry_set( 'last_sync_attempt', time() );
215
216 // 3. Set batch size for processing and initialize loop variables
217 $batch_size = 100;
218 $paged = 1;
219 $total_processed = 0;
220
221 // 4. Process in batches until no more items are found
222 do {
223 // Prepare query: only IDs, filter by meta key, batch, paged, no_found_rows speeds up query
224 $args = array(
225 'post_type' => 'mlsimport_item',
226 'post_status' => 'any',
227 'posts_per_page' => $batch_size,
228 'paged' => $paged,
229 'fields' => 'ids',
230 'meta_query' => array(
231 array(
232 'key' => 'mlsimport_item_stat_cron',
233 'value' => 1,
234 'compare' => '=',
235 ),
236 ),
237 'no_found_rows' => true,
238 );
239
240 // Get post IDs for this batch
241 $post_ids = get_posts($args);
242 //error_log("[AutoCron] Batch {$paged} fetched " . count($post_ids) . " items, memory: " . (memory_get_usage(true) / 1024 / 1024) . ' MB');
243
244 // If nothing is returned, break the loop
245 if (empty($post_ids)) {
246 break;
247 }
248
249 // 5. Loop through each post ID in this batch
250 foreach ($post_ids as $prop_id) {
251 $logs = 'Loop custom post: ' . $prop_id . PHP_EOL;
252 mlsimport_debuglogs_per_plugin($logs);
253
254 // Call processing function for this item. The feed count it pulls
255 // is recorded inside mlsimport_make_listing_requests() (last_feed_found).
256 $mlsimport->admin->mlsimport_saas_start_cron_links_per_item($prop_id);
257
258 $total_processed++;
259
260 // Free memory every 100 processed items
261 if ($total_processed % 100 === 0) {
262 gc_collect_cycles();
263 //error_log("[AutoCron] Processed {$total_processed} total, memory: " . (memory_get_usage(true) / 1024 / 1024) . ' MB');
264 }
265 }
266
267 // 6. Prepare next batch
268 $paged++;
269 unset($post_ids); // Free memory
270 gc_collect_cycles(); // Trigger garbage collection
271 //error_log("[AutoCron] After batch {$paged}, memory: " . (memory_get_usage(true) / 1024 / 1024) . ' MB');
272
273 } while (true);
274
275 mlsimport_telemetry_set( 'last_sync_success', time() );
276
277 //error_log('[AutoCron] Done, total processed: ' . $total_processed . ', end memory: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB');
278 }
279
280
281
282 /*
283 * Reconciliation Mechanism
284 *
285 *
286 *
287 **/
288
289 if ( ! wp_next_scheduled( 'mlsimport_reconciliation_event' ) ) {
290 wp_schedule_event( time(), 'daily', 'mlsimport_reconciliation_event' );
291 }
292
293 add_action( 'mlsimport_reconciliation_event', 'mlsimport_saas_reconciliation_event_function' );
294
295 if ( ! wp_next_scheduled( 'mlsimport_daily_telemetry_event' ) ) {
296 wp_schedule_event( time(), 'daily', 'mlsimport_daily_telemetry_event' );
297 }
298
299 add_action( 'mlsimport_daily_telemetry_event', 'mlsimport_telemetry_run_daily' );
300
301
302 /*
303 * Force use of transient
304 *
305 *
306 *
307 **/
308
309 function mlsimport_force_use_transient( $value ) {
310 return $value;
311 // return false;
312 }
313
314
315
316
317 global $mlsimport;
318 $mlsimport = new Mlsimport();
319 $mlsimport->run();
320
321
322
323
324
325 $supported_theme = array(
326 991 => 'WpResidence',
327 992 => 'Houzez',
328 993 => 'Real Homes',
329 994 => 'Wpestate',
330
331 );
332
333 define( 'MLSIMPORT_THEME', $supported_theme );
334
335 add_filter( 'action_scheduler_failure_period', 'mlsimport_saas_filter_timelimit' );
336 function mlsimport_saas_filter_timelimit( $time_limit ) {
337 return 3000;
338 }
339
340
341
342 /*
343 *
344 * Write logs
345 *
346 **/
347
348 function mlsimport_saas_single_write_import_custom_logs( $message, $tip_import = 'normal' ) {
349 // Check if logging is enabled
350 $enable_logs = intval( get_option( 'mlsimport_disable_logs' ) );
351 if ( 1 !== $enable_logs) {
352 return;
353 }
354
355 if ( is_array( $message ) ) {
356 $message = wp_json_encode( $message );
357 }
358
359 $formatted_message = gmdate( 'F j, Y, g:i a' ) . ' -> ' . $message;
360
361 // Determine the log file path based on the import type
362 $log_file_name = 'cron' === $tip_import ? 'cron_logs' :
363 ( 'delete' === $tip_import ? 'delete_logs' :
364 ( 'server_cron' === $tip_import ? 'server_cron_logs' : 'import_logs' ) );
365
366 // Construct the full path with a date suffix
367 $log_file_path = WP_PLUGIN_DIR . "/mlsimport/logs/{$log_file_name}-" . gmdate( 'Y-m-d' ) . '.log';
368
369 // Error handling for file operations
370 try {
371 // Check and create the directory for logs if it does not exist
372 $log_dir = dirname( $log_file_path );
373 if ( ! file_exists( $log_dir ) ) {
374 mkdir( $log_dir, 0755, true );
375 }
376
377 // Append the formatted message to the log file
378 file_put_contents( $log_file_path, $formatted_message, FILE_APPEND | LOCK_EX );
379 } catch ( Exception $e ) {
380 // Handle the exception, such as logging the error elsewhere or sending a notification
381 }
382 }
383
384
385
386 /*
387 *
388 *
389 * Write Status logs
390 *
391 *
392 **/
393
394
395
396 function mlsimport_debuglogs_per_plugin_old( $message ) {
397
398 if ( is_array( $message ) ) {
399 $message = wp_json_encode( $message );
400 }
401
402 global $wp_filesystem;
403 if ( empty( $wp_filesystem ) ) {
404 require_once ABSPATH . '/wp-admin/includes/file.php';
405 WP_Filesystem();
406 }
407
408 $path_status = WP_PLUGIN_DIR . '/mlsimport/logs/status_logs.log';
409 file_put_contents( $path_status, $message, LOCK_EX );
410 }
411 function mlsimport_debuglogs_per_plugin( $message ) {
412
413 if ( is_array( $message ) ) {
414 $message = wp_json_encode( $message );
415 }
416
417 if ( empty( $message ) ) {
418 return; // Exit the function if there's nothing to log
419 }
420
421 $log_file_path = WP_PLUGIN_DIR . '/mlsimport/logs/status_logs.log';
422
423 // Check and create the directory for logs if it does not exist
424 $log_dir = dirname( $log_file_path );
425 if ( ! file_exists( $log_dir ) ) {
426 mkdir( $log_dir, 0755, true );
427 }
428
429 // Error handling for file operations
430 try {
431 // Append the message to the log file with a newline and acquire an exclusive lock during writing
432 file_put_contents( $log_file_path, $message . PHP_EOL, LOCK_EX );
433 } catch ( Exception $e ) {
434 // Handle the exception, such as logging the error elsewhere or sending a notification
435 }
436 }
437
438
439
440
441
442 /*
443 * Cron job trigger
444 *
445 *
446 *
447 **/
448
449
450 // */5 * * * * wget http://example.com/check */2
451 add_action( 'init', 'mlsimport_trigger_cron_job' );
452 function mlsimport_trigger_cron_job() {
453 // ?mlsimport_cron=yes
454 if ( isset( $_REQUEST['mlsimport_cron'] ) && 'yes' === sanitize_text_field( wp_unslash( $_REQUEST['mlsimport_cron'] ) ) ) {
455 $last_run = intval( get_option( 'mlsimport_last_server_cron' ) );
456 $now = time();
457 if ( 0 === intval($last_run) ) {
458 update_option( 'mlsimport_last_server_cron', $now );
459 }
460
461 if ( $last_run < $now - ( 60 * 60 * 2 ) ) {
462 $log = 'Server Cron Job triggered on ' . date( 'l jS \of F Y h:i:s A', $last_run ) . ' vs ' . gmdate( 'l jS \of F Y h:i:s A', $now ) . PHP_EOL;
463 // mlsimport_saas_event_mls_import_auto_function();
464 update_option( 'mlsimport_last_server_cron', $now );
465 } else {
466 $log = 'Server Cron Job Called but not triggered. Last run on ' . gmdate( 'l jS \of F Y h:i:s A', $last_run ) . ' vs ' . gmdate( 'l jS \of F Y h:i:s A', $now ) . PHP_EOL;
467 }
468
469 mlsimport_saas_single_write_import_custom_logs( $log, 'server_cron' );
470 }
471 }
472
473
474
475 function mlsimport_show_signup() {
476 $affiliate_url = 'https://mlsimport.com';
477 if ( function_exists( 'wp_estate_init' ) ) {
478 $affiliate_url = 'https://mlsimport.com/ref/1/?campaign=wpresidence';
479 }
480 ?>
481 <div class="mlsimport_signup">
482 <h3><?php esc_html_e('Import MLS Listings into your Real Estate website', 'mlsimport'); ?></h3>
483 <p><?php esc_html_e('Signup now and get 30-Days Free trial, no setup fee & cancel anytime at ', 'mlsimport'); ?><a href="https://mlsimport.com/mls-import-plugin-pricing/" target="_blank">MLSImport.com</a></p>
484 <a href="https://mlsimport.com/mls-import-plugin-pricing" class="button mlsimport_button mlsimport_signup_button" target="_blank"><?php esc_html_e('Create My Account', 'mlsimport'); ?></a>
485 </div>
486 <?php
487 }
488
489
490 //add_action('admin_init', 'force_recount_all_terms');
491 function force_recount_all_terms() {
492 global $wpdb;
493
494 // Get all taxonomies
495 $taxonomies = get_taxonomies([], 'names');
496
497 foreach ($taxonomies as $taxonomy) {
498 // Get all terms for the taxonomy
499 $terms = get_terms([
500 'taxonomy' => $taxonomy,
501 'hide_empty' => false, // Include terms with 0 count
502 'fields' => 'ids', // Get only the term IDs
503 ]);
504
505 if (!is_wp_error($terms) && !empty($terms)) {
506 // Get term_taxonomy_ids for these terms
507 $term_taxonomy_ids = $wpdb->get_col($wpdb->prepare(
508 "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE term_id IN (" . implode(',', array_map('intval', $terms)) . ")"
509 ));
510
511 // Update term counts
512 if (!empty($term_taxonomy_ids)) {
513 wp_update_term_count_now($term_taxonomy_ids, $taxonomy);
514 }
515 }
516 }
517
518 echo "Term counts have been recalculated for all taxonomies.";
519 }
520
521
522 /*
523 *
524 * create dropdown list
525 *
526 *
527 */
528 function mlsiport_mls_select_list( $key, $value, $data_array ) {
529 $select = '<select class="mlsimport-2025-select" id="' . esc_attr( $key ) . '" name="mlsimport_admin_options[' . $key . ']">';
530 if ( is_array( $data_array ) ) :
531 foreach ( $data_array as $key => $mls_item ) {
532 $select .= '<option value="' .esc_attr( $key ). '"';
533 if ( intval( $value ) === intval( $key ) ) {
534 $select .= ' selected ';
535 }
536 $select .= '>' .esc_html( $mls_item ). '</option>';
537 }
538 endif;
539 $select .= '</select>';
540 return $select;
541 }
542
543
544
545 add_action('wp_ajax_mlsimport_save_account', 'mlsimport_save_account_callback');
546 function mlsimport_save_account_callback() {
547 check_ajax_referer('mlsimport_onboarding_nonce', 'security');
548
549 $options = get_option('mlsimport_admin_options', []);
550 if ( ! empty($_POST['mlsimport_username']) && ! empty($_POST['mlsimport_password']) ) {
551 $options['mlsimport_username'] = sanitize_text_field($_POST['mlsimport_username']);
552 $options['mlsimport_password'] = sanitize_text_field($_POST['mlsimport_password']);
553 update_option('mlsimport_admin_options', $options);
554 }
555
556 global $mlsimport;
557
558 // Refresh token
559 $token = $mlsimport->admin->mlsimport_saas_get_mls_api_token_from_transient();
560
561 if (trim($token) === '') {
562 ob_start();
563
564 ?>
565 <div class="mlsimport_warning">
566 <?php esc_html_e('You are not connected to MlsImport - Please check your Username and Password.', 'mlsimport'); ?>
567 </div>
568 <?php
569 $html = ob_get_clean();
570
571 wp_send_json_success([
572 'message' => __('You are not connected.', 'mlsimport'),
573 'html' => $html,
574 'connected' => false
575 ]);
576 } else {
577 ob_start();
578 ?>
579 <div class="mlsimport_warning mlsimport_validated">
580 <?php esc_html_e('You are connected to your MlsImport account!', 'mlsimport'); ?>
581 </div>
582 <?php
583 $html = ob_get_clean();
584
585 wp_send_json_success([
586 'message' => __('Connected successfully!', 'mlsimport'),
587 'html' => $html,
588 'connected' => true
589 ]);
590 }
591 }
592
593
594
595
596
597
598
599
600 add_action('wp_ajax_mlsimport_save_mls_data', 'mlsimport_save_mls_data_callback');
601 function mlsimport_save_mls_data_callback() {
602 check_ajax_referer('mlsimport_onboarding_nonce', 'security');
603
604 $options = get_option('mlsimport_admin_options', []);
605
606 foreach ($_POST as $key => $value) {
607 if (strpos($key, 'mlsimport_') === 0 && $key !== 'mlsimport_username' && $key !== 'mlsimport_password') {
608 $options[$key] = sanitize_text_field($value);
609 }
610 }
611
612 update_option('mlsimport_admin_options', $options);
613
614 // Run MLS connection check
615 global $mlsimport;
616 $is_mls_connected = get_option('mlsimport_connection_test', '');
617 $mlsimport->admin->mlsimport_saas_setting_up();
618
619 if ('yes' !== $is_mls_connected) {
620 $mlsimport->admin->mlsimport_saas_check_mls_connection();
621 $is_mls_connected = get_option('mlsimport_connection_test', '');
622 }
623
624 ob_start();
625 if ('yes' === $is_mls_connected) {
626 ?>
627 <div class="mlsimport_warning mlsimport_validated">
628 <?php esc_html_e('You’re now connected to your MLS.', 'mlsimport'); ?>
629 </div>
630 <?php
631 } else {
632 ?>
633 <div class="mlsimport_warning">
634 <?php esc_html_e('The connection to your MLS was NOT successful. Please check the authentication token is correct and check your MLS Data Access Application is approved.', 'mlsimport'); ?>
635 </div>
636 <?php
637 }
638 $html = ob_get_clean();
639
640 wp_send_json_success([
641 'message' => __('MLS data saved', 'mlsimport'),
642 'html' => $html,
643 'connected' => $is_mls_connected === 'yes',
644 ]);
645 }
646
647
648