Dokumentation · Technische Dokumentation

Import-Engine

Dieses Dokument beschreibt, wie das ADP Car Market Hub-Plugin Fahrzeugangebote in WordPress importiert. Das Plugin unterstützt zwei Import-Frontends, die dieselbe nachgelagerte Pipeline nutzen:

  • den AutoScout24-API-Importer (AS24CI\ClientAS24CI\Importer), der unten im Detail dokumentiert ist, und
  • den Universal Importer (AS24CI\Universal_Importer), der CSV- / XML- / XLSX- / JSON- / ZIP-Dateien und benannte Konnektoren (Feed, E-Mail, carcuro) importiert. Siehe Der Universal Importer unten und die Referenz zum Universal-Import-Admin.

Dieses Dokument behandelt die Zuständigkeiten der Importer-Klassen, den Ablauf pro Fahrzeug, die Änderungserkennung, die Löschung bei Vollsynchronisation und den öffentlichen Hook, der nach dem Import eines Fahrzeugs ausgelöst wird.

Wann Sie dieses Dokument lesen sollten

Lesen Sie dieses Dokument, wenn Sie Folgendes tun müssen:

  • Verstehen, was während eines Importlaufs geschieht.
  • Diagnostizieren, warum ein Fahrzeug hinzugefügt, aktualisiert, übersprungen oder entfernt wurde.
  • Eine benutzerdefinierte Integration erstellen, die über die Aktion as24ci_vehicle_imported auf Importe reagiert.
  • Kapazitäts- oder Hosting-Anforderungen für grosse Kataloge planen.

Für Details zur Zeitplanung und zu Cron-Jobs siehe Cron-Events und Scheduler. Für die Bildverarbeitung siehe Bild-Importer und Warteschlange.

Übersicht

Die Import-Engine besteht aus mehreren Klassen, die zusammenarbeiten:

  • AS24CI\Client — führt authentifizierte HTTP-Anfragen an die AutoScout24-API aus, verwaltet OAuth-Tokens (einschliesslich des transienten Caches as24ci_access_token) und stellt Hilfsfunktionen für Vorschauseiten und die Ausstattung pro Fahrzeug bereit.
  • AS24CI\Importer — koordiniert den Import pro Fahrzeug. Entscheidet, ob eingefügt, aktualisiert oder übersprungen werden soll, und schreibt den Post, die Postmeta und die Bildreferenzen des Fahrzeugs. Ist für die Änderungserkennung zuständig.
  • AS24CI\Mapper — ordnet die rohen AutoScout24-Daten über AS24CI\Vehicle_Repository den in der Tabelle as24_vehicles gespeicherten Feldern zu. Pflegt abwärtskompatible Postmeta-Schlüssel.
  • AS24CI\Vehicle_Repository — speichert die Fahrzeugfelddaten dauerhaft in der dedizierten Tabelle {$wpdb->prefix}as24_vehicles.
  • AS24CI\Image_Importer — lädt Bilder herunter, konvertiert sie optional in das WebP-Format und hängt sie an den Fahrzeug-Post an. Siehe Bild-Importer und Warteschlange.
  • AS24CI\Scheduler — kapselt Importer::import_all_for_seller() in einem sperrsicheren, wiederholungsfähigen Runner, der von WP-Cron, dem REST-Cron-Endpunkt und der manuellen Schaltfläche "Jetzt ausführen" verwendet wird.

Dieselbe Instanz von Importer wird vom manuellen Batch-Wizard, dem Cron-Runner und dem REST-Cron-Endpunkt wiederverwendet.

Anforderungen oder Voraussetzungen

Vor dem Ausführen eines Imports benötigen Sie:

  • Gültige API-Zugangsdaten für AutoScout24, die im Plugin konfiguriert sind (as24ci_base_url, as24ci_token_url, as24ci_client_id, as24ci_client_secret, as24ci_token_audience).
  • Eine oder mehrere Seller-IDs in as24ci_seller_ids (kommagetrennt).
  • Einen WordPress-Benutzer, der als Standard-Post-Autor festgelegt ist (as24ci_default_post_author); Importe fallen auf den aktuellen Benutzer zurück, wenn kein Standard definiert ist.
  • Funktionierenden ausgehenden HTTPS-Zugriff vom WordPress-Server auf die AutoScout24-API und auf die in der API-Antwort referenzierten Bild-Hosts.
  • Ausreichend PHP-Ausführungszeit. Der Scheduler erhöht das Zeitlimit über set_time_limit(300) für Cron- und REST-Läufe auf 300 Sekunden; einige Hosts überschreiben dies möglicherweise.

Ablauf pro Fahrzeug

AS24CI\Importer::upsert_post_from_listing() ist die zentrale Routine pro Fahrzeug. Der vereinfachte Ablauf ist:

  1. Überprüfen, ob das Angebot eine id hat. Andernfalls überspringen.
  2. Angebote überspringen, deren API-Status nicht activated ist oder deren Flag live leer ist.
  3. Nach einem bestehenden Fahrzeug-Post anhand der Listing-ID suchen (find_post_id_by_listing_id()).
  4. Änderungserkennung ausführen (siehe unten). Wenn sich nichts geändert hat, den Heartbeat der letzten Synchronisation über AS24CI\Sync_State::touch() aktualisieren und skipped zurückgeben.
  5. Post-Titel, Auszug und Inhalt erstellen. Wenn der AI Lock (_as24ci_ai_locked = 'yes') aktiv ist, den Post-Auszug oder den Inhalt nicht überschreiben.
  6. Den WordPress-Post mit dem konfigurierten Standard-Post-Status und -Autor einfügen oder aktualisieren.
  7. Abwärtskompatible Postmeta schreiben: _as24ci_listing_id, _as24ci_seller_id und _as24ci_last_modified (sofern von der API bereitgestellt). Der Heartbeat der letzten Synchronisation wird separat über AS24CI\Sync_State::touch() aufgezeichnet (eine dedizierte Tabelle as24ci_sync_state, nicht Postmeta).
  8. Sicherstellen, dass der Slug mit der Listing-ID endet (ensure_slug_has_listing_id()).
  9. Die Angebotsdaten über AS24CI\Mapper::map_listing_to_post() zuordnen, sodass die typisierten Felder in die Tabelle as24_vehicles geschrieben werden.
  10. Ausstattung über Client::get_listing_equipment() abrufen und dem Post über Mapper::map_equipment_to_post() zuordnen. Fehler werden protokolliert, führen aber nicht zum Fehlschlagen des Fahrzeugimports.
  11. Bilder importieren (abhängig von der Option as24ci_import_images und der Begrenzung as24ci_max_images). Der Bildablauf ist im Detail unter Bild-Importer und Warteschlange beschrieben.
  12. _as24ci_content_hash und _as24ci_original_description aktualisieren.
  13. Die Aktion as24ci_vehicle_imported mit der Post-ID, dem rohen API-Angebot und einem Boolean $is_update auslösen.
  14. Einen der Strings inserted, updated, skipped oder error (bei Fehlern in wp_insert_post / wp_update_post) zurückgeben.

Änderungserkennung

Der Importer überspringt Angebote, die sich seit dem vorherigen Durchlauf nicht geändert haben, mithilfe von zwei kaskadierenden Prüfungen:

  • Primär: das von der API zurückgegebene Feld lastModifiedDate. Wenn die lokale Postmeta _as24ci_last_modified mit dem Remote-Wert übereinstimmt, wird das Angebot als unverändert behandelt. Der Importer aktualisiert dennoch den Heartbeat der letzten Synchronisation (AS24CI\Sync_State::touch()) für den Admin-Tab des Importers. Dieser Heartbeat dient rein der Information; die Löschlogik bei der Vollsynchronisation verlässt sich auf die Zugehörigkeit der Listing-ID, nicht auf den Zeitstempel der letzten Synchronisation.
  • Fallback: Wenn lastModifiedDate fehlt, berechnet der Importer einen MD5-Hash der JSON-codierten Nutzdaten und vergleicht ihn mit dem gespeicherten Wert _as24ci_content_hash.

Die Änderungserkennung für Bilder läuft unabhängig und ist in der Dokumentation zum Bild-Importer beschrieben.

AI Lock

Wenn _as24ci_ai_locked auf 'yes' steht, behält der Importer den vorhandenen Inhalt von post_content und post_excerpt bei, sodass KI-generierte Texte einen erneuten Import überstehen. Alle anderen Felder, Taxonomie-Zuweisungen, Ausstattungen und Bilder werden weiterhin aktualisiert. Die ursprüngliche API-Beschreibung wird ebenfalls separat in _as24ci_original_description aufbewahrt.

Stabilität des Slugs

ensure_slug_has_listing_id() aktualisiert den Post-Slug so, dass er immer mit -<listing_id> endet, wenn sich der Slug ändert. Dies hält die URLs über Re-Importe hinweg stabil und vermeidet versehentliche Weiterleitungen bei Titeländerungen.

Massenoperationen

AS24CI\Importer stellt die folgenden übergeordneten Methoden bereit:

  • get_seller_ids() — gibt die bereinigte Liste der konfigurierten Seller-IDs zurück.
  • get_all_preview_listings_for_seller( $seller_id, $max_pages = 20, $page_size = 50 ) — blättert durch die API und gibt den vollständigen Satz aktiver Live-Angebote für einen einzelnen Verkäufer zurück.
  • preview_listings_for_seller( $seller_id, $page = 1, $per_page = 50 ) — paginierte Vorschau, die von der Benutzeroberfläche des Wizards verwendet wird.
  • import_selected_listings( $seller_id, $listing_ids, $max_vehicles = 0 ) — importiert die angegebenen Listing-IDs. Berücksichtigt das Budget $max_vehicles; übersprungene Fahrzeuge verbrauchen kein Budget.
  • import_all_for_seller( $seller_id, $max_vehicles = 0 ) — ruft die vollständige Vorschauliste für eine Garage ab und delegiert an import_selected_listings(). Gibt die Anzahl sowie listing_ids (alle in diesem Durchlauf erfassten IDs) und api_active (Anzahl der von der API zurückgegebenen aktiven Angebote) zurück.
  • full_sync_after_import( array $remote_listing_ids ) — löscht lokale as24ci_car-Posts, deren _as24ci_listing_id nicht im angegebenen Remote-Set enthalten ist. Wird übersprungen, wenn das Remote-Set leer ist, als Schutzmassnahme gegen versehentliches Löschen.
  • upsert_external_listing( array $listing, string $source_id ) — Einstiegspunkt für den Universal-Importer: markiert das Fahrzeug mit der Postmeta _as24ci_source und leitet das im AutoScout24-Format vorliegende Angebot durch denselben Ablauf upsert_post_from_listing(). Gibt inserted, updated, skipped oder error zurück.
  • full_sync_for_source( string $source_id, array $external_ids ) — Vollsynchronisation beschränkt auf eine einzelne Universal-Import-Quelle: entfernt oder hält nur die Fahrzeuge dieser Quelle zurück, die im neuesten Durchlauf fehlen, und rührt dabei niemals AutoScout24-Fahrzeuge oder andere Quellen an. Gibt { kept, held, deleted } zurück; wirkungslos bei leerer Quelle oder ID.
  • hard_delete_listing( $listing_id ) — manuelles, destruktives Löschen für ein einzelnes Angebot; durchläuft dieselbe Bereinigung Vehicle_Deleter wie das native Löschen von WordPress.

Die "All-in-One"-Version des Plugins sieht keine Begrenzung der Angebote vor; get_free_import_limit() und get_free_slots_left() geben PHP_INT_MAX zurück.


Der Universal Importer

Der Universal Importer bringt Nicht-AutoScout24-Bestände in dieselbe Pipeline. Er ist format- und quellenunabhängig: Jede Quellzeile wird zuerst in ein AutoScout24-geformtes $listing-Array umgewandelt und dann in denselben AS24CI\Importer eingespeist, der auch für den API-Import verwendet wird. Dadurch verhalten sich die VIN-Wiedereinstellungs-Erkennung, die Kulanzzeit für Soft-Deletes, die Wertnormalisierung, der Bildimport, die Slug-Stabilität und die Teamzuweisung absolut identisch.

Reader und Format-Dispatch

AS24CI\Import_Reader::read( string $content, string $filename = '' ) liefert eine einheitliche { header, rows }-Struktur und leitet je nach Format an einen formatspezifischen Reader weiter:

FormatReader
CSV / TSV / TXTAS24CI\Import_Csv_Reader
XMLAS24CI\Import_Xml_Reader
XLSXAS24CI\Import_Xlsx_Reader
JSONAS24CI\Import_Json_Reader
ZIPAS24CI\Import_Zip_Reader

Import_Reader::detect_format() ermittelt das Format zuerst anhand der Dateiendung und greift andernfalls auf Content-Sniffing zurück (ZIP-Magic-Bytes – zur Unterscheidung einer Office-.xlsx von einem Daten+Bilder-Paket –, dann ein führendes < für XML oder {/[ für JSON, andernfalls CSV). Die akzeptierten Dateiendungen sind csv, txt, tsv, xml, xlsx, json, zip (Import_Reader::ACCEPTED_EXTENSIONS).

  • Der CSV-Reader normalisiert zuerst die Kodierung auf UTF-8 (siehe unten), erkennt das Trennzeichen (Komma / Semikolon / Tabulator) automatisch und parst mit fgetcsv auf einem Memory-Stream, sodass in Anführungszeichen gesetzte Felder, die das Trennzeichen, Anführungszeichen oder Zeilenumbrüche (mehrzeilige Beschreibungen) enthalten, korrekt gelesen werden.
  • AS24CI\Import_Encoding::to_utf8() konvertiert Exporte aus der DACH-Region (Windows-1252 / ISO-8859, UTF-16/32 mit einem BOM) in sauberes UTF-8. Der XLSX-Reader verwendet dies nicht (sein internes XML ist immer UTF-8).
  • Der ZIP-Reader liest die erste unterstützte Datendatei innerhalb des Archivs, extrahiert gebündelte Bilder in einen as24ci-import/…-Ordner unter wp-content/uploads und schreibt einfache Bilddateinamen in den Zeilen auf die resultierenden öffentlichen URLs um.

Mapping-Vorlage

AS24CI\Import_Template wandelt eine rohe Quellzeile in ein AutoScout24-geformtes Fahrzeuginserat um. Kanonische Feldnamen sind die AutoScout24-Feldnamen (makeKey, price, …), die von AS24CI\Field_Mapping und AS24CI\Mapper verwendet werden. Die Vorlage:

  • ordnet konfigurierte Quellspalten → kanonischen Feldern über field_map zu;
  • normalisiert numerische Felder: INTEGER_FIELDS (entfernt Tausendertrennzeichen wie ., ', Leerzeichen und nachgestellte Einheiten) und FLOAT_FIELDS (akzeptiert ein Dezimalkomma, Dezimalpunkt-Ausgabe);
  • wendet ein feldweises value_maps an (in Kleinbuchstaben umgewandelter Quellwert → kanonischer Wert) und erzwingt erkannte boolesche Felder;
  • erstellt eine stabile id: Garagen-Lagernummer → VIN-<normalised VIN>ROW-<row hash>;
  • teilt die konfigurierte Bildspalte am Bildtrennzeichen auf und wandelt protokollose URLs (z. B. www.example.com/a.jpg) in absolute https:// um;
  • erzwingt status = activated und live = true, damit der nachgelagerte Importer die Zeile nicht überspringt.

Ablauf des Imports

AS24CI\Universal_Importer::run( $content, $template, $source_id, $dry_run = true, $sample_limit = 5, $full_sync = false ):

  1. Parst $content über Import_Reader::read().
  2. Erstellt für jede Zeile ein Fahrzeuginserat über Import_Template::to_listing() und führt eine deterministische Validierung durch (Universal_Importer::validate() – erfordert eine Identität, Marke/Modell/Version, eine plausible VIN, sofern vorhanden, und einen numerischen Preis).
  3. Liefert bei einem Testlauf (Dry Run) eine Vorschau (neu vs. Aktualisierung) zurück, ohne zu schreiben.
  4. Schreibt andernfalls jedes gültige Fahrzeuginserat über Importer::upsert_external_listing( $listing, $source_id ), was das Fahrzeug mit den _as24ci_source-Postmeta versieht und über den gemeinsamen upsert_post_from_listing() leitet. Manuelle/Datei-Importe importieren Bilder immer sofort (nie über die Warteschlange).
  5. Wenn $full_sync auf true steht und eine $source_id gesetzt ist, wird Importer::full_sync_for_source() aufgerufen, um Fahrzeuge DIESER Quelle zu entfernen/zurückzuhalten, die im aktuellen Durchlauf fehlten. Der Full-Sync ist ein Opt-in, da ein manueller Upload oft nur eine Teilmenge des Bestands enthält; er berührt niemals AutoScout24-Fahrzeuge oder andere Quellen.

Benannte Konnektoren

Drei Konnektoren verwenden dieselbe Vorlage + Reader wieder, um nach Zeitplan zu importieren. Jeder speichert eine Einstellungsoption sowie eine verschlüsselte Secret-Option über AS24CI\Secrets:

  • AS24CI\Import_Feed – ruft eine Datei von einer https://-, ftp://-, ftps://- oder sftp://-URL oder einem Server-Dateipfad ab (mit Normalisierung von Dropbox- / Google Drive- / Google Sheets- / OneDrive-Freigabelinks) und verwendet das gespeicherte as24ci_import_csv_template-Mapping wieder.
  • AS24CI\Import_Mail – verbindet sich über IMAP und importiert den am besten passenden Anhang aus der neuesten ungelesenen Nachricht.
  • AS24CI\Import_Carcuro – ruft die öffentliche Bestands-API von carcuro unter Verwendung eines festen, integrierten Feld-Mappings (Import_Carcuro::carcuro_template()) ab, sodass kein manuelles Spalten-Mapping erforderlich ist. Das accident_free von carcuro wird über ein value_map in das kanonische hadAccident-Flag umgekehrt.

Die Konnektoren stellen eine gemeinsame Schnittstelle für register_hooks() / run() / run_now() / execute() / finish() bereit. Für deren Cron-Events siehe Cron-Events und Scheduler; Zugangsdaten werden im Admin-Tab Universal Import (AS24CI\Admin_Tab_Universal_Import) eingegeben, nicht in den Einstellungen.

Fahrzeuglöschung

Jeder dauerhafte Löschpfad läuft über AS24CI\Vehicle_Deleter:

  • Natives "Dauerhaft löschen" von WordPress in der Fahrzeugliste.
  • Vollständige Synchronisierung des Importers (full_sync_after_import()).
  • Massenaktionen (AS24CI\Bulk_Actions).
  • Manuelles Importer::hard_delete_listing().

Der Löschprozess läuft auf before_delete_post / deleted_post und:

  • Entfernt in _as24ci_image_ids nachverfolgte Anhänge.
  • Entfernt die entsprechende Zeile in {$wpdb->prefix}as24_vehicles.
  • Löst die Aktion as24ci_vehicle_deleted aus.

Manuelle Galerie-Anhänge (_as24ci_manual_image_ids) und andere Anhänge, die nicht vom Importer nachverfolgt werden, bleiben absichtlich erhalten.

Öffentliche Hooks

Die Import-Engine löst die folgenden Hooks aus. Überprüfen Sie die Hook-Signaturen in der aktuellen Plugin-Version, bevor Sie sich darauf verlassen.

HookWann er ausgelöst wird
as24ci_vehicle_importedNachdem upsert_post_from_listing() abgeschlossen ist. Argumente: $post_id, $listing, $is_update.
as24ci_vehicle_deletedNachdem ein Fahrzeug und seine nachverfolgten Anhänge über Vehicle_Deleter entfernt wurden.

Das Plugin liest auch den Filter as24ci_webp_quality, wenn Bilder konvertiert werden; siehe die Dokumentation zum Bild-Importer.

Konfigurationsreferenz

OptionAuswirkungStandard
as24ci_seller_idsKommagetrennte Seller-IDs für den Import.(keine)
as24ci_default_post_statusBeitragsstatus für neu eingefügte Fahrzeuge.draft
as24ci_default_post_authorStandard-Autoren-Benutzer-ID für eingefügte Fahrzeuge.(keine → aktueller Benutzer)
as24ci_import_imagesOb Bilder importiert werden sollen.(Umschalter im Adminbereich)
as24ci_max_imagesMaximale Anzahl Bilder pro Fahrzeug. 0 = keine pluginseitige Begrenzung.30
as24ci_full_syncLokale Fahrzeuge löschen, die nach jedem Import in der API fehlen.0
as24ci_cron_image_queueBild-Warteschlange bei Cron-/REST-Läufen verwenden.1
as24ci_cron_max_vehiclesFahrzeugbegrenzung pro Cron-/REST-Lauf. 0 = unbegrenzt.(Scheduler-Standard 50)
as24ci_verbose_loggingEine Zeile pro Fahrzeug- und Bildaktion protokollieren.1
as24ci_mapping_overridesFeldweise Label- und Sichtbarkeits-Overrides, die von der Admin-UI verwendet werden.(leer)

Betriebliche Hinweise

  • Der Importer bricht niemals wegen eines einzelnen fehlerhaften Fahrzeuginserats ab. Fehler von wp_insert_post, wp_update_post, Client::get_listing_equipment und dem Bild-Importer werden über AS24CI\Logger protokolliert und gezählt, brechen den Durchlauf jedoch nicht ab.
  • Dank der Änderungserkennung ist ein vollständiger Re-Import eines unveränderten Katalogs kostengünstig: Die meisten Fahrzeuginserate werden übersprungen und Bild-Downloads werden nicht erneut angefordert.
  • Der Mapper schreibt über das Repository in die Tabelle as24_vehicles, nicht in wp_postmeta, mit Ausnahme des kleinen, abwärtskompatiblen Schlüsselsatzes, der in Datenmodell dokumentiert ist.
  • Der Full-Sync ist ein Opt-in. Wenn as24ci_full_sync aktiviert ist, stellen Sie sicher, dass die konfigurierten Seller-IDs den gesamten Katalog abdecken, den Sie online halten möchten; Fahrzeuge, deren Inserate aus der API verschwinden, werden dauerhaft gelöscht.
  • Die ausführliche Protokollierung (Verbose Logging) erzeugt detaillierte Protokollzeilen und wächst bei grossen Katalogen schnell an. Das Plugin erzwingt eine Protokollbegrenzung von 10 MB mit Rotation; passen Sie die ausführliche Protokollierung an, um Diagnose und Speicherplatzbedarf abzuwägen.

Fehlerbehebung

  • Keine Fahrzeuge importiert. Überprüfen Sie die API-Zugangsdaten, ob as24ci_seller_ids nicht leer ist und ob die API Fahrzeuginserate mit status = activated und live = true zurückgibt. Überprüfen Sie das Plugin-Protokoll auf HTTP-Fehler von AS24CI\Client.
  • Fahrzeuginserate bleiben im Status draft. Das Plugin setzt as24ci_default_post_status standardmässig auf draft, damit Administratoren die Mappings überprüfen können. Ändern Sie die Option auf publish, sobald Sie zufrieden sind, oder veröffentlichen Sie einzelne Fahrzeuge aus der Admin-Liste.
  • Wiederholte Re-Importe aktualisieren immer dieselben Fahrzeuge. Stellen Sie sicher, dass die API einen stabilen lastModifiedDate liefert. Wenn dieser fehlt, erkennt der Fallback-Inhaltshash Änderungen; der Hash ändert sich, wann immer sich der API-Payload aus irgendeinem Grund ändert.
  • Ein Fahrzeug ist nach einem Cron-Lauf verschwunden. Überprüfen Sie, ob as24ci_full_sync aktiviert ist. Bei aktiviertem Full-Sync wird jedes in der API fehlende Fahrzeuginserat dauerhaft gelöscht (einschliesslich seiner importierten Anhänge).
  • Importer ran but no images were downloaded. Überprüfen Sie as24ci_import_images und as24ci_max_images. Bei Cron-/REST-Läufen mit as24ci_cron_image_queue = 1 wird nur das erste Bild sofort heruntergeladen und der Rest an den Worker der Bild-Warteschlange übergeben.
  • Skipping listing_id=… : lastModifiedDate unchanged. Dies ist die erwartete ausführliche Protokollzeile für unveränderte Fahrzeuginserate; sie bestätigt, dass die Änderungserkennung funktioniert.

Verwandte Dokumente