PluginProbe
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings / 7.2
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings v7.2
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 6.0.7 All 35 releases
← All changes | includes/help_functions.php +54 -7 7.0.77.2 View file →
@@ -2873,8 +2873,15 @@
2873 2873
2874 2874 // Success: reshape the list into autocomplete {label,value} pairs.
2875 2875 if ( isset( $answer['success'] ) && true === $answer['success'] ) {
2876 2876 $mls_data = $answer['mls_list'];
2877 +
2878 + // Fresh catalogue in hand: refresh registered connections' display
2879 + // names so an MLS renamed upstream shows its new name everywhere
2880 + // (Connections table, import task picker) after a cache clear.
2881 + if ( is_array( $mls_data ) && class_exists( 'Mlsimport_Connections' ) ) {
2882 + Mlsimport_Connections::sync_names( $mls_data );
2883 + }
2877 2884 // Prepend the "not listed" opt-out choice.
2878 2885 $mls_data['0'] = esc_html__( 'My MLS is not on this list', 'mlsimport' );
2879 2886
2880 2887 $autofill_array = array();
@@ -2952,11 +2959,17 @@
2952 2959 /**
2953 2960 * Cron entry point for the daily SaaS reconciliation pass.
2954 2961 *
2955 2962 * Bails out early unless at least one non-trashed import task has a title, then
2956 - * kicks off reconciliation when an MLS name is configured.
2963 + * hands off to the per-connection runner (#279) when an MLS name is configured:
2964 + * one sub-run of the deep reconciliation module per registered connection,
2965 + * or the single legacy unscoped run while no connections are registered.
2957 2966 *
2958 - * @return void
2967 + * The same function handles the deduplicated one-hour retry hook — a retry
2968 + * re-runs all connections, and completed ones converge to no-op keeps. Trigger
2969 + * code intentionally owns no snapshot, status, batching, or deletion decisions.
2970 + *
2971 + * @return array<int, array<string, int|string>>|null Outcome per connection, or null when ineligible.
2959 2972 */
2960 2973 function mlsimport_saas_reconciliation_event_function() {
2961 2974
2962 2975 // Pull the API token (side effect: ensures a fresh token) and plugin options.
@@ -2973,15 +2986,19 @@
2973 2986 LIMIT 1"
2974 2987 );
2975 2988 // No titled task -> nothing to reconcile, abort.
2976 2989 if ( ! $has_titled_task ) {
2977 - return;
2990 + return null;
2978 2991 }
2979 2992
2980 - // Only reconcile when an MLS name is configured.
2993 + // Only reconcile when an MLS name is configured. The runner sequences one
2994 + // scoped sub-run per registered connection (legacy unscoped run when the
2995 + // registry is empty) and records/logs every outcome itself.
2981 2996 if ( isset( $options['mlsimport_mls_name'] ) && '' !== $options['mlsimport_mls_name'] ) {
2982 - $mlsimport->admin->mlsimport_saas_start_doing_reconciliation();
2997 + return mlsimport_reconciliation_run_connections();
2983 2998 }
2999 +
3000 + return null;
2984 3001 }
2985 3002
2986 3003 /*
2987 3004 * Admin extra columns for MlsImport Items
@@ -3017,8 +3034,9 @@
3017 3034 $splice = array_splice( $columns, 2 );
3018 3035
3019 3036 // Append the plugin's own columns.
3020 3037 $columns['mlsimport_items_params'] = esc_html__( 'Import Parameters', 'mlsimport' );
3038 + $columns['mlsimport_task_health'] = esc_html__( 'Status', 'mlsimport' );
3021 3039 $columns['mlsimport_last_action'] = esc_html__( 'Last action', 'mlsimport' );
3022 3040 $columns['mlsimport_autoupdates'] = esc_html__( 'Auto Update Enabled', 'mlsimport' );
3023 3041
3024 3042 // Return the plugin columns followed by the preserved slice (reversed).
@@ -3081,11 +3099,12 @@
3081 3099 * @param int $postID Import Task post ID.
3082 3100 * @return void Output is echoed directly.
3083 3101 */
3084 3102 function mlsimport_populate_columns_params_display( $postID ) {
3085 - // Field definitions come from the admin class.
3103 + // Field definitions come from the admin class, scoped to the TASK's own
3104 + // connection (#277) so each row's parameters render against its MLS.
3086 3105 global $mlsimport;
3087 - $field_import = $mlsimport->admin->mlsimport_saas_return_mls_fields();
3106 + $field_import = $mlsimport->admin->mlsimport_saas_return_mls_fields( mlsimport_task_mls_id( (int) $postID ) );
3088 3107
3089 3108 // Fields whose stored value is always shown verbatim (never collapsed to "ALL").
3090 3109 $select_all_none = array(
3091 3110 'InternetAddressDisplayYN',
@@ -3201,8 +3220,36 @@
3201 3220 <?php
3202 3221
3203 3222 // Then the per-field import parameters.
3204 3223 mlsimport_populate_columns_params_display( $post->ID );
3224 + } elseif ( 'mlsimport_task_health' === $column ) {
3225 + // Status column (GitHub issue #200): surface stuck, failed, and
3226 + // sync-overdue tasks directly in the list. All inputs are already
3227 + // recorded — the run status meta (state, progress, heartbeat, error),
3228 + // the sync watermark, and the auto-sync flag. The badge decision
3229 + // itself lives in the pure, unit-tested mlsimport_task_health().
3230 + $health_status = get_post_meta( $post->ID, 'mlsimport_import_run_status', true );
3231 + $health = mlsimport_task_health(
3232 + is_array( $health_status ) ? $health_status : array(),
3233 + (string) get_post_meta( $post->ID, 'mlsimport_last_date', true ),
3234 + 1 === (int) get_post_meta( $post->ID, 'mlsimport_item_stat_cron', true ),
3235 + time(),
3236 + // Watermarks are stored with wp_date() in site-local time, so
3237 + // the overdue cutoff must be built the same way to compare.
3238 + wp_date( 'Y-m-d\TH:i', time() - MLSIMPORT_TASK_HEALTH_OVERDUE_AFTER ),
3239 + // The hourly runner's own eligibility rule (GitHub issue #330):
3240 + // a task it will never pick up must not read as merely overdue.
3241 + mlsimport_cron_task_is_eligible(
3242 + (int) get_post_meta( $post->ID, 'mlsimport_initial_import_completed', true ),
3243 + (string) get_post_meta( $post->ID, 'mlsimport_spawn_status', true )
3244 + )
3245 + );
3246 + ?>
3247 + <span class="mlsimport-task-health mlsimport-task-health--<?php echo esc_attr( $health['level'] ); ?>">
3248 + <?php echo esc_html( $health['label'] ); ?>
3249 + </span>
3250 + <p class="mlsimport-task-health__message"><?php echo esc_html( $health['message'] ); ?></p>
3251 + <?php
3205 3252 } elseif ( 'mlsimport_last_action' === $column ) {
3206 3253 // Last action column: date of the most recent import activity.
3207 3254 $last_date = get_post_meta( $post->ID, 'mlsimport_last_date', true );
3208 3255 if ( '' !== $last_date ) {