Documentation · Technical Documentation

Import Engine

This document describes how the ADP Car Market Hub plugin imports vehicle listings from the AutoScout24 API into WordPress. It covers the responsibilities of the importer classes, the per-listing flow, change detection, full-sync deletion and the public hook that fires after a vehicle is imported.

When to use this document

Read this document if you need to:

  • Understand what happens during an import run.
  • Diagnose why a vehicle was inserted, updated, skipped or removed.
  • Build a custom integration that reacts to imports via the as24ci_vehicle_imported action.
  • Plan capacity or hosting requirements for large catalogues.

For scheduling and cron details, see Cron Events And Scheduler. For image handling, see Image Importer And Queue.

Overview

The import engine consists of several classes that work together:

  • AS24CI\Client — issues authenticated HTTP requests to the AutoScout24 API, manages OAuth tokens (including the as24ci_access_token transient cache) and exposes helpers for preview pages and per-listing equipment.
  • AS24CI\Importer — coordinates per-listing import. Decides whether to insert, update or skip and writes the vehicle's post, postmeta and image references. Owns change detection.
  • AS24CI\Mapper — maps the raw AutoScout24 payload to the fields stored in the as24_vehicles table via AS24CI\Vehicle_Repository. Maintains backwards-compatible postmeta keys.
  • AS24CI\Vehicle_Repository — persists vehicle field data in the dedicated {$wpdb->prefix}as24_vehicles table.
  • AS24CI\Image_Importer — downloads images, optionally converts them to WebP, and attaches them to the vehicle post. See Image Importer And Queue.
  • AS24CI\Scheduler — wraps Importer::import_all_for_seller() in a locking, retry-safe runner used by WP-Cron, the REST cron endpoint and the manual "Run now" button.

The same Importer instance is reused by the manual Batch-Wizard, the cron runner and the REST cron endpoint.

Requirements or prerequisites

Before running an import you need:

  • Valid AutoScout24 API credentials configured in the plugin (as24ci_base_url, as24ci_token_url, as24ci_client_id, as24ci_client_secret, as24ci_token_audience).
  • One or more seller IDs in as24ci_seller_ids (comma-separated).
  • A WordPress user designated as the default post author (as24ci_default_post_author); imports fall back to the current user when no default is set.
  • Working outbound HTTPS access from the WordPress server to the AutoScout24 API and to the image hosts referenced in the API response.
  • Sufficient PHP execution time. The scheduler raises the time limit to 300 seconds via set_time_limit(300) for cron and REST runs; some hosts may override this.

Per-listing flow

AS24CI\Importer::upsert_post_from_listing() is the central per-listing routine. The simplified flow is:

  1. Validate the listing has an id. Skip otherwise.
  2. Skip listings whose API status is not activated or whose live flag is empty.
  3. Look up an existing vehicle post by listing ID (find_post_id_by_listing_id()).
  4. Run change detection (see below). If nothing has changed, write _as24ci_last_sync and return skipped.
  5. Build the post title, excerpt and content. If the AI Lock (_as24ci_ai_locked = 'yes') is active, do not overwrite the post excerpt or content.
  6. Insert or update the WordPress post with the configured default post status and author.
  7. Write backwards-compatibility postmeta: _as24ci_listing_id, _as24ci_seller_id, _as24ci_last_modified (when the API supplies it) and _as24ci_last_sync.
  8. Ensure the slug ends with the listing ID (ensure_slug_has_listing_id()).
  9. Map the listing payload via AS24CI\Mapper::map_listing_to_post() so the typed fields are written to the as24_vehicles table.
  10. Fetch equipment via Client::get_listing_equipment() and map it to the post via Mapper::map_equipment_to_post(). Errors are logged but do not fail the listing.
  11. Import images (subject to the as24ci_import_images toggle and as24ci_max_images cap). The image flow is described in detail in Image Importer And Queue.
  12. Update _as24ci_content_hash and _as24ci_original_description.
  13. Fire the as24ci_vehicle_imported action with the post ID, the raw API listing and a boolean $is_update.
  14. Return one of the strings inserted, updated, skipped or error (on wp_insert_post / wp_update_post failure).

Change detection

The importer skips listings that have not changed since the previous run, using two cascading checks:

  • Primary: the lastModifiedDate field returned by the API. If the local _as24ci_last_modified postmeta matches the remote value, the listing is treated as unchanged. The importer still refreshes _as24ci_last_sync so that full-sync logic knows the listing exists remotely.
  • Fallback: when lastModifiedDate is missing, the importer computes an MD5 of the JSON-encoded payload and compares it against the stored _as24ci_content_hash.

Image change detection runs independently and is described in the image importer documentation.

AI Lock

When _as24ci_ai_locked is 'yes', the importer keeps the existing post_content and post_excerpt so AI-generated copy survives a re-import. All other fields, taxonomy assignments, equipment and images are still updated. The original API description is also preserved separately in _as24ci_original_description.

Slug stability

ensure_slug_has_listing_id() updates the post slug to end with -<listing_id> whenever the slug changes. This keeps URLs stable across re-imports and avoids accidental redirects when titles change.

Bulk operations

AS24CI\Importer exposes the following high-level methods:

  • get_seller_ids() — returns the cleaned list of configured seller IDs.
  • get_all_preview_listings_for_seller( $seller_id, $max_pages = 20, $page_size = 50 ) — pages through the API and returns the full set of activated, live listings for a single seller.
  • preview_listings_for_seller( $seller_id, $page = 1, $per_page = 50 ) — paginated preview used by the wizard's UI.
  • import_selected_listings( $seller_id, $listing_ids, $max_vehicles = 0 ) — imports the given listing IDs. Honours the $max_vehicles budget; skipped vehicles do not consume budget.
  • import_all_for_seller( $seller_id, $max_vehicles = 0 ) — fetches the full preview list for a seller and delegates to import_selected_listings(). Returns counts plus listing_ids (the full set seen this run) and api_active (number of active listings the API returned).
  • full_sync_after_import( array $remote_listing_ids ) — deletes local as24ci_car posts whose _as24ci_listing_id is not in the given remote set. Skipped if the remote set is empty as a safety guard against accidental wipe.
  • hard_delete_listing( $listing_id ) — manual destructive delete for a single listing; goes through the same Vehicle_Deleter cleanup as native WordPress delete.

The "All-in-One" version of the plugin imposes no listing cap; get_free_import_limit() and get_free_slots_left() return PHP_INT_MAX.

Vehicle deletion

Every permanent delete path flows through AS24CI\Vehicle_Deleter:

  • WordPress native "Delete permanently" on the Cars list.
  • Importer full sync (full_sync_after_import()).
  • Bulk actions (AS24CI\Bulk_Actions).
  • Manual Importer::hard_delete_listing().

The deleter runs on before_delete_post / deleted_post and:

  • Removes attachments tracked in _as24ci_image_ids.
  • Removes the corresponding row in {$wpdb->prefix}as24_vehicles.
  • Fires the as24ci_vehicle_deleted action.

Manual gallery attachments (_as24ci_manual_image_ids) and other attachments not tracked by the importer are intentionally preserved.

Public hooks

The import engine fires the following hooks. Verify hook signatures in the current plugin version before relying on them.

HookWhen it fires
as24ci_vehicle_importedAfter upsert_post_from_listing() finishes. Args: $post_id, $listing, $is_update.
as24ci_vehicle_deletedAfter a vehicle and its tracked attachments are removed via Vehicle_Deleter.

The plugin also reads the as24ci_webp_quality filter when converting images; see the image importer documentation.

Configuration reference

OptionEffectDefault
as24ci_seller_idsComma-separated seller IDs to import.(none)
as24ci_default_post_statusPost status for newly inserted vehicles.draft
as24ci_default_post_authorDefault author user ID for inserted vehicles.(none → current user)
as24ci_import_imagesWhether to import images.(toggle in admin)
as24ci_max_imagesMax images per vehicle. 0 = no plugin-side cap.30
as24ci_full_syncDelete local vehicles missing from the API after each import.0
as24ci_cron_image_queueUse the image queue during cron/REST runs.1
as24ci_cron_max_vehiclesVehicle cap per cron/REST run. 0 = unlimited.(Scheduler default 50)
as24ci_verbose_loggingLog a line per vehicle and image action.1
as24ci_mapping_overridesPer-field label and visibility overrides used by the admin UI.(empty)

Operational notes

  • The importer never throws on a single bad listing. Errors from wp_insert_post, wp_update_post, Client::get_listing_equipment and the image importer are logged via AS24CI\Logger and counted but do not abort the run.
  • Change detection means a full re-import of an unchanged catalogue is inexpensive: most listings are skipped and image downloads are not re-issued.
  • The mapper writes to the as24_vehicles table via the repository, not to wp_postmeta, except for the small backwards-compat key set documented in Data Model.
  • Full-sync is opt-in. If as24ci_full_sync is enabled, ensure the configured seller IDs cover the entire catalogue you want to keep online; vehicles whose listings disappear from the API are permanently deleted.
  • Verbose logging produces detailed log lines and grows quickly on large catalogues. The plugin enforces a 10 MB log cap with rotation; adjust verbose logging to balance diagnostics with storage.

Troubleshooting

  • No vehicles imported. Confirm the API credentials, that as24ci_seller_ids is non-empty, and that the API returns listings with status = activated and live = true. Check the plugin log for HTTP errors from AS24CI\Client.
  • Listings remain in draft status. The plugin defaults as24ci_default_post_status to draft so administrators can review mappings. Change the option to publish once you are satisfied, or publish individual vehicles from the admin list.
  • Repeated re-imports keep updating the same vehicles. Verify that the API supplies a stable lastModifiedDate. When it is missing, the fallback content hash detects changes; the hash will change whenever the API payload changes for any reason.
  • A vehicle disappeared after a cron run. Check whether as24ci_full_sync is enabled. With full sync on, any listing missing from the API is permanently deleted (its imported attachments included).
  • Importer ran but no images were downloaded. Check as24ci_import_images and as24ci_max_images. In cron/REST runs with as24ci_cron_image_queue = 1, only the first image is downloaded immediately and the rest are deferred to the image queue worker.
  • Skipping listing_id=… : lastModifiedDate unchanged. This is the expected verbose log line for unchanged listings; it confirms change detection is working.