=== MotorHangar Connect ===
Contributors: motorhangar
Tags: car dealer, cars, inventory, vehicles, listings
Requires at least: 6.0
Tested up to: 6.8
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Publish the cars of your WordPress dealer site on MotorHangar and keep them in sync. Works with the fields your theme already uses: Motors, ACF, any custom post type. No WooCommerce needed.

== Description ==

MotorHangar is a free marketplace for car dealers. Most dealer sites built on WordPress do not use WooCommerce: the cars live in a custom post type created by the theme or a plugin (Motors by StylemixThemes, Elementor + JetEngine, ACF-based setups, Kallyas…), and every one stores the make, the price or the photos somewhere different.

So this plugin does not assume a schema. It looks at your site first:

* **"Where are your cars?"** lists your post types with their number of posts. Pick the one with your cars.
* **Discovery:** the plugin inspects your 20 most recent cars and shows every custom field, ACF field and taxonomy they use, with sample values, and spots the image fields (featured image, galleries stored as arrays or comma lists of attachment IDs or URLs).
* **Mapping:** for each MotorHangar field (brand, model, year, version, price, currency, mileage, fuel, transmission, colour, condition, city, description, photos, sold flag) you choose where it comes from: a custom field, an ACF field, a taxonomy (the term, or the parent / child term for make › model trees), the post title, content or excerpt, a fixed value, or "not available on this site".
* **Presets:** start from "Motors (StylemixThemes)", "ACF / custom fields" or "Generic custom post type". A preset only fills the form; rows that point at fields your cars do not have are highlighted.
* **Live preview:** before saving, see the exact payload for 3 of your cars and, for each one, why it would not be sent.

Then it keeps MotorHangar in sync:

* **Realtime:** when you publish or edit a car, its listing is updated within minutes. Unpublishing, trashing or deleting withdraws it. Ticking your theme's "sold" box marks it as sold.
* **Daily reconciliation:** once a day every car is sent again and MotorHangar is told which cars the site still has, so a sale that a missed hook did not report is caught.
* **Safe by design:**
  * Missing data is never invented: a car without a mapped brand, model, year, price, mileage or 3 photos is not sent, and the reason is shown on the car.
  * A field with two values on one car (a car tagged with two makes) is reported as ambiguous; the plugin never picks one.
  * A site that suddenly lists zero cars never marks your listings as sold.
  * If more than 40% of your listings would be marked as sold at once, MotorHangar refuses and the plugin asks you to confirm instead.
* **Background processing:** the API is never called while you save a car. Jobs run through Action Scheduler when another plugin (such as WooCommerce) provides it, or through the plugin's own small queue on WP-Cron.
* **WP-CLI:** `wp motorhangar-connect sync [--dry-run]`, `wp motorhangar-connect status`, `wp motorhangar-connect discover [<post_type>] [--preset=motors]`.

Changes travel one way only: from your site to MotorHangar. Nothing on MotorHangar ever changes your site, and the plugin never writes to your cars' own fields.

= What is sent =

* Values are normalised: "45.000 km" becomes 45000, "S/ 45.900" becomes 45900, "Automático" becomes automatic, "Gasolina" becomes petrol, "Used Cars" becomes used. Mileage is converted to the market's unit when your site uses the other one.
* Photos: the featured image followed by the gallery, full size, without duplicates, up to 10.
* Description: plain text, shortcodes and HTML removed, 2000 characters at most.
* Stock id: the post ID, or a stock-number field if you prefer. The same id always means the same car.

= Presets =

Presets are JSON files in the plugin's `presets/` folder (developers can also add them with the `motorhangar_connect_presets` filter). The Motors preset was checked against the source code of "Motors – Car Dealer, Classifieds & Listing" 1.4.125 (the plugin the Motors theme also runs on): post type `listings`; make, model (`serie`), year (`ca-year`), fuel, transmission, exterior colour and condition as taxonomies; `mileage`, `price` and `sale_price` as custom fields; photos as the featured image plus `gallery` (attachment IDs); `stock_number`; sold as `car_mark_as_sold` = `on` (Motors has no "sold" post status); cars with "Request a price" (`car_price_form` = `on`) are never sent, even if a price is saved, because MotorHangar would show a price you chose to hide. Motors lets each site rename or remove these fields, so still check the discovery table, which shows what your site really stores and highlights preset rows your cars do not have. One thing the preset cannot know: the mileage unit (Motors only stores the number; set "Mileage on this site is in" to match the suffix of your Mileage field).

== External services ==

This plugin connects to the MotorHangar Inventory API (https://motorhangar.com/api/v1) to publish, update, withdraw and mark as sold the cars of your site, and to read your dealer account and your market's vocabulary (currencies, fuels, mileage unit).

It sends, for each car you publish: its stock id, brand, model, year, version, price, currency, mileage, fuel, transmission, colour, condition, city, description and the public URLs of its photos. It sends your API key in the Authorization header of every request. No data about your visitors, customers or users is ever sent.

Data is sent when you save, publish, unpublish, trash or delete a car, once a day for the reconciliation, and when you click "Sync now" or "Test connection". The discovery screen and the preview do not send anything: they only read your own database.

MotorHangar terms of use: https://motorhangar.com/terms/ — privacy policy: https://motorhangar.com/privacy/

== Installation ==

1. Upload the `motorhangar-connect` folder to `/wp-content/plugins/`, or install the zip from Plugins > Add New > Upload.
2. Activate the plugin.
3. In your MotorHangar dealer panel, open API keys (https://motorhangar.com/account/dealer/api/) and create a key (it starts with `mh_`). Copy it: it is shown once.
4. Go to Settings > MotorHangar Connect > "Connection & sync", paste the key, click "Save Changes" and then "Test connection". Choose the market.
5. Open "Where are your cars?", choose your car post type, load a preset if one fits, check the rows against the discovery table and the preview, and click "Save mapping".
6. A full sync starts in the background. Each car shows its status in the list and in the MotorHangar box on its edit screen.

== Frequently Asked Questions ==

= Does it need WooCommerce? =

No. It works with any post type. If WooCommerce (or another plugin that bundles Action Scheduler) is active, its queue is used; otherwise WP-Cron is.

= My theme is not Motors. =

Use "ACF / custom fields" or "Generic custom post type", or map the rows by hand from the discovery table. If your theme stores something the plugin cannot read, `wp motorhangar-connect discover <post_type>` prints the full table: send it to MotorHangar support.

= A car shows "Error". What now? =

Open the car: the MotorHangar box says exactly what is missing, ambiguous or rejected (for example "Brand is empty (taxonomy "make")" or "unknown model"). Brand and model must exist in the MotorHangar catalog.

= Will the plugin mark all my cars as sold if something goes wrong? =

No. If the site lists no car, if any batch could not be sent, or if the change would mark more than 40% of your listings as sold, nothing is marked as sold. In the last case you get a notice in the admin and can confirm it if those cars really were sold.

= I changed the stock number of a car. =

It is published under the new number and the old listing is withdrawn. Emptying the field does not change anything for a car already on MotorHangar.

= WP-Cron is disabled on my site. =

Then a system cron must call `wp-cron.php` (or `wp cron event run --due-now`), otherwise changes wait. The status tab warns about it.

= Where are the logs? =

With WooCommerce active: WooCommerce > Status > Logs, source `motorhangar-connect`. Otherwise the last lines are shown on the "Connection & sync" tab. The API key is never written to the log.

= What happens when I uninstall the plugin? =

Its settings, caches, queued tasks and its own post meta (`_mhc_*`) are deleted. Your cars' data is not touched, and neither are your listings on MotorHangar: withdraw them from the dealer panel if you want them gone.

== Changelog ==

= 1.0.0 =
* First release: discovery screen, field mapping with presets (Motors, ACF, generic), live preview, realtime sync and daily reconciliation (Action Scheduler or WP-Cron), car status box and column, WP-CLI commands.

== Upgrade Notice ==

= 1.0.0 =
First release.
