'ids' so only post IDs are loaded (saves memory) * - Batches with posts_per_page/paged, so memory does not spike for large data sets * - Calls gc_collect_cycles() periodically to further reduce memory leaks * - Skips processing if MLS is not connected or token is missing * * @return void */ add_action('event_mls_import_auto', 'mlsimport_saas_event_mls_import_auto_function'); /** * Scheduled event handler for MLS Import Auto (runs via WP Cron). * Processes mlsimport_item posts in batches and logs memory usage. */ function mlsimport_saas_event_mls_import_auto_function() { global $mlsimport; //error_log('[AutoCron] Start: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB'); // 1. Get the API token from transient - exit if not set $token = $mlsimport->admin->mlsimport_saas_get_mls_api_token_from_transient(); //error_log('[AutoCron] After token fetch: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB'); if (trim($token) === '') { //error_log('[AutoCron] No token, exiting.'); return; } // 2. Check if MLS connection is valid - exit if not $is_mls_connected = get_option('mlsimport_connection_test', ''); //error_log('[AutoCron] After connection check: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB'); if ('yes' !== $is_mls_connected) { //error_log('[AutoCron] No valid connection, exiting.'); return; } // 3. Set batch size for processing and initialize loop variables $batch_size = 100; $paged = 1; $total_processed = 0; // 4. Process in batches until no more items are found do { // Prepare query: only IDs, filter by meta key, batch, paged, no_found_rows speeds up query $args = array( 'post_type' => 'mlsimport_item', 'post_status' => 'any', 'posts_per_page' => $batch_size, 'paged' => $paged, 'fields' => 'ids', 'meta_query' => array( array( 'key' => 'mlsimport_item_stat_cron', 'value' => 1, 'compare' => '=', ), ), 'no_found_rows' => true, ); // Get post IDs for this batch $post_ids = get_posts($args); //error_log("[AutoCron] Batch {$paged} fetched " . count($post_ids) . " items, memory: " . (memory_get_usage(true) / 1024 / 1024) . ' MB'); // If nothing is returned, break the loop if (empty($post_ids)) { break; } // 5. Loop through each post ID in this batch foreach ($post_ids as $prop_id) { $logs = 'Loop custom post: ' . $prop_id . PHP_EOL; mlsimport_debuglogs_per_plugin($logs); // Call processing function for this item $mlsimport->admin->mlsimport_saas_start_cron_links_per_item($prop_id); $total_processed++; // Free memory every 100 processed items if ($total_processed % 100 === 0) { gc_collect_cycles(); //error_log("[AutoCron] Processed {$total_processed} total, memory: " . (memory_get_usage(true) / 1024 / 1024) . ' MB'); } } // 6. Prepare next batch $paged++; unset($post_ids); // Free memory gc_collect_cycles(); // Trigger garbage collection //error_log("[AutoCron] After batch {$paged}, memory: " . (memory_get_usage(true) / 1024 / 1024) . ' MB'); } while (true); //error_log('[AutoCron] Done, total processed: ' . $total_processed . ', end memory: ' . (memory_get_usage(true) / 1024 / 1024) . ' MB'); } /* * Reconciliation Mechanism * * * **/ if ( ! wp_next_scheduled( 'mlsimport_reconciliation_event' ) ) { wp_schedule_event( time(), 'daily', 'mlsimport_reconciliation_event' ); } add_action( 'mlsimport_reconciliation_event', 'mlsimport_saas_reconciliation_event_function' ); /* * Force use of transient * * * **/ function mlsimport_force_use_transient( $value ) { return $value; // return false; } global $mlsimport; $mlsimport = new Mlsimport(); $mlsimport->run(); $supported_theme = array( 991 => 'WpResidence', 992 => 'Houzez', 993 => 'Real Homes', 994 => 'Wpestate', ); define( 'MLSIMPORT_THEME', $supported_theme ); add_filter( 'action_scheduler_failure_period', 'mlsimport_saas_filter_timelimit' ); function mlsimport_saas_filter_timelimit( $time_limit ) { return 3000; } /* * * Write logs * **/ function mlsimport_saas_single_write_import_custom_logs( $message, $tip_import = 'normal' ) { // Check if logging is enabled $enable_logs = intval( get_option( 'mlsimport_disable_logs' ) ); if ( 1 !== $enable_logs) { return; } if ( is_array( $message ) ) { $message = wp_json_encode( $message ); } $formatted_message = gmdate( 'F j, Y, g:i a' ) . ' -> ' . $message; // Determine the log file path based on the import type $log_file_name = 'cron' === $tip_import ? 'cron_logs' : ( 'delete' === $tip_import ? 'delete_logs' : ( 'server_cron' === $tip_import ? 'server_cron_logs' : 'import_logs' ) ); // Construct the full path with a date suffix $log_file_path = WP_PLUGIN_DIR . "/mlsimport/logs/{$log_file_name}-" . gmdate( 'Y-m-d' ) . '.log'; // Error handling for file operations try { // Check and create the directory for logs if it does not exist $log_dir = dirname( $log_file_path ); if ( ! file_exists( $log_dir ) ) { mkdir( $log_dir, 0755, true ); } // Append the formatted message to the log file file_put_contents( $log_file_path, $formatted_message, FILE_APPEND | LOCK_EX ); } catch ( Exception $e ) { // Handle the exception, such as logging the error elsewhere or sending a notification } } /* * * * Write Status logs * * **/ function mlsimport_debuglogs_per_plugin_old( $message ) { if ( is_array( $message ) ) { $message = wp_json_encode( $message ); } global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . '/wp-admin/includes/file.php'; WP_Filesystem(); } $path_status = WP_PLUGIN_DIR . '/mlsimport/logs/status_logs.log'; file_put_contents( $path_status, $message, LOCK_EX ); } function mlsimport_debuglogs_per_plugin( $message ) { if ( is_array( $message ) ) { $message = wp_json_encode( $message ); } if ( empty( $message ) ) { return; // Exit the function if there's nothing to log } $log_file_path = WP_PLUGIN_DIR . '/mlsimport/logs/status_logs.log'; // Check and create the directory for logs if it does not exist $log_dir = dirname( $log_file_path ); if ( ! file_exists( $log_dir ) ) { mkdir( $log_dir, 0755, true ); } // Error handling for file operations try { // Append the message to the log file with a newline and acquire an exclusive lock during writing file_put_contents( $log_file_path, $message . PHP_EOL, LOCK_EX ); } catch ( Exception $e ) { // Handle the exception, such as logging the error elsewhere or sending a notification } } /* * Cron job trigger * * * **/ // */5 * * * * wget http://example.com/check */2 add_action( 'init', 'mlsimport_trigger_cron_job' ); function mlsimport_trigger_cron_job() { // ?mlsimport_cron=yes if ( isset( $_REQUEST['mlsimport_cron'] ) && 'yes' === sanitize_text_field( wp_unslash( $_REQUEST['mlsimport_cron'] ) ) ) { $last_run = intval( get_option( 'mlsimport_last_server_cron' ) ); $now = time(); if ( 0 === intval($last_run) ) { update_option( 'mlsimport_last_server_cron', $now ); } if ( $last_run < $now - ( 60 * 60 * 2 ) ) { $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; // mlsimport_saas_event_mls_import_auto_function(); update_option( 'mlsimport_last_server_cron', $now ); } else { $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; } mlsimport_saas_single_write_import_custom_logs( $log, 'server_cron' ); } } function mlsimport_show_signup() { $affiliate_url = 'https://mlsimport.com'; if ( function_exists( 'wp_estate_init' ) ) { $affiliate_url = 'https://mlsimport.com/ref/1/?campaign=wpresidence'; } ?>
$taxonomy, 'hide_empty' => false, // Include terms with 0 count 'fields' => 'ids', // Get only the term IDs ]); if (!is_wp_error($terms) && !empty($terms)) { // Get term_taxonomy_ids for these terms $term_taxonomy_ids = $wpdb->get_col($wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE term_id IN (" . implode(',', array_map('intval', $terms)) . ")" )); // Update term counts if (!empty($term_taxonomy_ids)) { wp_update_term_count_now($term_taxonomy_ids, $taxonomy); } } } echo "Term counts have been recalculated for all taxonomies."; } /* * * create dropdown list * * */ function mlsiport_mls_select_list( $key, $value, $data_array ) { $select = ''; return $select; } add_action('wp_ajax_mlsimport_save_account', 'mlsimport_save_account_callback'); function mlsimport_save_account_callback() { check_ajax_referer('mlsimport_onboarding_nonce', 'security'); $options = get_option('mlsimport_admin_options', []); if ( ! empty($_POST['mlsimport_username']) && ! empty($_POST['mlsimport_password']) ) { $options['mlsimport_username'] = sanitize_text_field($_POST['mlsimport_username']); $options['mlsimport_password'] = sanitize_text_field($_POST['mlsimport_password']); update_option('mlsimport_admin_options', $options); } global $mlsimport; // Refresh token $token = $mlsimport->admin->mlsimport_saas_get_mls_api_token_from_transient(); if (trim($token) === '') { ob_start(); ?>