ads AS $ad ) : // Retrieve data of individual vehicles $url = 'https://services.mobile.de/search-api/ad/'.$ad->mobileAdId; $ad_json = mobile_api_request( $url ); // Request failed or returned no JSON: keep the last sync so the next run retries this vehicle if ( !is_object( $ad_json ) ) { $retry = true; continue; } // API error instead of an ad, e.g. deleted in the meantime: skip it, the delete cron removes it if ( !property_exists( $ad_json, 'mobileAdId' ) ) continue; // Check if vehicle already exists $args = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'meta_key' => 'mobile_api_mobileAdId', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value 'meta_value' => $ad->mobileAdId, 'post_type' => 'mobile-api-vehicle', 'posts_per_page' => 1 ); $posts = get_posts( $args ); if ( $posts ) mobile_api_update_vehicle( $ad_json, $posts[0]->ID ); else mobile_api_create_vehicle( $ad_json ); endforeach; $max_pages = property_exists( $json, 'maxPages' ) ? intval( $json->maxPages ) : 1; $page++; } while ( $page <= $max_pages ); if ( $retry ) return; update_option( 'mobile_api_last_sync', $now->format('Y-m-d\TH:i:s.0\Z') ); // ISO-8601 } function mobile_api_delete_vehicles( $reset = false ) { $args = array( 'post_type' => 'mobile-api-vehicle', 'posts_per_page' => -1 ); $posts = get_posts( $args ); if ( $posts ) : foreach ( $posts as $post ) : $post_id = $post->ID; $mobileAdId = get_post_meta( $post_id, 'mobile_api_mobileAdId', true ); if ( !$reset && !empty( $mobileAdId ) ) { $url = 'https://services.mobile.de/search-api/ad/'.$mobileAdId; $json = mobile_api_request( $url ); // Keep the vehicle if the request failed or returned no JSON, only delete on an explicit API error if ( !is_object( $json ) || !property_exists( $json, 'errors' ) ) continue; } // The images are deleted with the post, see mobile_api_delete_vehicle_images() wp_delete_post( $post_id ); mobile_api_log( $mobileAdId, $post_id, 'DELETE' ); endforeach; endif; } // Completes the images from the stored mobile.de data, e.g. of vehicles imported by earlier versions or after a failed download. Stops after 20 seconds, the next run continues. function mobile_api_import_missing_vehicle_images() { // The initial import is still running and imports the images itself if ( empty( get_option( 'mobile_api_last_sync' ) ) ) return; $start = time(); $post_ids = get_posts( array( 'post_type' => 'mobile-api-vehicle', 'posts_per_page' => -1, 'fields' => 'ids' ) ); foreach ( $post_ids AS $post_id ) : $images = maybe_unserialize( get_post_meta( $post_id, 'mobile_api_images', true ) ); if ( empty( $images ) || !is_array( $images ) ) continue; // Nothing to do if every image is imported once. mobile.de can list the same image twice, so the different hashes are counted. if ( count( mobile_api_get_vehicle_images( $post_id ) ) == count( array_unique( wp_list_pluck( $images, 'hash' ) ) ) ) continue; mobile_api_import_vehicle_images( $images, $post_id, get_post_field( 'post_title', $post_id ) ); if ( time() - $start > 20 ) break; endforeach; } // Weekly if ( !wp_next_scheduled( 'mobile_api_cron_weekly' ) ) { wp_schedule_event( time(), 'daily', 'mobile_api_cron_weekly' ); } add_action( 'mobile_api_cron_weekly', 'mobile_api_clean_database' ); function mobile_api_clean_database() { global $wpdb; // Delete old entries to keep databases small and clean $timestamp = gmdate( 'Y-m-d', strtotime( '-12 months' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->get_results( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}mobile_api_logs WHERE timestamp < %s", array( $timestamp ) ) ); }