PluginProbe
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings / 6.3.7
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings v6.3.7
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 6.0.7 6.1.0 All 34 releases
mlsimport / mlsimport.php

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

649 lines 21.6 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.7
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.7');
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/mlsimport-status-normalize.php';
146 require_once plugin_dir_path( __FILE__ ) . 'includes/class-mlsimport.php';
147 require_once plugin_dir_path( __FILE__ ) . 'includes/ThemeImport.php';
148 require_once plugin_dir_path( __FILE__ ) . 'enviroment/ResidenceClass.php';
149 require_once plugin_dir_path( __FILE__ ) . 'enviroment/EstateClass.php';
150 require_once plugin_dir_path( __FILE__ ) . 'enviroment/HouzezClass.php';
151 require_once plugin_dir_path( __FILE__ ) . 'enviroment/RealHomesClass.php';
152 require_once plugin_dir_path( __FILE__ ) . 'enviroment/ResoBase.php';
153 require_once plugin_dir_path( __FILE__ ) . 'enviroment/SparkResoClass.php';
154 require_once plugin_dir_path( __FILE__ ) . 'enviroment/BridgeResoClass.php';
155 require_once plugin_dir_path( __FILE__ ) . 'enviroment/TresleResoClass.php';
156 require_once plugin_dir_path( __FILE__ ) . 'enviroment/MlsgridResoClass.php';
157 require_once plugin_dir_path( __FILE__ ) . 'enviroment/MlsgridResoClass.php';
158 require_once plugin_dir_path( __FILE__ ) . 'includes/addons/agents_offices.php';
159 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-onboarding.php';
160
161 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-field-selector-functions.php';
162 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-progressive-save.php';
163 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-telemetry.php';
164 require_once plugin_dir_path( __FILE__ ) . 'includes/mlsimport-activity-log.php';
165
166 if ( ! wp_next_scheduled( 'event_mls_import_auto' ) ) {
167 wp_schedule_event( time(), 'hourly', 'event_mls_import_auto' );
168 }
169
170
171 /**
172 * Scheduled event: Processes MLSimport items marked for cron processing, in memory-safe batches.
173 *
174 * This function is triggered by the 'event_mls_import_auto' action.
175 * It fetches mlsimport_item post IDs in small batches (not all at once!) to minimize memory usage.
176 * Only posts with meta 'mlsimport_item_stat_cron' = 1 are processed.
177 * For each item, calls mlsimport_saas_start_cron_links_per_item().
178 *
179 * Optimizations:
180 * - Uses 'fields' => 'ids' so only post IDs are loaded (saves memory)
181 * - Batches with posts_per_page/paged, so memory does not spike for large data sets
182 * - Calls gc_collect_cycles() periodically to further reduce memory leaks
183 * - Skips processing if MLS is not connected or token is missing
184 *
185 * @return void
186 */
187 add_action('event_mls_import_auto', 'mlsimport_saas_event_mls_import_auto_function');
188 /**
189 * Scheduled event handler for MLS Import Auto (runs via WP Cron).
190 * Processes mlsimport_item posts in batches and logs memory usage.
191 */
192 function mlsimport_saas_event_mls_import_auto_function() {
193 global $mlsimport;
194
195 //error_log('[AutoCron] Start: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB');
196
197 // 1. Get the API token from transient - exit if not set
198 $token = $mlsimport->admin->mlsimport_saas_get_mls_api_token_from_transient();
199 //error_log('[AutoCron] After token fetch: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB');
200 if (trim($token) === '') {
201 //error_log('[AutoCron] No token, exiting.');
202 return;
203 }
204
205 // 2. Check if MLS connection is valid - exit if not
206 $is_mls_connected = get_option('mlsimport_connection_test', '');
207 //error_log('[AutoCron] After connection check: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB');
208 if ('yes' !== $is_mls_connected) {
209 //error_log('[AutoCron] No valid connection, exiting.');
210 return;
211 }
212
213 // Record sync attempt in telemetry
214 mlsimport_telemetry_bump( 'syncs' );
215 mlsimport_telemetry_set( 'last_sync_attempt', time() );
216
217 // 3. Set batch size for processing and initialize loop variables
218 $batch_size = 100;
219 $paged = 1;
220 $total_processed = 0;
221
222 // 4. Process in batches until no more items are found
223 do {
224 // Prepare query: only IDs, filter by meta key, batch, paged, no_found_rows speeds up query
225 $args = array(
226 'post_type' => 'mlsimport_item',
227 'post_status' => 'any',
228 'posts_per_page' => $batch_size,
229 'paged' => $paged,
230 'fields' => 'ids',
231 'meta_query' => array(
232 array(
233 'key' => 'mlsimport_item_stat_cron',
234 'value' => 1,
235 'compare' => '=',
236 ),
237 ),
238 'no_found_rows' => true,
239 );
240
241 // Get post IDs for this batch
242 $post_ids = get_posts($args);
243 //error_log("[AutoCron] Batch {$paged} fetched " . count($post_ids) . " items, memory: " . (memory_get_usage(true) / 1024 / 1024) . ' MB');
244
245 // If nothing is returned, break the loop
246 if (empty($post_ids)) {
247 break;
248 }
249
250 // 5. Loop through each post ID in this batch
251 foreach ($post_ids as $prop_id) {
252 $logs = 'Loop custom post: ' . $prop_id . PHP_EOL;
253 mlsimport_debuglogs_per_plugin($logs);
254
255 // Call processing function for this item. The feed count it pulls
256 // is recorded inside mlsimport_make_listing_requests() (last_feed_found).
257 $mlsimport->admin->mlsimport_saas_start_cron_links_per_item($prop_id);
258
259 $total_processed++;
260
261 // Free memory every 100 processed items
262 if ($total_processed % 100 === 0) {
263 gc_collect_cycles();
264 //error_log("[AutoCron] Processed {$total_processed} total, memory: " . (memory_get_usage(true) / 1024 / 1024) . ' MB');
265 }
266 }
267
268 // 6. Prepare next batch
269 $paged++;
270 unset($post_ids); // Free memory
271 gc_collect_cycles(); // Trigger garbage collection
272 //error_log("[AutoCron] After batch {$paged}, memory: " . (memory_get_usage(true) / 1024 / 1024) . ' MB');
273
274 } while (true);
275
276 mlsimport_telemetry_set( 'last_sync_success', time() );
277
278 //error_log('[AutoCron] Done, total processed: ' . $total_processed . ', end memory: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB');
279 }
280
281
282
283 /*
284 * Reconciliation Mechanism
285 *
286 *
287 *
288 **/
289
290 if ( ! wp_next_scheduled( 'mlsimport_reconciliation_event' ) ) {
291 wp_schedule_event( time(), 'daily', 'mlsimport_reconciliation_event' );
292 }
293
294 add_action( 'mlsimport_reconciliation_event', 'mlsimport_saas_reconciliation_event_function' );
295
296 if ( ! wp_next_scheduled( 'mlsimport_daily_telemetry_event' ) ) {
297 wp_schedule_event( time(), 'daily', 'mlsimport_daily_telemetry_event' );
298 }
299
300 add_action( 'mlsimport_daily_telemetry_event', 'mlsimport_telemetry_run_daily' );
301
302
303 /*
304 * Force use of transient
305 *
306 *
307 *
308 **/
309
310 function mlsimport_force_use_transient( $value ) {
311 return $value;
312 // return false;
313 }
314
315
316
317
318 global $mlsimport;
319 $mlsimport = new Mlsimport();
320 $mlsimport->run();
321
322
323
324
325
326 $supported_theme = array(
327 991 => 'WpResidence',
328 992 => 'Houzez',
329 993 => 'Real Homes',
330 994 => 'Wpestate',
331
332 );
333
334 define( 'MLSIMPORT_THEME', $supported_theme );
335
336 add_filter( 'action_scheduler_failure_period', 'mlsimport_saas_filter_timelimit' );
337 function mlsimport_saas_filter_timelimit( $time_limit ) {
338 return 3000;
339 }
340
341
342
343 /*
344 *
345 * Write logs
346 *
347 **/
348
349 function mlsimport_saas_single_write_import_custom_logs( $message, $tip_import = 'normal' ) {
350 // Check if logging is enabled
351 $enable_logs = intval( get_option( 'mlsimport_disable_logs' ) );
352 if ( 1 !== $enable_logs) {
353 return;
354 }
355
356 if ( is_array( $message ) ) {
357 $message = wp_json_encode( $message );
358 }
359
360 $formatted_message = gmdate( 'F j, Y, g:i a' ) . ' -> ' . $message;
361
362 // Determine the log file path based on the import type
363 $log_file_name = 'cron' === $tip_import ? 'cron_logs' :
364 ( 'delete' === $tip_import ? 'delete_logs' :
365 ( 'server_cron' === $tip_import ? 'server_cron_logs' : 'import_logs' ) );
366
367 // Construct the full path with a date suffix
368 $log_file_path = WP_PLUGIN_DIR . "/mlsimport/logs/{$log_file_name}-" . gmdate( 'Y-m-d' ) . '.log';
369
370 // Error handling for file operations
371 try {
372 // Check and create the directory for logs if it does not exist
373 $log_dir = dirname( $log_file_path );
374 if ( ! file_exists( $log_dir ) ) {
375 mkdir( $log_dir, 0755, true );
376 }
377
378 // Append the formatted message to the log file
379 file_put_contents( $log_file_path, $formatted_message, FILE_APPEND | LOCK_EX );
380 } catch ( Exception $e ) {
381 // Handle the exception, such as logging the error elsewhere or sending a notification
382 }
383 }
384
385
386
387 /*
388 *
389 *
390 * Write Status logs
391 *
392 *
393 **/
394
395
396
397 function mlsimport_debuglogs_per_plugin_old( $message ) {
398
399 if ( is_array( $message ) ) {
400 $message = wp_json_encode( $message );
401 }
402
403 global $wp_filesystem;
404 if ( empty( $wp_filesystem ) ) {
405 require_once ABSPATH . '/wp-admin/includes/file.php';
406 WP_Filesystem();
407 }
408
409 $path_status = WP_PLUGIN_DIR . '/mlsimport/logs/status_logs.log';
410 file_put_contents( $path_status, $message, LOCK_EX );
411 }
412 function mlsimport_debuglogs_per_plugin( $message ) {
413
414 if ( is_array( $message ) ) {
415 $message = wp_json_encode( $message );
416 }
417
418 if ( empty( $message ) ) {
419 return; // Exit the function if there's nothing to log
420 }
421
422 $log_file_path = WP_PLUGIN_DIR . '/mlsimport/logs/status_logs.log';
423
424 // Check and create the directory for logs if it does not exist
425 $log_dir = dirname( $log_file_path );
426 if ( ! file_exists( $log_dir ) ) {
427 mkdir( $log_dir, 0755, true );
428 }
429
430 // Error handling for file operations
431 try {
432 // Append the message to the log file with a newline and acquire an exclusive lock during writing
433 file_put_contents( $log_file_path, $message . PHP_EOL, LOCK_EX );
434 } catch ( Exception $e ) {
435 // Handle the exception, such as logging the error elsewhere or sending a notification
436 }
437 }
438
439
440
441
442
443 /*
444 * Cron job trigger
445 *
446 *
447 *
448 **/
449
450
451 // */5 * * * * wget http://example.com/check */2
452 add_action( 'init', 'mlsimport_trigger_cron_job' );
453 function mlsimport_trigger_cron_job() {
454 // ?mlsimport_cron=yes
455 if ( isset( $_REQUEST['mlsimport_cron'] ) && 'yes' === sanitize_text_field( wp_unslash( $_REQUEST['mlsimport_cron'] ) ) ) {
456 $last_run = intval( get_option( 'mlsimport_last_server_cron' ) );
457 $now = time();
458 if ( 0 === intval($last_run) ) {
459 update_option( 'mlsimport_last_server_cron', $now );
460 }
461
462 if ( $last_run < $now - ( 60 * 60 * 2 ) ) {
463 $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;
464 // mlsimport_saas_event_mls_import_auto_function();
465 update_option( 'mlsimport_last_server_cron', $now );
466 } else {
467 $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;
468 }
469
470 mlsimport_saas_single_write_import_custom_logs( $log, 'server_cron' );
471 }
472 }
473
474
475
476 function mlsimport_show_signup() {
477 $affiliate_url = 'https://mlsimport.com';
478 if ( function_exists( 'wp_estate_init' ) ) {
479 $affiliate_url = 'https://mlsimport.com/ref/1/?campaign=wpresidence';
480 }
481 ?>
482 <div class="mlsimport_signup">
483 <h3><?php esc_html_e('Import MLS Listings into your Real Estate website', 'mlsimport'); ?></h3>
484 <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>
485 <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>
486 </div>
487 <?php
488 }
489
490
491 //add_action('admin_init', 'force_recount_all_terms');
492 function force_recount_all_terms() {
493 global $wpdb;
494
495 // Get all taxonomies
496 $taxonomies = get_taxonomies([], 'names');
497
498 foreach ($taxonomies as $taxonomy) {
499 // Get all terms for the taxonomy
500 $terms = get_terms([
501 'taxonomy' => $taxonomy,
502 'hide_empty' => false, // Include terms with 0 count
503 'fields' => 'ids', // Get only the term IDs
504 ]);
505
506 if (!is_wp_error($terms) && !empty($terms)) {
507 // Get term_taxonomy_ids for these terms
508 $term_taxonomy_ids = $wpdb->get_col($wpdb->prepare(
509 "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE term_id IN (" . implode(',', array_map('intval', $terms)) . ")"
510 ));
511
512 // Update term counts
513 if (!empty($term_taxonomy_ids)) {
514 wp_update_term_count_now($term_taxonomy_ids, $taxonomy);
515 }
516 }
517 }
518
519 echo "Term counts have been recalculated for all taxonomies.";
520 }
521
522
523 /*
524 *
525 * create dropdown list
526 *
527 *
528 */
529 function mlsiport_mls_select_list( $key, $value, $data_array ) {
530 $select = '<select class="mlsimport-2025-select" id="' . esc_attr( $key ) . '" name="mlsimport_admin_options[' . $key . ']">';
531 if ( is_array( $data_array ) ) :
532 foreach ( $data_array as $key => $mls_item ) {
533 $select .= '<option value="' .esc_attr( $key ). '"';
534 if ( intval( $value ) === intval( $key ) ) {
535 $select .= ' selected ';
536 }
537 $select .= '>' .esc_html( $mls_item ). '</option>';
538 }
539 endif;
540 $select .= '</select>';
541 return $select;
542 }
543
544
545
546 add_action('wp_ajax_mlsimport_save_account', 'mlsimport_save_account_callback');
547 function mlsimport_save_account_callback() {
548 check_ajax_referer('mlsimport_onboarding_nonce', 'security');
549
550 $options = get_option('mlsimport_admin_options', []);
551 if ( ! empty($_POST['mlsimport_username']) && ! empty($_POST['mlsimport_password']) ) {
552 $options['mlsimport_username'] = sanitize_text_field($_POST['mlsimport_username']);
553 $options['mlsimport_password'] = sanitize_text_field($_POST['mlsimport_password']);
554 update_option('mlsimport_admin_options', $options);
555 }
556
557 global $mlsimport;
558
559 // Refresh token
560 $token = $mlsimport->admin->mlsimport_saas_get_mls_api_token_from_transient();
561
562 if (trim($token) === '') {
563 ob_start();
564
565 ?>
566 <div class="mlsimport_warning">
567 <?php esc_html_e('You are not connected to MlsImport - Please check your Username and Password.', 'mlsimport'); ?>
568 </div>
569 <?php
570 $html = ob_get_clean();
571
572 wp_send_json_success([
573 'message' => __('You are not connected.', 'mlsimport'),
574 'html' => $html,
575 'connected' => false
576 ]);
577 } else {
578 ob_start();
579 ?>
580 <div class="mlsimport_warning mlsimport_validated">
581 <?php esc_html_e('You are connected to your MlsImport account!', 'mlsimport'); ?>
582 </div>
583 <?php
584 $html = ob_get_clean();
585
586 wp_send_json_success([
587 'message' => __('Connected successfully!', 'mlsimport'),
588 'html' => $html,
589 'connected' => true
590 ]);
591 }
592 }
593
594
595
596
597
598
599
600
601 add_action('wp_ajax_mlsimport_save_mls_data', 'mlsimport_save_mls_data_callback');
602 function mlsimport_save_mls_data_callback() {
603 check_ajax_referer('mlsimport_onboarding_nonce', 'security');
604
605 $options = get_option('mlsimport_admin_options', []);
606
607 foreach ($_POST as $key => $value) {
608 if (strpos($key, 'mlsimport_') === 0 && $key !== 'mlsimport_username' && $key !== 'mlsimport_password') {
609 $options[$key] = sanitize_text_field($value);
610 }
611 }
612
613 update_option('mlsimport_admin_options', $options);
614
615 // Run MLS connection check
616 global $mlsimport;
617 $is_mls_connected = get_option('mlsimport_connection_test', '');
618 $mlsimport->admin->mlsimport_saas_setting_up();
619
620 if ('yes' !== $is_mls_connected) {
621 $mlsimport->admin->mlsimport_saas_check_mls_connection();
622 $is_mls_connected = get_option('mlsimport_connection_test', '');
623 }
624
625 ob_start();
626 if ('yes' === $is_mls_connected) {
627 ?>
628 <div class="mlsimport_warning mlsimport_validated">
629 <?php esc_html_e('You’re now connected to your MLS.', 'mlsimport'); ?>
630 </div>
631 <?php
632 } else {
633 ?>
634 <div class="mlsimport_warning">
635 <?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'); ?>
636 </div>
637 <?php
638 }
639 $html = ob_get_clean();
640
641 wp_send_json_success([
642 'message' => __('MLS data saved', 'mlsimport'),
643 'html' => $html,
644 'connected' => $is_mls_connected === 'yes',
645 ]);
646 }
647
648
649